app/SearchMatch.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "SearchMatch.h" | ||
| 2 | |||
| 3 | #include "app/SearchQuery.h" | ||
| 4 | #include "data/MailSearchIndex.h" | ||
| 5 | #include <algorithm> | ||
| 6 | |||
| 7 | namespace SearchMatch { | ||
| 8 | |||
| 9 | 232 | QStringList words(const QString &query) { | |
| 10 | 232 | MailCache::SearchFilter filter; | |
| 11 |
1/1✓ Branch 3 → 4 taken 232 times.
|
232 | const QString text = parseSearchQuery(query, filter); |
| 12 | 232 | QStringList result; | |
| 13 |
5/5✓ Branch 7 → 8 taken 232 times.
✓ Branch 8 → 9 taken 232 times.
✓ Branch 9 → 10 taken 232 times.
✓ Branch 39 → 11 taken 130 times.
✓ Branch 39 → 40 taken 232 times.
|
362 | for (QString word : text.split(QLatin1Char(' '), Qt::SkipEmptyParts)) { |
| 14 |
2/3✓ Branch 15 → 16 taken 130 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 130 times.
|
130 | if (word.startsWith(QLatin1Char('-'))) continue; |
| 15 |
1/1✓ Branch 20 → 21 taken 130 times.
|
130 | word.remove(QLatin1Char('"')); |
| 16 |
1/1✓ Branch 21 → 22 taken 130 times.
|
130 | const QString folded = MailSearchIndex::foldForSearch(word); |
| 17 |
6/7✓ Branch 23 → 24 taken 129 times.
✓ Branch 23 → 27 taken 1 time.
✓ Branch 25 → 26 taken 129 times.
✗ Branch 25 → 27 not taken.
✓ Branch 28 → 29 taken 129 times.
✓ Branch 28 → 30 taken 1 time.
✓ Branch 29 → 30 taken 129 times.
|
130 | if (folded.size() >= 2 && !result.contains(folded)) result.append(folded); |
| 18 | 362 | } | |
| 19 | 232 | return result; | |
| 20 | 232 | } | |
| 21 | |||
| 22 | 10972 | QList<QPair<int, int>> spans(const QString &text, const QStringList &foldedWords) { | |
| 23 |
5/6✓ Branch 3 → 4 taken 10909 times.
✓ Branch 3 → 6 taken 63 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 10909 times.
✓ Branch 8 → 9 taken 63 times.
✓ Branch 8 → 10 taken 10909 times.
|
10972 | if (foldedWords.isEmpty() || text.isEmpty()) return {}; |
| 24 | // Fold chunk by chunk (a surrogate pair is one chunk) and remember, for | ||
| 25 | // every folded character, the original chunk it came from. | ||
| 26 | 10909 | QString folded; | |
| 27 | 10909 | QList<int> chunkStart; | |
| 28 | 10909 | QList<int> chunkEnd; | |
| 29 |
2/2✓ Branch 31 → 11 taken 236824 times.
✓ Branch 31 → 32 taken 10909 times.
|
247733 | for (int i = 0; i < text.size();) { |
| 30 |
1/4✗ Branch 13 → 14 not taken.
✓ Branch 13 → 17 taken 236824 times.
✗ Branch 15 → 16 not taken.
✗ Branch 15 → 17 not taken.
|
236824 | const int length = text.at(i).isHighSurrogate() && i + 1 < text.size() ? 2 : 1; |
| 31 |
2/2✓ Branch 18 → 19 taken 236824 times.
✓ Branch 19 → 20 taken 236824 times.
|
236824 | const QString piece = MailSearchIndex::foldForSearch(text.mid(i, length)); |
| 32 |
2/2✓ Branch 26 → 22 taken 236824 times.
✓ Branch 26 → 27 taken 236824 times.
|
473648 | for (int k = 0; k < piece.size(); ++k) { |
| 33 |
1/1✓ Branch 22 → 23 taken 236824 times.
|
236824 | chunkStart.append(i); |
| 34 |
1/1✓ Branch 23 → 24 taken 236824 times.
|
236824 | chunkEnd.append(i + length); |
| 35 | } | ||
| 36 |
1/1✓ Branch 27 → 28 taken 236824 times.
|
236824 | folded += piece; |
| 37 | 236824 | i += length; | |
| 38 | 236824 | } | |
| 39 | 10909 | QList<QPair<int, int>> found; // [start, end) in the original text | |
| 40 |
2/2✓ Branch 47 → 34 taken 11056 times.
✓ Branch 47 → 48 taken 10909 times.
|
21965 | for (const QString &word : foldedWords) { |
| 41 |
3/3✓ Branch 35 → 36 taken 11056 times.
✓ Branch 44 → 37 taken 5549 times.
✓ Branch 44 → 45 taken 11056 times.
|
16605 | for (int at = folded.indexOf(word); at >= 0; at = folded.indexOf(word, at + 1)) |
| 42 |
2/2✓ Branch 41 → 42 taken 5549 times.
✓ Branch 42 → 43 taken 5549 times.
|
5549 | found.append({chunkStart.at(at), chunkEnd.at(at + int(word.size()) - 1)}); |
| 43 | } | ||
| 44 |
3/3✓ Branch 48 → 49 taken 10909 times.
✓ Branch 49 → 50 taken 10909 times.
✓ Branch 50 → 51 taken 10909 times.
|
10909 | std::sort(found.begin(), found.end()); |
| 45 | 10909 | QList<QPair<int, int>> merged; | |
| 46 |
2/2✓ Branch 73 → 54 taken 5549 times.
✓ Branch 73 → 74 taken 10909 times.
|
16458 | for (const auto &range : std::as_const(found)) { |
| 47 |
8/8✓ Branch 56 → 57 taken 14 times.
✓ Branch 56 → 61 taken 5535 times.
✓ Branch 57 → 58 taken 14 times.
✓ Branch 58 → 59 taken 14 times.
✓ Branch 59 → 60 taken 1 time.
✓ Branch 59 → 61 taken 13 times.
✓ Branch 62 → 63 taken 1 time.
✓ Branch 62 → 68 taken 5548 times.
|
5549 | if (!merged.isEmpty() && range.first <= merged.last().first + merged.last().second) |
| 48 |
3/3✓ Branch 63 → 64 taken 1 time.
✓ Branch 64 → 65 taken 1 time.
✓ Branch 66 → 67 taken 1 time.
|
1 | merged.last().second = std::max(merged.last().second, range.second - merged.last().first); |
| 49 | else | ||
| 50 |
1/1✓ Branch 69 → 70 taken 5548 times.
|
5548 | merged.append({range.first, range.second - range.first}); |
| 51 | } | ||
| 52 | 10909 | return merged; | |
| 53 | 10909 | } | |
| 54 | |||
| 55 | 10243 | bool matches(const QString &text, const QStringList &foldedWords) { | |
| 56 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 10242 times.
|
10243 | if (foldedWords.isEmpty()) return false; |
| 57 |
1/1✓ Branch 5 → 6 taken 10242 times.
|
10242 | const QString folded = MailSearchIndex::foldForSearch(text); |
| 58 |
2/2✓ Branch 14 → 8 taken 10242 times.
✓ Branch 14 → 15 taken 207 times.
|
10449 | for (const QString &word : foldedWords) |
| 59 |
3/3✓ Branch 9 → 10 taken 10242 times.
✓ Branch 10 → 11 taken 10035 times.
✓ Branch 10 → 12 taken 207 times.
|
10242 | if (folded.contains(word)) return true; |
| 60 | 207 | return false; | |
| 61 | 10242 | } | |
| 62 | |||
| 63 | 10969 | QString markup(const QString &text, const QStringList &foldedWords, const QString &open, const QString &close) { | |
| 64 | 10969 | QString result; | |
| 65 | 10969 | int done = 0; | |
| 66 |
5/5✓ Branch 2 → 3 taken 10969 times.
✓ Branch 3 → 4 taken 10969 times.
✓ Branch 4 → 5 taken 10969 times.
✓ Branch 25 → 6 taken 5544 times.
✓ Branch 25 → 26 taken 10969 times.
|
16513 | for (const auto &[start, length] : spans(text, foldedWords)) { |
| 67 |
3/3✓ Branch 9 → 10 taken 5544 times.
✓ Branch 10 → 11 taken 5544 times.
✓ Branch 11 → 12 taken 5544 times.
|
5544 | result += text.mid(done, start - done).toHtmlEscaped(); |
| 68 |
5/5✓ Branch 14 → 15 taken 5544 times.
✓ Branch 15 → 16 taken 5544 times.
✓ Branch 16 → 17 taken 5544 times.
✓ Branch 17 → 18 taken 5544 times.
✓ Branch 18 → 19 taken 5544 times.
|
5544 | result += open + text.mid(start, length).toHtmlEscaped() + close; |
| 69 | 5544 | done = start + length; | |
| 70 | 10969 | } | |
| 71 |
3/3✓ Branch 27 → 28 taken 10969 times.
✓ Branch 28 → 29 taken 10969 times.
✓ Branch 29 → 30 taken 10969 times.
|
21938 | return result + text.mid(done).toHtmlEscaped(); |
| 72 | 10969 | } | |
| 73 | |||
| 74 | } // namespace SearchMatch | ||
| 75 |