diff --git a/include/components/config.hpp b/include/components/config.hpp index 3177c7eb..df296740 100644 --- a/include/components/config.hpp +++ b/include/components/config.hpp @@ -129,7 +129,7 @@ class config { } else if (path.find("xrdb:") == 0) { return dereference_xrdb(path.substr(5), value); } else if ((pos = path.find(".")) != string::npos) { - return dereference_local(path.substr(0, pos), path.substr(pos + 1)); + return dereference_local(path.substr(0, pos), path.substr(pos + 1), section); } else { throw value_error("Invalid reference defined at [" + build_path(section, key) + "]"); } @@ -142,13 +142,13 @@ class config { * ${section.key} */ template - T dereference_local(string section, string key) const { + T dereference_local(string section, string key, string current_section) const { if (section == "BAR") m_logger.warn("${BAR.key} is deprecated. Use ${root.key} instead"); - section = string_util::replace(section, "BAR", bar_section()); - section = string_util::replace(section, "root", bar_section()); - section = string_util::replace(section, "self", section); + section = string_util::replace(section, "BAR", bar_section(), 0, 3); + section = string_util::replace(section, "root", bar_section(), 0, 4); + section = string_util::replace(section, "self", current_section, 0, 4); auto path = build_path(section, key); auto result = m_ptree.get_optional(path); diff --git a/include/utils/string.hpp b/include/utils/string.hpp index a7163a1b..ba2b737f 100644 --- a/include/utils/string.hpp +++ b/include/utils/string.hpp @@ -16,8 +16,8 @@ namespace string_util { string upper(const string& s); string lower(const string& s); bool compare(const string& s1, const string& s2); - string replace(const string& haystack, string needle, string replacement); - string replace_all(const string& haystack, string needle, string replacement); + string replace(const string& haystack, string needle, string repl, size_t start = 0, size_t end = string::npos); + string replace_all(const string& haystack, string needle, string repl, size_t start = 0, size_t end = string::npos); string squeeze(const string& haystack, char needle); string strip(const string& haystack, char needle); string strip_trailing_newline(const string& haystack); diff --git a/src/utils/string.cpp b/src/utils/string.cpp index 51ff962e..dbf949cc 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -41,27 +41,40 @@ namespace string_util { /** * Replace first occurence of needle in haystack */ - string replace(const string& haystack, string needle, string replacement) { + string replace(const string& haystack, string needle, string reply, size_t start, size_t end) { string str(haystack); string::size_type pos; - if (needle != replacement && (pos = str.find(needle)) != string::npos) - str = str.replace(pos, needle.length(), replacement); + + if (needle != reply && (pos = str.find(needle, start)) != string::npos) { + if (end == string::npos || pos < end) + str = str.replace(pos, needle.length(), reply); + } + return str; } /** * Replace all occurences of needle in haystack */ - string replace_all(const string& haystack, string needle, string replacement) { + string replace_all(const string& haystack, string needle, string reply, size_t start, size_t end) { string replaced; + + if (end == string::npos) + end = haystack.length(); + for (size_t i = 0; i < haystack.length(); i++) { - if (haystack.compare(i, needle.length(), needle) == 0) { - replaced += replacement; + if (i < start) { + replaced += haystack[i]; + } else if (i + needle.length() > end) { + replaced += haystack[i]; + } else if (haystack.compare(i, needle.length(), needle) == 0) { + replaced += reply; i += needle.length() - 1; } else { replaced += haystack[i]; } } + return replaced; } @@ -70,8 +83,7 @@ namespace string_util { */ string squeeze(const string& haystack, char needle) { string result = haystack; - while (result.find({needle, needle}) != string::npos) - result = replace_all(result, {needle, needle}, {needle}); + while (result.find({needle, needle}) != string::npos) result = replace_all(result, {needle, needle}, {needle}); return result; } diff --git a/tests/unit_tests/utils/string.cpp b/tests/unit_tests/utils/string.cpp index 8bae85c1..0ea92662 100644 --- a/tests/unit_tests/utils/string.cpp +++ b/tests/unit_tests/utils/string.cpp @@ -14,11 +14,21 @@ int main() { expect(!string_util::compare("foo", "bar")); }; - "replace"_test = [] { expect(string_util::replace("Foo bar baz", "a", "x") == "Foo bxr baz"); }; + "replace"_test = [] { + expect(string_util::replace("abc", "b", ".") == "a.c"); + expect(string_util::replace("aaa", "a", ".", 1, 2) == "a.a"); + expect(string_util::replace("aaa", "a", ".", 0, 2) == ".aa"); + expect(string_util::replace("Foo bar baz", "a", "x") == "Foo bxr baz"); + expect(string_util::replace("foooobar", "o", "x", 2, 3) == "foxoobar"); + expect(string_util::replace("foooobar", "o", "x", 0, 1) == "foooobar"); + }; "replace_all"_test = [] { - expect(string_util::replace_all("Foo bar baz", "a", "x") == "Foo bxr bxz"); + expect(string_util::replace_all("Foo bar baza", "a", "x") == "Foo bxr bxzx"); expect(string_util::replace_all("hehehe", "he", "hoo") == "hoohoohoo"); + expect(string_util::replace_all("hehehe", "he", "hoo", 0, 2) == "hoohehe"); + expect(string_util::replace_all("hehehe", "he", "hoo", 4) == "hehehoo"); + expect(string_util::replace_all("hehehe", "he", "hoo", 0, 1) == "hehehe"); expect(string_util::replace_all("131313", "3", "13") == "113113113"); };