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 "orpostingiterator.h" |
9 | |
10 | using namespace Baloo; |
11 | |
12 | OrPostingIterator::OrPostingIterator(const QVector<PostingIterator*>& iterators) |
13 | : m_iterators(iterators) |
14 | , m_docId(0) |
15 | , m_nextId(0) |
16 | { |
17 | /* |
18 | * Check for null iterators |
19 | * Preferably, these are not pushed to the list at all, but better be safe |
20 | */ |
21 | m_iterators.removeAll(t: nullptr); |
22 | |
23 | for (PostingIterator* iter : std::as_const(t&: m_iterators)) { |
24 | auto docId = iter->next(); |
25 | // find smallest docId |
26 | if (docId && (docId < m_nextId || m_nextId == 0)) { |
27 | m_nextId = docId; |
28 | } |
29 | } |
30 | } |
31 | |
32 | OrPostingIterator::~OrPostingIterator() |
33 | { |
34 | qDeleteAll(c: m_iterators); |
35 | } |
36 | |
37 | quint64 OrPostingIterator::docId() const |
38 | { |
39 | return m_docId; |
40 | } |
41 | |
42 | quint64 OrPostingIterator::skipTo(quint64 id) |
43 | { |
44 | if (m_docId >= id) { |
45 | return m_docId; |
46 | } |
47 | if (m_nextId == 0) { |
48 | m_docId = m_nextId; |
49 | return 0; |
50 | } |
51 | |
52 | if (id > m_nextId) { |
53 | // Fast forward - move all iterators to the lowest position |
54 | // greater or equal to id |
55 | m_nextId = 0; |
56 | for (PostingIterator* iter : std::as_const(t&: m_iterators)) { |
57 | auto docId = iter->skipTo(docId: id); |
58 | if (docId > 0) { |
59 | if (docId < m_nextId || !m_nextId) { |
60 | m_nextId = docId; |
61 | } |
62 | } |
63 | } |
64 | if (m_nextId == 0) { |
65 | m_docId = m_nextId; |
66 | return 0; |
67 | } |
68 | } |
69 | |
70 | m_docId = m_nextId; |
71 | m_nextId = 0; |
72 | |
73 | // advance all iterators which point to the lowest docId |
74 | for (PostingIterator*& iter : m_iterators) { |
75 | auto docId = iter->docId(); |
76 | if (docId == m_docId) { |
77 | docId = iter->next(); |
78 | } |
79 | |
80 | if (docId == 0) { |
81 | // remove element if iterator has reached the end |
82 | delete iter; |
83 | iter = nullptr; |
84 | } else { |
85 | // check if the docId is the new lowest docId |
86 | if (docId < m_nextId || !m_nextId) { |
87 | m_nextId = docId; |
88 | } |
89 | } |
90 | } |
91 | auto tail = std::remove_if(first: m_iterators.begin(), last: m_iterators.end(), |
92 | pred: [](const PostingIterator* it) { return it == nullptr; }); |
93 | m_iterators.erase(abegin: tail, aend: m_iterators.end()); |
94 | |
95 | return m_docId; |
96 | } |
97 | |
98 | quint64 OrPostingIterator::next() |
99 | { |
100 | if (m_nextId) { |
101 | m_docId = skipTo(id: m_nextId); |
102 | } else { |
103 | m_docId = 0; |
104 | } |
105 | return m_docId; |
106 | } |
107 |