From 37fb296e722ecb0ca1c69bfd111ab4338f8fcd6d Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 23 Mar 2015 15:19:42 +0100 Subject: FileSearch: Move FileIterator to std iterator semantics. We need this when we want to use QtConcurrent::mappedReduced. Change-Id: I4a6a31f4a0cc9a739a263cc148a1d51d7aa5d418 Reviewed-by: David Schulz --- src/libs/utils/filesearch.cpp | 124 ++++++++++++++++++++++++++---------------- src/libs/utils/filesearch.h | 100 ++++++++++++++++++++++++++-------- 2 files changed, 156 insertions(+), 68 deletions(-) (limited to 'src/libs') diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp index 0219f73d10..a6faf567be 100644 --- a/src/libs/utils/filesearch.cpp +++ b/src/libs/utils/filesearch.cpp @@ -246,8 +246,9 @@ void runFileSearch(QFutureInterface &future, QString str; QTextStream stream; FileSearchResultList results; - while (files->hasNext()) { - const QString &filePath = files->next(); + auto end = files->end(); + for (auto it = files->begin(); it != end; ++it) { + const QString &filePath = it->filePath; if (future.isPaused()) future.waitForResume(); if (future.isCanceled()) { @@ -267,7 +268,7 @@ void runFileSearch(QFutureInterface &future, continue; needsToCloseFile = true; stream.setDevice(&file); - stream.setCodec(files->encoding()); + stream.setCodec(it->encoding); } const FileSearchResultList singleFileResults = searchFunction(filePath, stream); @@ -420,9 +421,8 @@ QString matchCaseReplacement(const QString &originalText, const QString &replace return replaceText; // mixed } } -} -QString Utils::matchCaseReplacement(const QString &originalText, const QString &replaceText) +QString matchCaseReplacement(const QString &originalText, const QString &replaceText) { if (originalText.isEmpty()) return replaceText; @@ -451,55 +451,83 @@ QString Utils::matchCaseReplacement(const QString &originalText, const QString & // #pragma mark -- FileIterator -FileIterator::FileIterator() - : m_list(QStringList()), - m_iterator(0), - m_index(-1) +void FileIterator::next(FileIterator::const_iterator *it) +{ + if (it->m_index < 0) // == end + return; + ++it->m_index; + update(it->m_index); + if (it->m_index < currentFileCount()) { + it->m_item.filePath = fileAt(it->m_index); + it->m_item.encoding = codecAt(it->m_index); + } else { + it->m_index = -1; // == end + it->m_item.filePath.clear(); + it->m_item.encoding = 0; + } +} + +FileIterator::const_iterator FileIterator::begin() { + update(0); + if (currentFileCount() == 0) + return end(); + return FileIterator::const_iterator(this, + FileIterator::Item(fileAt(0), codecAt(0)), + 0/*index*/); } -FileIterator::FileIterator(const QStringList &fileList, - const QList encodings) - : m_list(fileList), - m_iterator(new QStringListIterator(m_list)), +FileIterator::const_iterator FileIterator::end() +{ + return FileIterator::const_iterator(this, FileIterator::Item(QString(), 0), + -1/*end*/); +} + +// #pragma mark -- FileListIterator + +FileListIterator::FileListIterator(const QStringList &fileList, + const QList encodings) + : m_files(fileList), m_encodings(encodings), - m_index(-1) + m_maxIndex(-1) +{ +} + +void FileListIterator::update(int requestedIndex) { + if (requestedIndex > m_maxIndex) + m_maxIndex = requestedIndex; } -FileIterator::~FileIterator() +int FileListIterator::currentFileCount() const { - if (m_iterator) - delete m_iterator; + return m_files.size(); } -bool FileIterator::hasNext() const +QString FileListIterator::fileAt(int index) const { - Q_ASSERT(m_iterator); - return m_iterator->hasNext(); + return m_files.at(index); } -QString FileIterator::next() +QTextCodec *FileListIterator::codecAt(int index) const { - Q_ASSERT(m_iterator); - ++m_index; - return m_iterator->next(); + return m_encodings.at(index); } -int FileIterator::maxProgress() const +int FileListIterator::maxProgress() const { - return m_list.size(); + return m_files.size(); } -int FileIterator::currentProgress() const +int FileListIterator::currentProgress() const { - return m_index + 1; + return m_maxIndex + 1; } -QTextCodec * FileIterator::encoding() const +QTextCodec *FileListIterator::encodingAt(int index) const { - if (m_index >= 0 && m_index < m_encodings.size()) - return m_encodings.at(m_index); + if (index >= 0 && index < m_encodings.size()) + return m_encodings.at(index); return QTextCodec::codecForLocale(); } @@ -524,11 +552,12 @@ SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QSt } } -bool SubDirFileIterator::hasNext() const +void SubDirFileIterator::update(int index) { - if (!m_currentFiles.isEmpty()) - return true; - while (!m_dirs.isEmpty() && m_currentFiles.isEmpty()) { + if (index < m_files.size()) + return; + // collect files from the directories until we have enough for the given index + while (!m_dirs.isEmpty() && index >= m_files.size()) { QDir dir = m_dirs.pop(); const qreal dirProgressMax = m_progressValues.pop(); const bool processed = m_processedValues.pop(); @@ -543,7 +572,7 @@ bool SubDirFileIterator::hasNext() const it.toBack(); while (it.hasPrevious()) { const QString &file = it.previous(); - m_currentFiles.append(dir.path()+ QLatin1Char('/') +file); + m_files.append(dir.path()+ QLatin1Char('/') +file); } m_progress += dirProgressMax; } else { @@ -564,18 +593,24 @@ bool SubDirFileIterator::hasNext() const m_progress += dirProgressMax; } } - if (m_currentFiles.isEmpty()) { + if (index >= m_files.size()) m_progress = MAX_PROGRESS; - return false; - } +} - return true; +int SubDirFileIterator::currentFileCount() const +{ + return m_files.size(); } -QString SubDirFileIterator::next() +QString SubDirFileIterator::fileAt(int index) const { - Q_ASSERT(!m_currentFiles.isEmpty()); - return m_currentFiles.takeFirst(); + return m_files.at(index); +} + +QTextCodec *SubDirFileIterator::codecAt(int index) const +{ + Q_UNUSED(index) + return m_encoding; } int SubDirFileIterator::maxProgress() const @@ -588,7 +623,4 @@ int SubDirFileIterator::currentProgress() const return qMin(qRound(m_progress), MAX_PROGRESS); } -QTextCodec * SubDirFileIterator::encoding() const -{ - return m_encoding; } diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h index e77c4887fd..bf827d0c27 100644 --- a/src/libs/utils/filesearch.h +++ b/src/libs/utils/filesearch.h @@ -46,24 +46,77 @@ namespace Utils { class QTCREATOR_UTILS_EXPORT FileIterator { public: - explicit FileIterator(const QStringList &fileList, - const QList encodings); - virtual ~FileIterator(); + class Item + { + public: + Item(const QString &path, QTextCodec *codec) + : filePath(path), encoding(codec) + {} + QString filePath; + QTextCodec *encoding; + }; + + class const_iterator + { + public: + typedef std::forward_iterator_tag iterator_category; + typedef Item value_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type *pointer; + typedef const value_type &reference; + + const_iterator(FileIterator *parent, Item item, int id) + : m_parent(parent), m_item(item), m_index(id) + {} + const Item operator*() const { return m_item; } + const Item *operator->() const { return &m_item; } + void operator++() { m_parent->next(this); } + bool operator==(const const_iterator &other) const + { + return m_parent == other.m_parent && m_index == other.m_index; + } + bool operator!=(const const_iterator &other) const { return !operator==(other); } + + FileIterator *m_parent; + Item m_item; + int m_index; // -1 == end + }; + + virtual ~FileIterator() {} + void next(const_iterator *it); + const_iterator begin(); + const_iterator end(); + + virtual int maxProgress() const = 0; + virtual int currentProgress() const = 0; + +protected: + virtual void update(int requestedIndex) = 0; + virtual int currentFileCount() const = 0; + virtual QString fileAt(int index) const = 0; + virtual QTextCodec *codecAt(int index) const = 0; +}; - virtual bool hasNext() const; - virtual QString next(); - virtual QTextCodec *encoding() const; - virtual int maxProgress() const; - virtual int currentProgress() const; +class QTCREATOR_UTILS_EXPORT FileListIterator : public FileIterator +{ +public: + explicit FileListIterator(const QStringList &fileList, + const QList encodings); + + int maxProgress() const override; + int currentProgress() const override; protected: - FileIterator(); + void update(int requestedIndex) override; + int currentFileCount() const override; + QString fileAt(int index) const override; + QTextCodec *codecAt(int index) const override; private: - QStringList m_list; - QStringListIterator *m_iterator; + QTextCodec *encodingAt(int index) const; + QStringList m_files; QList m_encodings; - int m_index; + int m_maxIndex; }; class QTCREATOR_UTILS_EXPORT SubDirFileIterator : public FileIterator @@ -72,20 +125,23 @@ public: SubDirFileIterator(const QStringList &directories, const QStringList &filters, QTextCodec *encoding = 0); - bool hasNext() const; - QString next(); - QTextCodec *encoding() const; - int maxProgress() const; - int currentProgress() const; + int maxProgress() const override; + int currentProgress() const override; + +protected: + void update(int requestedIndex) override; + int currentFileCount() const override; + QString fileAt(int index) const override; + QTextCodec *codecAt(int index) const override; private: QStringList m_filters; QTextCodec *m_encoding; - mutable QStack m_dirs; - mutable QStack m_progressValues; - mutable QStack m_processedValues; - mutable qreal m_progress; - mutable QStringList m_currentFiles; + QStack m_dirs; + QStack m_progressValues; + QStack m_processedValues; + qreal m_progress; + QStringList m_files; }; class QTCREATOR_UTILS_EXPORT FileSearchResult -- cgit v1.2.1