1 | /* |
---|---|
2 | This file is part of the KDE Baloo project. |
3 | SPDX-FileCopyrightText: 2015 Vishesh Handa <vhanda@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.1-or-later |
6 | */ |
7 | |
8 | #include "phraseanditerator.h" |
9 | #include "positioninfo.h" |
10 | |
11 | using namespace Baloo; |
12 | |
13 | PhraseAndIterator::PhraseAndIterator(const QVector<VectorPositionInfoIterator*>& iterators) |
14 | : m_iterators(iterators) |
15 | , m_docId(0) |
16 | { |
17 | if (m_iterators.contains(t: nullptr)) { |
18 | qDeleteAll(c: m_iterators); |
19 | m_iterators.clear(); |
20 | } |
21 | } |
22 | |
23 | PhraseAndIterator::~PhraseAndIterator() |
24 | { |
25 | qDeleteAll(c: m_iterators); |
26 | } |
27 | |
28 | quint64 PhraseAndIterator::docId() const |
29 | { |
30 | return m_docId; |
31 | } |
32 | |
33 | bool PhraseAndIterator::checkIfPositionsMatch() |
34 | { |
35 | using Offset = decltype(m_iterators[0]->positions().size()); |
36 | using Position = std::remove_reference<decltype(m_iterators[0]->positions()[0])>::type; |
37 | |
38 | std::vector<Offset> offsets; |
39 | offsets.resize(new_size: m_iterators.size()); |
40 | |
41 | const auto firstPositions = m_iterators[0]->positions(); |
42 | Position lower_bound = 0; |
43 | |
44 | while (offsets[0] < firstPositions.size()) { |
45 | for (int i = 0; i < m_iterators.size(); i++) { |
46 | const auto positions = m_iterators[i]->positions(); |
47 | Offset off = offsets[i]; |
48 | |
49 | for (; off < positions.size(); ++off) { |
50 | Position pos = positions[off]; |
51 | // Adjust the position. We have a match iff |
52 | // term0 is at pos N, term1 at N+1, term2 at N+2 ... |
53 | if (pos >= (lower_bound + i)) { |
54 | lower_bound = pos - i; |
55 | break; |
56 | } |
57 | } |
58 | if (off >= positions.size()) { |
59 | return false; |
60 | } |
61 | offsets[i] = off; |
62 | } |
63 | |
64 | if (lower_bound == firstPositions[offsets[0]]) { |
65 | // lower_bound has not changed, i.e. all offsets are aligned |
66 | for (int i = 0; i < m_iterators.size(); i++) { |
67 | auto positions = m_iterators[i]->positions(); |
68 | } |
69 | return true; |
70 | } else { |
71 | offsets[0]++; |
72 | } |
73 | } |
74 | return false; |
75 | } |
76 | |
77 | quint64 PhraseAndIterator::skipTo(quint64 id) |
78 | { |
79 | if (m_iterators.isEmpty()) { |
80 | m_docId = 0; |
81 | return 0; |
82 | } |
83 | |
84 | while (true) { |
85 | quint64 lower_bound = id; |
86 | for (PostingIterator* iter : std::as_const(t&: m_iterators)) { |
87 | lower_bound = iter->skipTo(docId: lower_bound); |
88 | |
89 | if (lower_bound == 0) { |
90 | m_docId = 0; |
91 | return 0; |
92 | } |
93 | } |
94 | |
95 | if (lower_bound == id) { |
96 | if (checkIfPositionsMatch()) { |
97 | m_docId = lower_bound; |
98 | return lower_bound; |
99 | } else { |
100 | lower_bound = m_iterators[0]->next(); |
101 | } |
102 | } |
103 | id = lower_bound; |
104 | } |
105 | } |
106 | |
107 | quint64 PhraseAndIterator::next() |
108 | { |
109 | if (m_iterators.isEmpty()) { |
110 | m_docId = 0; |
111 | return 0; |
112 | } |
113 | |
114 | m_docId = m_iterators[0]->next(); |
115 | m_docId = skipTo(id: m_docId); |
116 | |
117 | return m_docId; |
118 | } |
119 |