diff --git a/coding/coding_tests/string_utf8_multilang_tests.cpp b/coding/coding_tests/string_utf8_multilang_tests.cpp index 81a99321e8..c47e220d87 100644 --- a/coding/coding_tests/string_utf8_multilang_tests.cpp +++ b/coding/coding_tests/string_utf8_multilang_tests.cpp @@ -194,3 +194,61 @@ UNIT_TEST(MultilangString_ForEachLanguage) TEST(!s.ForEachLanguage(corruptedLanguages, fn), ()); TEST_EQUAL(testAccumulator.size(), 0, ()); } + +UNIT_TEST(MultilangString_RemoveString) +{ + auto testRemove = [](vector> const & strings, + set const & codesToRemove) { + StringUtf8Multilang str; + for (auto const & s : strings) + str.AddString(s.first, s.second); + + string tmp; + for (auto const & s : strings) + { + TEST(str.HasString(s.first), ()); + TEST(str.GetString(s.first, tmp), ()); + TEST_EQUAL(tmp, s.second, ()); + } + + for (auto c : codesToRemove) + str.RemoveString(c); + + for (auto const & s : strings) + { + if (codesToRemove.find(s.first) == codesToRemove.end()) + { + TEST(str.HasString(s.first), ()); + TEST(str.GetString(s.first, tmp), ()); + TEST_EQUAL(tmp, s.second, ()); + } + else + { + TEST(!str.HasString(s.first), ()); + } + } + + // No extra languages or other data damage. + str.ForEach([&](uint8_t lang, auto const &) { + TEST(base::FindIf(strings, [&lang](auto const & s) { return s.first == lang; }) != + strings.end(), + ()); + TEST(codesToRemove.find(lang) == codesToRemove.end(), ()); + }); + }; + + vector> strings = {{0, "aaa"}, + {1, "bbb"}, + {2, "ccc"}, + {9, "ddd"}, + {17, "eee"}, + {27, "fff"}, + {37, "ggg"}}; + + testRemove(strings, {0}); + testRemove(strings, {1}); + testRemove(strings, {9, 27}); + testRemove(strings, {37}); + testRemove(strings, {0, 1, 2, 9, 17, 27, 37}); + testRemove(strings, {39}); +} diff --git a/coding/string_utf8_multilang.cpp b/coding/string_utf8_multilang.cpp index 2fe62d281e..51d22c4d2c 100644 --- a/coding/string_utf8_multilang.cpp +++ b/coding/string_utf8_multilang.cpp @@ -207,6 +207,25 @@ void StringUtf8Multilang::AddString(int8_t lang, string const & utf8s) m_s.insert(m_s.end(), utf8s.begin(), utf8s.end()); } +void StringUtf8Multilang::RemoveString(int8_t lang) +{ + size_t i = 0; + size_t const sz = m_s.size(); + + while (i < sz) + { + size_t const next = GetNextIndex(i); + + if ((m_s[i] & 0x3F) == lang) + { + m_s.erase(i, next - i); + return; + } + + i = next; + } +} + bool StringUtf8Multilang::GetString(int8_t lang, string & utf8s) const { if (!IsSupportedLangCode(lang)) diff --git a/coding/string_utf8_multilang.hpp b/coding/string_utf8_multilang.hpp index 46c79f617a..7f84cab87e 100644 --- a/coding/string_utf8_multilang.hpp +++ b/coding/string_utf8_multilang.hpp @@ -120,6 +120,14 @@ public: AddString(l, utf8s); } + void RemoveString(int8_t lang); + void RemoveString(std::string const & lang) + { + int8_t const l = GetLangIndex(lang); + if (l >= 0) + RemoveString(l); + } + // Calls |fn| for each pair of |lang| and |utf8s| stored in this multilang string. template void ForEach(Fn && fn) const