diff --git a/plugins/include/string.inc b/plugins/include/string.inc index 565451e0..01ad9d52 100755 --- a/plugins/include/string.inc +++ b/plugins/include/string.inc @@ -20,7 +20,7 @@ native contain(const source[],const string[]); native containi(const source[],const string[]); /* Replaces given string to another in given text. */ -native replace(text[],len,const what[],const with[]); +native replace(text[], len, const what[], const with[]); /* Adds one string to another. Last parameter different from 0, specifies * how many chars we want to add. Function returns number of all merged chars. */ @@ -215,19 +215,50 @@ stock remove_filepath(szFilePath[], szFile[], pMax) return; } -/* Replaces a contained string - By jtp10181 -*/ +/* Replaces a contained string iteratively. + * This ensures that no infinite replacements will take place by + * intelligently moving to the next string position each iteration. + */ stock replace_all(string[], len, what[], with[]) { - new withlen, charnum = 0; - new total = 0; + new pos = 0; - withlen = strlen(with); - - while (replace(string[charnum], len, what, with) != 0) + if ((pos = contain(string, what)) == -1) { - charnum += contain(string[charnum], what) + withlen; + return 0; + } + + new total = 0; + new with_len = strlen(with); + new diff = strlen(what) - with_len; + new total_len = strlen(string); + new temp_pos = 0 + + while (replace(string[pos], len, what, with) != 0) + { + /* jump to position after replacement */ + pos += with_len; + + /* update cached length of string */ + total_len -= diff; + + /* will the next call be operating on the last character? */ + if (pos >= total_len) + { + break; + } + + /* find the next position from our offset */ + temp_pos = contain(string[pos], what); + + /* if it's invalid, we're done */ + if (temp_pos == -1) + { + break; + } + + /* otherwise, reposition and update counters */ + pos += temp_pos; total++; } diff --git a/plugins/testsuite/fmttest.sma b/plugins/testsuite/fmttest.sma index e0a15f79..28d98935 100644 --- a/plugins/testsuite/fmttest.sma +++ b/plugins/testsuite/fmttest.sma @@ -8,6 +8,14 @@ public plugin_init() register_srvcmd("test_replace", "Command_TestReplace") } +public gabprint(const fmt[], ...) +{ + static buffer[2048] + vformat(buffer, 2047, fmt, 2) + + server_print("%s", buffer) +} + public Command_TestFormat() { server_print("Printing -1 with d: %d", -1) @@ -22,9 +30,29 @@ public Command_TestReplace() { new message[192] = "^"@test^"" - server_print("orig message: %s", message) - replace_all(message, 191, "^"", "") + server_print("Got: %s (expected: %s)", message, "@test") - server_print("new message: %s", message) + copy(message, 191, "test") + replace_all(message, 191, "t", "tt") + server_print("Got: %s (expected: %s)", message, "ttestt") + + replace_all(message, 191, "tt", "") + server_print("Got: %s (expected: %s)", message, "es") + + copy(message, 191, "good boys do fine always") + replace_all(message, 191, " ", "-----") + server_print("Got %s (expected: %s)", message, "good-----boys-----do-----fine-----always") + + copy(message, 191, "-----") + replace_all(message, 191, "-", "") + server_print("Got ^"%s%^" (expected: ^"%s%^")", message, "") + + copy(message, 191, "-----") + replace_all(message, 191, "--", "") + server_print("Got ^"%s%^" (expected: ^"%s%^")", message, "-") + + copy(message, 191, "aaaa") + replace_all(message, 191, "a", "Aaa") + server_print("Got %s (expected: %s)", message, "AaaAaaAaaAaa") }