diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:08:42 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:08:42 +0200 |
commit | c32707148292d104c66276b43796d6057c8c7a5d (patch) | |
tree | bb83513f4aff24153e21a4ec92e34e4c27651b1f /library/filter.cpp | |
parent | 3.9 (diff) | |
download | FreeFileSync-c32707148292d104c66276b43796d6057c8c7a5d.tar.gz FreeFileSync-c32707148292d104c66276b43796d6057c8c7a5d.tar.bz2 FreeFileSync-c32707148292d104c66276b43796d6057c8c7a5d.zip |
3.10
Diffstat (limited to 'library/filter.cpp')
-rw-r--r-- | library/filter.cpp | 151 |
1 files changed, 104 insertions, 47 deletions
diff --git a/library/filter.cpp b/library/filter.cpp index c4bc69d7..7697ea4b 100644 --- a/library/filter.cpp +++ b/library/filter.cpp @@ -59,11 +59,11 @@ BaseFilter::FilterRef BaseFilter::loadFilter(wxInputStream& stream) const Zstring uniqueClassId = util::readString(stream); //read actual object - if (uniqueClassId == DefaultStr("NullFilter")) + if (uniqueClassId == Zstr("NullFilter")) return NullFilter::load(stream); - else if (uniqueClassId == DefaultStr("NameFilter")) + else if (uniqueClassId == Zstr("NameFilter")) return NameFilter::load(stream); - else if (uniqueClassId == DefaultStr("CombinedFilter")) + else if (uniqueClassId == Zstr("CombinedFilter")) return CombinedFilter::load(stream); else throw std::logic_error("Programming Error: Unknown filter!"); @@ -78,15 +78,15 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st #ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case - filterFormatted.MakeUpper(); + MakeUpper(filterFormatted); #elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case: nothing to do here #endif - static const Zstring sepAsterisk = Zstring() + common::FILE_NAME_SEPARATOR + DefaultChar('*'); - static const Zstring sepQuestionMark = Zstring() + common::FILE_NAME_SEPARATOR + DefaultChar('?'); - static const Zstring asteriskSep = Zstring(DefaultStr("*")) + common::FILE_NAME_SEPARATOR; - static const Zstring questionMarkSep = Zstring(DefaultStr("?")) + common::FILE_NAME_SEPARATOR; + static const Zstring sepAsterisk = Zstring(common::FILE_NAME_SEPARATOR) + Zchar('*'); + static const Zstring sepQuestionMark = Zstring(common::FILE_NAME_SEPARATOR) + Zchar('?'); + static const Zstring asteriskSep = Zstring(Zchar('*')) + common::FILE_NAME_SEPARATOR; + static const Zstring questionMarkSep = Zstring(Zchar('?')) + common::FILE_NAME_SEPARATOR; //-------------------------------------------------------------------------------------------------- //add some syntactic sugar: handle beginning of filtername @@ -127,49 +127,77 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st } -class MatchFound : public std::unary_function<Zstring, bool> +namespace { -public: - MatchFound(const Zstring& name) : name_(name) {} - - bool operator()(const Zstring& mask) const +template <class T> +inline +const T* cStringFind(const T* str1, T ch) //strchr() +{ + while (*str1 != ch) //ch is allowed to be 0 by contract! must return end of string in this case { - return Zstring::Matches(name_.c_str(), mask.c_str()); + if (*str1 == 0) + return NULL; + ++str1; } -private: - const Zstring& name_; -}; + return str1; +} -inline -bool matchesFilter(const Zstring& name, const std::set<Zstring>& filter) +bool matchesMask(const Zchar* string, const Zchar* mask) { -#ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case - Zstring nameFormatted = name; - nameFormatted.MakeUpper(); -#elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case - const Zstring& nameFormatted = name; //nothing to do here -#endif + for (Zchar ch; (ch = *mask) != 0; ++mask, ++string) + { + switch (ch) + { + case Zchar('?'): + if (*string == 0) + return false; + break; - return std::find_if(filter.begin(), filter.end(), MatchFound(nameFormatted)) != filter.end(); -} + case Zchar('*'): + //advance to next non-*/? char + do + { + ++mask; + ch = *mask; + } + while (ch == Zchar('*') || ch == Zchar('?')); + //if match ends with '*': + if (ch == 0) + return true; + + ++mask; + while ((string = cStringFind(string, ch)) != NULL) + { + ++string; + if (matchesMask(string, mask)) + return true; + } + return false; + default: + if (*string != ch) + return false; + } + } + return *string == 0; +} //returns true if string matches at least the beginning of mask inline -bool matchesMaskBegin(const DefaultChar* string, const DefaultChar* mask) +bool matchesMaskBegin(const Zchar* string, const Zchar* mask) { - for (DefaultChar ch; (ch = *mask) != 0; ++mask, ++string) + for (Zchar ch; (ch = *mask) != 0; ++mask, ++string) { if (*string == 0) return true; switch (ch) { - case DefaultChar('?'): + case Zchar('?'): break; - case DefaultChar('*'): + case Zchar('*'): return true; default: @@ -179,18 +207,33 @@ bool matchesMaskBegin(const DefaultChar* string, const DefaultChar* mask) } return *string == 0; } +} + + +class MatchFound : public std::unary_function<Zstring, bool> +{ +public: + MatchFound(const Zstring& name) : name_(name) {} + + bool operator()(const Zstring& mask) const + { + return matchesMask(name_, mask); + } +private: + const Zstring& name_; +}; inline -bool matchesFilterBegin(const Zstring& name, const std::set<Zstring>& filter) +bool matchesFilter(const Zstring& nameFormatted, const std::set<Zstring>& filter) { -#ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case - Zstring nameFormatted = name; - nameFormatted.MakeUpper(); -#elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case - const Zstring& nameFormatted = name; //nothing to do here -#endif + return std::find_if(filter.begin(), filter.end(), MatchFound(nameFormatted)) != filter.end(); +} + +inline +bool matchesFilterBegin(const Zstring& nameFormatted, const std::set<Zstring>& filter) +{ return std::find_if(filter.begin(), filter.end(), boost::bind(matchesMaskBegin, nameFormatted.c_str(), _1)) != filter.end(); } @@ -201,10 +244,10 @@ std::vector<Zstring> compoundStringToFilter(const Zstring& filterString) //delimiters may be ';' or '\n' std::vector<Zstring> output; - const std::vector<Zstring> filterPreProcessing = filterString.Tokenize(wxT(';')); + const std::vector<Zstring> filterPreProcessing = filterString.Split(Zchar(';')); for (std::vector<Zstring>::const_iterator i = filterPreProcessing.begin(); i != filterPreProcessing.end(); ++i) { - const std::vector<Zstring> newEntries = i->Tokenize(wxT('\n')); + const std::vector<Zstring> newEntries = i->Split(Zchar('\n')); output.insert(output.end(), newEntries.begin(), newEntries.end()); } @@ -231,8 +274,15 @@ NameFilter::NameFilter(const Zstring& includeFilter, const Zstring& excludeFilte bool NameFilter::passFileFilter(const Zstring& relFilename) const { - return matchesFilter(relFilename, filterFileIn) && //process include filters - !matchesFilter(relFilename, filterFileEx); //process exclude filters +#ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case + Zstring nameFormatted = relFilename; + MakeUpper(nameFormatted); +#elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case + const Zstring& nameFormatted = relFilename; //nothing to do here +#endif + + return matchesFilter(nameFormatted, filterFileIn) && //process include filters + !matchesFilter(nameFormatted, filterFileEx); //process exclude filters } @@ -240,18 +290,25 @@ bool NameFilter::passDirFilter(const Zstring& relDirname, bool* subObjMightMatch { assert(subObjMightMatch == NULL || *subObjMightMatch == true); //check correct usage - if (matchesFilter(relDirname, filterFolderEx)) //process exclude filters +#ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case + Zstring nameFormatted = relDirname; + MakeUpper(nameFormatted); +#elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case + const Zstring& nameFormatted = relDirname; //nothing to do here +#endif + + if (matchesFilter(nameFormatted, filterFolderEx)) //process exclude filters { if (subObjMightMatch) *subObjMightMatch = false; //exclude subfolders/subfiles as well return false; } - if (!matchesFilter(relDirname, filterFolderIn)) //process include filters + if (!matchesFilter(nameFormatted, filterFolderIn)) //process include filters { if (subObjMightMatch) { - const Zstring& subNameBegin = relDirname + common::FILE_NAME_SEPARATOR; //const-ref optimization + const Zstring& subNameBegin = nameFormatted + common::FILE_NAME_SEPARATOR; //const-ref optimization *subObjMightMatch = matchesFilterBegin(subNameBegin, filterFileIn) || //might match a file in subdirectory matchesFilterBegin(subNameBegin, filterFolderIn); //or another subdirectory @@ -265,7 +322,7 @@ bool NameFilter::passDirFilter(const Zstring& relDirname, bool* subObjMightMatch bool NameFilter::isNull() const { - static NameFilter output(DefaultStr("*"), Zstring()); + static NameFilter output(Zstr("*"), Zstring()); return *this == output; } @@ -294,7 +351,7 @@ bool NameFilter::cmpLessSameType(const BaseFilter& other) const Zstring NameFilter::uniqueClassIdentifier() const { - return DefaultStr("NameFilter"); + return Zstr("NameFilter"); } |