From 3c55d4fde4430696507a49249b3fb1f2ba318f3c Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Mon, 27 Jul 2015 09:46:28 -0700 Subject: [PATCH] Fix incorrect results for non-regex skip tags searches Closes #1865. --- libaegisub/common/util.cpp | 10 ++++----- tests/tests/ifind.cpp | 43 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/libaegisub/common/util.cpp b/libaegisub/common/util.cpp index a2f349521..e92d14776 100644 --- a/libaegisub/common/util.cpp +++ b/libaegisub/common/util.cpp @@ -61,7 +61,7 @@ void parse_blocks(std::vector>& blocks, std::string co if (c == '{' && ovr_start == bad_pos) ovr_start = i; else if (c == '}' && ovr_start != bad_pos) { - blocks.emplace_back(ovr_start, i); + blocks.emplace_back(ovr_start, i + 1); ovr_start = bad_pos; } ++i; @@ -152,10 +152,10 @@ std::string tagless_find_helper::strip_tags(std::string const& str, size_t s) { size_t last = s; for (auto const& block : blocks) { - if (block.second < s) continue; + if (block.second <= s) continue; if (block.first > last) out.append(str.begin() + last, str.begin() + block.first); - last = block.second + 1; + last = block.second; } if (last < str.size()) @@ -178,7 +178,7 @@ void tagless_find_helper::map_range(size_t &s, size_t &e) { // < should only happen if the cursor was within an override block // when the user started a search if (block.first <= s) { - size_t len = block.second - std::max(block.first, s) + 1; + size_t len = block.second - std::max(block.first, start); s += len; e += len; continue; @@ -190,7 +190,7 @@ void tagless_find_helper::map_range(size_t &s, size_t &e) { // Extend the match to include blocks within the match // Note that blocks cannot be partially within the match - e += block.second - block.first + 1; + e += block.second - block.first; } } } // namespace util diff --git a/tests/tests/ifind.cpp b/tests/tests/ifind.cpp index 2b2e7acd0..541089627 100644 --- a/tests/tests/ifind.cpp +++ b/tests/tests/ifind.cpp @@ -73,3 +73,46 @@ TEST(lagi_ifind, correct_index_with_shrunk_character_before_match) { // U+FB00 turns into "ff", which is one byte shorter in UTF-8 EXPECT_IFIND(" \xEF\xAC\x80 a ", "a", 5, 6); } + +TEST(lagi_skip_tags, tag_stripping) { + agi::util::tagless_find_helper helper; + + EXPECT_EQ("", helper.strip_tags("", 0)); + EXPECT_EQ("", helper.strip_tags("{}", 0)); + EXPECT_EQ("abc", helper.strip_tags("{}abc", 0)); + EXPECT_EQ("abc", helper.strip_tags("a{}bc", 0)); + EXPECT_EQ("abc", helper.strip_tags("abc{}", 0)); + EXPECT_EQ("abc", helper.strip_tags("{}a{}bc{}", 0)); + + EXPECT_EQ("abc", helper.strip_tags("{}abc", 1)); + EXPECT_EQ("abc", helper.strip_tags("{}abc", 2)); + EXPECT_EQ("bc", helper.strip_tags("{}abc", 3)); + EXPECT_EQ("c", helper.strip_tags("{}abc", 4)); +} + +static void test_range_map(const char *str, size_t start, size_t& s, size_t& e) { + agi::util::tagless_find_helper helper; + helper.strip_tags(str, start); + helper.map_range(s, e); +} + +#define EXPECT_RANGE(str, start, match_start, match_end, result_start, result_end) \ + do { \ + size_t s = match_start, e = match_end; \ + test_range_map(str, start, s, e); \ + EXPECT_EQ(result_start, s); \ + EXPECT_EQ(result_end, e); \ + } while (0) + +TEST(lagi_skip_tags, range_mapping) { + EXPECT_RANGE("", 0, 0, 0, 0, 0); + EXPECT_RANGE("a", 0, 0, 1, 0, 1); + EXPECT_RANGE("{}a", 0, 0, 1, 2, 3); + EXPECT_RANGE("{cc}ab", 0, 1, 2, 5, 6); + EXPECT_RANGE("{cc}ab{cc}b", 0, 1, 2, 5, 6); + EXPECT_RANGE("{cc}ab{cc}b", 0, 1, 3, 5, 11); + + EXPECT_RANGE("{cc}ab{cc}b", 3, 1, 3, 5, 11); + EXPECT_RANGE("{cc}ab{cc}b", 4, 1, 3, 5, 11); + EXPECT_RANGE("{cc}ab{cc}b", 5, 0, 2, 5, 11); +}