From 4dc07c3bd28f9fa9f0afb8c1ad1873d82cb38d19 Mon Sep 17 00:00:00 2001 From: hama Date: Sat, 19 Sep 2015 02:25:04 +0200 Subject: [PATCH] ReFileSystem + ReMatcher --- base/ReMatcher.cpp | 198 ++++++++++++++++++++++++++++++++++++--- base/ReMatcher.hpp | 28 +++++- cunit/allTests.cpp | 2 + cunit/cuReFileSystem.cpp | 36 +++++-- os/ReFileSystem.cpp | 94 ++++++++++++++----- os/ReFileSystem.hpp | 17 ++-- 6 files changed, 320 insertions(+), 55 deletions(-) diff --git a/base/ReMatcher.cpp b/base/ReMatcher.cpp index 3b9a5a9..2d86b27 100644 --- a/base/ReMatcher.cpp +++ b/base/ReMatcher.cpp @@ -20,6 +20,8 @@ */ #include "base/rebase.hpp" +QStringList* ReListMatcher::m_allMatchingList = NULL; +ReListMatcher* ReListMatcher::m_allMatcher = NULL; /** * Constructor. @@ -38,7 +40,7 @@ ReMatcher::ReMatcher(const QString& pattern, Qt::CaseSensitivity caseSensivity, m_restLengths(), m_anchored(anchored), m_caseSensivitiy(caseSensivity) { - setPattern(pattern); + setPattern(pattern, anchored); } /** @@ -71,13 +73,20 @@ bool ReMatcher::matches(const QString& text) { * Sets the search pattern. * * @param pattern the search pattern, with wildcards '*' (any string) + * @param anchored true: the pattern must match at the begin
+ * false: the pattern can match anywhere */ -void ReMatcher::setPattern(const QString& pattern) { +void ReMatcher::setPattern(const QString& pattern, bool anchored) { + m_anchored = anchored; + m_allMatching = false; if (pattern.isEmpty()) m_needles.clear(); else { - if (pattern.startsWith("*")) + if (pattern.startsWith("*")){ m_anchored = false; + if (pattern.length() == 1) + m_allMatching = true; + } m_needles = pattern.split('*'); // Eliminate empty entries: for (int ix = m_needles.size() - 1; ix >= 0; ix--) { @@ -94,6 +103,36 @@ void ReMatcher::setPattern(const QString& pattern) { } } } +/** + * Returns whether the matcher accepts all strings (pattern "*"). + * + * @return true: the matcher accepts all strings + */ +bool ReMatcher::allMatching() const +{ + return m_allMatching; +} + +/** + * Returns the case sensitivity of the pattern matching. + * + * @return true: the character case is relevant + */ +Qt::CaseSensitivity ReMatcher::caseSensivitiy() const +{ + return m_caseSensivitiy; +} + +/** + * Sets the case sensisitivy of the pattern matching. + * + * @param caseSensivitiy true: the character case is relevant + */ +void ReMatcher::setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy) +{ + m_caseSensivitiy = caseSensivitiy; +} + /** * Constructor. @@ -106,15 +145,13 @@ void ReMatcher::setPattern(const QString& pattern) { * the string */ ReListMatcher::ReListMatcher(const QStringList& patterns, - Qt::CaseSensitivity caseSensitivty, bool anchored) : + Qt::CaseSensitivity caseSensivity, bool anchored) : + m_patterns(patterns), m_list(), - m_empty(false) + m_empty(false), + m_allMatching(false) { - QStringList::const_iterator it; - for (it = patterns.constBegin(); it != patterns.cend(); ++it){ - m_list.append(new ReMatcher(*it, caseSensitivty, anchored)); - m_empty = true; - } + setPatterns(patterns, caseSensivity, anchored); } /** * Destructor. @@ -122,6 +159,40 @@ ReListMatcher::ReListMatcher(const QStringList& patterns, ReListMatcher::~ReListMatcher(){ destroy(); } + +/** + * Returns whether the search finds all (pattern "*"). + * + * @return true: the matcher accept all strings + */ +bool ReListMatcher::allMatching() const +{ + return m_allMatching; +} + +/** + * Returns a string list with one entry "*". + * + * @return a + */ +const QStringList& ReListMatcher::allMatchingList() +{ + if (m_allMatchingList == NULL){ + m_allMatchingList = new QStringList(); + m_allMatchingList->append("*"); + } + return *m_allMatchingList; +} + +/** + * Returns the case sensitivity of the pattern matching. + * + * @return true: the character case is relevant + */ +Qt::CaseSensitivity ReListMatcher::caseSensivitiy() const +{ + return m_list.at(0)->caseSensivitiy(); +} /** * Frees the resources. */ @@ -133,6 +204,30 @@ void ReListMatcher::destroy(){ m_list.clear(); } +/** + * Returns a pattern match processor accepting all strings. + * + * @return a matcher accepting all strings + */ +const ReListMatcher& ReListMatcher::allMatcher() +{ + if (m_allMatcher == NULL){ + m_allMatcher = new ReListMatcher(allMatchingList()); + } + return *m_allMatcher; +} + + +/** + * Returns the current pattern list. + * + * @return the pattern list + */ +const QStringList& ReListMatcher::patterns() const +{ + return m_patterns; +} + /** * Returns whether the pattern list is empty. * @@ -159,6 +254,43 @@ bool ReListMatcher::matches(const QString& text) return rc; } +/** + * Sets the case sensisitivy of the pattern matching. + * + * @param caseSensivitiy true: the character case is relevant + */ +void ReListMatcher::setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy) +{ + QList::const_iterator it; + for (it = m_list.begin(); it != m_list.end(); ++it){ + (*it)->setCaseSensivitiy(caseSensivitiy); + } +} + +/** + * Sets a new pattern list. + * + * @param patterns the patterns to search + * @param anchored true: the pattern must match the string's start
+ * false: the pattern can match anywhere + */ +void ReListMatcher::setPatterns(const QStringList& patterns, + Qt::CaseSensitivity caseSensivity, bool anchored) +{ + destroy(); + m_patterns = patterns; + m_empty = true; + m_allMatching = false; + QStringList::const_iterator it; + for (it = patterns.constBegin(); it != patterns.cend(); ++it){ + ReMatcher* matcher = new ReMatcher(*it, caseSensivity, anchored); + m_list.append(matcher); + if (matcher->allMatching()) + m_allMatching = true; + m_empty = false; + } +} + /** * Constructor. @@ -172,11 +304,39 @@ bool ReListMatcher::matches(const QString& text) * the string */ ReIncludeExcludeMatcher::ReIncludeExcludeMatcher(const QStringList& includes, - const QStringList& excludes, Qt::CaseSensitivity caseSensitivty, + const QStringList& excludes, Qt::CaseSensitivity caseSensivity, bool anchored) : - m_includes(includes, caseSensitivty, anchored), - m_excludes(excludes, caseSensitivty, anchored) + m_includes(includes, caseSensivity, anchored), + m_excludes(excludes, caseSensivity, anchored) +{ +} + +/** + * Returns the case sensitivity of the pattern matching. + * + * @return true: the character case is relevant + */ +Qt::CaseSensitivity ReIncludeExcludeMatcher::caseSensivitiy() const +{ + return m_includes.caseSensivitiy(); +} + +/** + * Returns the exclude matcher. + * @return the exclude matcher + */ +const ReListMatcher& ReIncludeExcludeMatcher::excludes() const { + return m_excludes; +} + +/** + * Returns the include matcher. + * @return the include matcher + */ +const ReListMatcher& ReIncludeExcludeMatcher::includes() const +{ + return m_includes; } /** @@ -195,3 +355,15 @@ bool ReIncludeExcludeMatcher::matches(const QString& text, bool excludeToo) rc = ! m_excludes.matches(text); return rc; } + +/** + * Sets the case sensitivity of the pattern matching. + * + * @param caseSensivitiy true: the character case is relevant + */ +void ReIncludeExcludeMatcher::setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy) +{ + m_includes.setCaseSensivitiy(caseSensivitiy); + m_excludes.setCaseSensivitiy(caseSensivitiy); +} + diff --git a/base/ReMatcher.hpp b/base/ReMatcher.hpp index c5eb9b7..3ba8e8f 100644 --- a/base/ReMatcher.hpp +++ b/base/ReMatcher.hpp @@ -23,14 +23,19 @@ public: ReMatcher(const QString& pattern, Qt::CaseSensitivity caseSensitivty = Qt::CaseSensitive, bool anchored = false); public: + bool allMatching() const; + Qt::CaseSensitivity caseSensivitiy() const; bool matches(const QString& text); - void setPattern(const QString& pattern); + void setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy); + void setPattern(const QString& pattern, bool anchored = false); + protected: QStringList m_needles; // m_restLengths[ix] = sum(m_needles[ix..last].size() QList m_restLengths; bool m_anchored; Qt::CaseSensitivity m_caseSensivitiy; + bool m_allMatching; }; /** @@ -42,13 +47,27 @@ public: Qt::CaseSensitive, bool anchored = false); ~ReListMatcher(); public: - bool matches(const QString& text); + bool allMatching() const; + Qt::CaseSensitivity caseSensivitiy() const; bool empty() const; + bool matches(const QString& text); + const QStringList& patterns() const; + void setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy); + void setPatterns(const QStringList& patterns, + Qt::CaseSensitivity caseSensivity = Qt::CaseSensitive, bool anchored = false); +public: + static const ReListMatcher& allMatcher(); + static const QStringList& allMatchingList(); protected: void destroy(); +private: + static QStringList* m_allMatchingList; + static ReListMatcher* m_allMatcher; protected: + QStringList m_patterns; QList m_list; bool m_empty; + bool m_allMatching; }; /** @@ -61,7 +80,12 @@ public: Qt::CaseSensitivity caseSensitivty = Qt::CaseSensitive, bool anchored = false); public: + Qt::CaseSensitivity caseSensivitiy() const; bool matches(const QString& text, bool excludeToo = true); + const ReListMatcher& includes() const; + const ReListMatcher& excludes() const; + void setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy); + protected: ReListMatcher m_includes; ReListMatcher m_excludes; diff --git a/cunit/allTests.cpp b/cunit/allTests.cpp index 9c16df1..ddd8169 100644 --- a/cunit/allTests.cpp +++ b/cunit/allTests.cpp @@ -84,7 +84,9 @@ static void testNet() { } static void testOs() { + void testReFileSystem(); + testReFileSystem(); } void allTests() { testBase(); diff --git a/cunit/cuReFileSystem.cpp b/cunit/cuReFileSystem.cpp index 6f732eb..743d32e 100644 --- a/cunit/cuReFileSystem.cpp +++ b/cunit/cuReFileSystem.cpp @@ -27,21 +27,41 @@ private: protected: void init(){ m_base = ReFileUtils::tempDir("refilesystem"); - m_subDir1 = tempDir("dir1", "refilesystem"); - tempDir("dir2", "refilesystem"); + m_subDir1 = ReFileUtils::tempDir("dir1", "refilesystem"); + ReFileUtils::tempDir("dir2", "refilesystem"); QString node; for (int ix = 1; ix <= 7; ix++){ node.sprintf("test%d.txt", ix); - QString fn = ReFileUtils::tempFile(node, "refilesystem", false); - ReFileUtils::writeToFile(fn, node); - fn.sprintf("%stext%d.txt", m_subDir1.constData(), ix); - ReFileUtils::writeToFile(fn, fn); + QByteArray fn = ReFileUtils::tempFile(node.toUtf8().constData(), + "refilesystem", false); + ReFileUtils::writeToFile(fn.constData(), node.toUtf8().constData()); + fn = m_subDir1; + fn.append("text").append(QByteArray::number(ix)); + ReFileUtils::writeToFile(fn.constData(), fn.constData()); } } + void testContains(const char* name, QList nodes){ + bool rc = false; + QList::const_iterator it; + for (it = nodes.cbegin(); it != nodes.cend(); ++it){ + if ((*it)->m_node == name) + rc = true; + } + if (! rc) + checkT(rc); + } + void testReLocalFileSystem() { ReLocalFileSytem fs(m_base); - fs. - + checkEqu(QString(m_base), fs.directory()); + checkEqu(QString(m_base), fs.basePath()); + QList nodes; + ReIncludeExcludeMatcher matcher(ReListMatcher::allMatchingList(), + ReQStringUtils::m_emptyList, Qt::CaseInsensitive, false); + fs.listInfos(matcher, nodes); + testContains("dir1", nodes); + testContains("test1.txt", nodes); + testContains("test7.txt", nodes); } virtual void run() { init(); diff --git a/os/ReFileSystem.cpp b/os/ReFileSystem.cpp index 862e77f..b88f0a3 100644 --- a/os/ReFileSystem.cpp +++ b/os/ReFileSystem.cpp @@ -66,18 +66,21 @@ ReLocalFileSytem::ReLocalFileSytem(const QString& basePath) : } /** - * Changes the current directory of the filesystem. + * Destructor. + */ +ReLocalFileSytem::~ReLocalFileSytem() +{ + +} + +/** + * Returns the base path of the filesystem. * - * @param path the new current directory - * @return 0: success
- * EC_PATH_NOT_FOUND directory does not exist
- * EC_NOT_ACCESSIBLE parent not readable + * @return the base path */ -ReFileSystem::ErrorCode ReLocalFileSytem::setDirectory(const QString& path) +const QString& ReLocalFileSytem::basePath() const { - ErrorCode rc = m_dir.setCurrent(path) ? EC_SUCCESS : EC_PATH_NOT_FOUND; - m_currentPath = m_dir.absolutePath(); - return rc; + return m_basePath; } /** @@ -91,37 +94,80 @@ const QString& ReLocalFileSytem::directory() const } /** - * Returns a list of the file infos of the current directory. + * Fills a list with the items of the current directory. * - * @param patterns only files matching these patterns will be in the result. - * Can contain wildcard '*' (for any string) - * @return a list of the files matching the patterns + * @param matcher the matching processor + * @return the count of the found entries (list.size()) */ int ReLocalFileSytem::listInfos(const ReIncludeExcludeMatcher& matcher, QList& list) { - QList rc; - QStringList list = pattern.size() == 0 ? m_dir.entryList() - : m_dir.entryList(pattern); + list.clear(); + const QStringList& patterns = matcher.includes().patterns(); + QStringList nodes = patterns.size() == 0 ? m_dir.entryList() + : m_dir.entryList(patterns); QStringList::const_iterator it; QByteArray full = m_currentPath.toUtf8(); full.append(OS_SEPARATOR); int pathLength = full.length(); struct stat info; - for (it = list.cbegin(); it != list.cend(); it++){ + for (it = nodes.cbegin(); it != nodes.cend(); it++){ QString node = *it; full.resize(pathLength); full.append(node.toUtf8()); if (stat(full.constData(), &info) == 0){ - ReFileMetaData* meta = new ReFileMetaData(node); - meta->m_modified = QDateTime::fromTime_t(info.st_mtim); - meta->m_created = QDateTime::fromTime_t(info.st_ctim); - meta->m_group = info.st_gid; - meta->m_owner = info.st_uid; - meta->m_mode = info.st_mode; - rc.append(meta); + ReFileMetaData* meta = new ReFileMetaData(node, + QDateTime::fromTime_t(info.st_mtime), + QDateTime::fromTime_t(info.st_ctime), + info.st_uid, info.st_gid, info.st_mode); + list.append(meta); } } + return list.size(); +} + +/** + * Changes the current directory of the filesystem. + * + * @param path the new current directory + * @return 0: success
+ * EC_PATH_NOT_FOUND directory does not exist
+ * EC_NOT_ACCESSIBLE parent not readable + */ +ReFileSystem::ErrorCode ReLocalFileSytem::setDirectory(const QString& path) +{ + ErrorCode rc = m_dir.setCurrent(path) ? EC_SUCCESS : EC_PATH_NOT_FOUND; + m_currentPath = m_dir.absolutePath(); return rc; } + +/** + * Constructor. + * + * @param node the filename without path + * @param modified the modification date/time + * @param created the creation date/time + * @param owner the owner of the file (UID) + * @param group the group of the file (GID) + * @param mode rights and attributs of the file + */ +ReFileMetaData::ReFileMetaData(const QString& node, const QDateTime& modified, + const QDateTime& created, int owner, int group, mode_t mode) : + m_node(node), + m_modified(modified), + m_created(created), + m_owner(owner), + m_group(group), + m_mode(mode) +{ + +} + +/** + * Destructor. + */ +ReFileMetaData::~ReFileMetaData() +{ + +} diff --git a/os/ReFileSystem.hpp b/os/ReFileSystem.hpp index d48648c..b194c13 100644 --- a/os/ReFileSystem.hpp +++ b/os/ReFileSystem.hpp @@ -14,7 +14,9 @@ class ReFileMetaData { public: - ReFileMetaData(const QString& node); + ReFileMetaData(const QString& node, const QDateTime& modified, + const QDateTime& created, + int owner, int group, mode_t mode); virtual ~ReFileMetaData(); public: QString m_node; @@ -56,12 +58,9 @@ public: * @return the name of the current directory */ virtual const QString& directory() const = 0; - /** Returns a list of the file infos of the current directory. - * @param patterns only files matching these patterns will be in the result - * Can contain wildcard '*' (for any string) - * @param excludePatterns only files not matching this patterns - * can be in the result list - * @return a list of the files matching the patterns + /** Fills a list with the items of the current directory. + * @param matcher the matching processor + * @return the count of the found entries (list.size()) */ virtual int listInfos(const ReIncludeExcludeMatcher& matcher, QList& list) = 0; @@ -79,10 +78,12 @@ public: ReLocalFileSytem(const QString& basePath); virtual ~ReLocalFileSytem(); public: - ErrorCode setDirectory(const QString& path); + const QString& basePath() const; const QString& directory() const; virtual int listInfos(const ReIncludeExcludeMatcher& matcher, QList& list); + ErrorCode setDirectory(const QString& path); + protected: QString m_basePath; QString m_currentPath; -- 2.39.5