File indexing completed on 2024-04-14 03:49:41

0001 /*
0002     This file is part of the KDE Baloo project.
0003     SPDX-FileCopyrightText: 2015 Vishesh Handa <vhanda@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 #include "orpostingiterator.h"
0009 
0010 using namespace Baloo;
0011 
0012 OrPostingIterator::OrPostingIterator(const QVector<PostingIterator*>& iterators)
0013     : m_iterators(iterators)
0014     , m_docId(0)
0015     , m_nextId(0)
0016 {
0017     /*
0018      * Check for null iterators
0019      * Preferably, these are not pushed to the list at all, but better be safe
0020      */
0021     m_iterators.removeAll(nullptr);
0022 
0023     for (PostingIterator* iter : std::as_const(m_iterators)) {
0024         auto docId = iter->next();
0025         // find smallest docId
0026         if (docId && (docId < m_nextId || m_nextId == 0)) {
0027             m_nextId = docId;
0028         }
0029     }
0030 }
0031 
0032 OrPostingIterator::~OrPostingIterator()
0033 {
0034     qDeleteAll(m_iterators);
0035 }
0036 
0037 quint64 OrPostingIterator::docId() const
0038 {
0039     return m_docId;
0040 }
0041 
0042 quint64 OrPostingIterator::skipTo(quint64 id)
0043 {
0044     if (m_docId >= id) {
0045         return m_docId;
0046     }
0047     if (m_nextId == 0) {
0048         m_docId = m_nextId;
0049         return 0;
0050     }
0051 
0052     if (id > m_nextId) {
0053         // Fast forward - move all iterators to the lowest position
0054         // greater or equal to id
0055         m_nextId = 0;
0056         for (PostingIterator* iter : std::as_const(m_iterators)) {
0057             auto docId = iter->skipTo(id);
0058             if (docId > 0) {
0059                 if (docId < m_nextId || !m_nextId) {
0060                     m_nextId = docId;
0061                 }
0062             }
0063         }
0064         if (m_nextId == 0) {
0065             m_docId = m_nextId;
0066             return 0;
0067         }
0068     }
0069 
0070     m_docId = m_nextId;
0071     m_nextId = 0;
0072 
0073     // advance all iterators which point to the lowest docId
0074     for (PostingIterator*& iter : m_iterators) {
0075         auto docId = iter->docId();
0076         if (docId == m_docId) {
0077             docId = iter->next();
0078         }
0079 
0080         if (docId == 0) {
0081             // remove element if iterator has reached the end
0082             delete iter;
0083             iter = nullptr;
0084         } else {
0085             // check if the docId is the new lowest docId
0086             if (docId < m_nextId || !m_nextId) {
0087                 m_nextId = docId;
0088             }
0089         }
0090     }
0091     auto tail = std::remove_if(m_iterators.begin(), m_iterators.end(),
0092         [](const PostingIterator* it) { return it == nullptr; });
0093     m_iterators.erase(tail, m_iterators.end());
0094 
0095     return m_docId;
0096 }
0097 
0098 quint64 OrPostingIterator::next()
0099 {
0100     if (m_nextId) {
0101         m_docId = skipTo(m_nextId);
0102     } else {
0103         m_docId = 0;
0104     }
0105     return m_docId;
0106 }