Index: src/libchcore/TStringPattern.cpp
===================================================================
diff -u -N -r3401d5079f33b29a7783b65bfad5f34d89a33ba5 -r6d90b96005710c802d5f141b69528e9e87a380c9
--- src/libchcore/TStringPattern.cpp	(.../TStringPattern.cpp)	(revision 3401d5079f33b29a7783b65bfad5f34d89a33ba5)
+++ src/libchcore/TStringPattern.cpp	(.../TStringPattern.cpp)	(revision 6d90b96005710c802d5f141b69528e9e87a380c9)
@@ -19,6 +19,8 @@
 #include "stdafx.h"
 #include "TStringPattern.h"
 #include <tchar.h>
+#include <regex>
+#include <boost/algorithm/string/replace.hpp>
 
 using namespace string;
 
@@ -33,32 +35,52 @@
 		}
 	}
 
-	TStringPattern::TStringPattern(EPatternType ePatternType) :
-		m_ePatternType(ePatternType)
+	TStringPattern::TStringPattern() :
+		m_ePatternType(EPatternType::eType_FilenameWildcard)
 	{
 	}
 
+	TStringPattern::TStringPattern(const TString& strPattern)
+	{
+		FromString(strPattern);
+	}
+	
 	TStringPattern::TStringPattern(const TString& strPattern, EPatternType ePatternType) :
 		m_strPattern(strPattern),
 		m_ePatternType(ePatternType)
 	{
 	}
 
-	TStringPattern TStringPattern::CreateFromString(const TString& strPattern, EPatternType eDefaultPatternType)
+	TStringPattern TStringPattern::CreateFromString(const TString& strPattern)
 	{
 		TStringPattern pattern;
-		pattern.FromString(strPattern, eDefaultPatternType);
+		pattern.FromString(strPattern);
 		return pattern;
 	}
 
-	void TStringPattern::FromString(const TString& strPattern, EPatternType eDefaultPatternType)
+	void TStringPattern::FromString(const TString& strPattern)
 	{
-		m_ePatternType = eDefaultPatternType;
-		if (strPattern.StartsWith(L"WC;"))
+		m_ePatternType = EPatternType::eType_FilenameWildcard;
+		if(strPattern.StartsWith(L"file:"))
 		{
-			m_strPattern = strPattern.Mid(3);
-			m_ePatternType = EPatternType::eType_Wildcard;
+			m_strPattern = strPattern.Mid(5);
+			m_ePatternType = EPatternType::eType_FilenameWildcard;
 		}
+		else if(strPattern.StartsWith(L"path:"))
+		{
+			m_strPattern = strPattern.Mid(5);
+			m_ePatternType = EPatternType::eType_FullPathWildcard;
+		}
+		else if(strPattern.StartsWith(L"rfile:"))
+		{
+			m_strPattern = strPattern.Mid(6);
+			m_ePatternType = EPatternType::eType_FilenameRegex;
+		}
+		else if(strPattern.StartsWith(L"rpath:"))
+		{
+			m_strPattern = strPattern.Mid(6);
+			m_ePatternType = EPatternType::eType_FullPathRegex;
+		}
 		else
 			m_strPattern = strPattern;
 	}
@@ -68,9 +90,21 @@
 		TString strPrefix;
 		switch (m_ePatternType)
 		{
-		case EPatternType::eType_Wildcard:
+		case EPatternType::eType_FilenameWildcard:
 			break;	// wildcard won't have any prefix (it's implicit)
 
+		case EPatternType::eType_FullPathWildcard:
+			strPrefix = L"path:";
+			break;
+
+		case EPatternType::eType_FilenameRegex:
+			strPrefix = L"rfile:";
+			break;
+
+		case EPatternType::eType_FullPathRegex:
+			strPrefix = L"rpath:";
+			break;
+
 		default:
 			throw std::invalid_argument("Pattern type not supported");
 		}
@@ -88,71 +122,51 @@
 		return m_ePatternType == rSrc.m_ePatternType && m_strPattern == rSrc.m_strPattern;
 	}
 
-	bool TStringPattern::MatchMask(LPCTSTR lpszMask, LPCTSTR lpszString) const
+	bool TStringPattern::Matches(const TSmartPath& pathToMatch) const
 	{
-		bool bMatch = true;
-
-		//iterate and delete '?' and '*' one by one
-		while (*lpszMask != _T('\0') && bMatch && *lpszString != _T('\0'))
+		switch(m_ePatternType)
 		{
-			if (*lpszMask == _T('?')) lpszString++;
-			else if (*lpszMask == _T('*'))
-			{
-				bMatch = Scan(lpszMask, lpszString);
-				lpszMask--;
-			}
-			else
-			{
-				bMatch = _tcicmp(*lpszMask, *lpszString);
-				lpszString++;
-			}
-			lpszMask++;
-		}
-		while (*lpszMask == _T('*') && bMatch)
-			lpszMask++;
+		case EPatternType::eType_FilenameWildcard:
+		{
+			if(m_strPattern == L"*" || m_strPattern == L"*.*")
+				return true;
 
-		return bMatch && *lpszString == _T('\0') && *lpszMask == _T('\0');
-	}
+			std::wstring strPattern = ConvertGlobToRegex();
 
-	// scan '?' and '*'
-	bool TStringPattern::Scan(LPCTSTR& lpszMask, LPCTSTR& lpszString) const
-	{
-		// remove the '?' and '*'
-		for (lpszMask++; *lpszString != _T('\0') && (*lpszMask == _T('?') || *lpszMask == _T('*')); lpszMask++)
-			if (*lpszMask == _T('?')) lpszString++;
-		while (*lpszMask == _T('*')) lpszMask++;
+			std::wstring strText(pathToMatch.GetFileName().ToString());
+			std::wregex pattern(strPattern, std::regex_constants::icase | std::regex_constants::ECMAScript);
 
-		// if lpszString is empty and lpszMask has more characters or,
-		// lpszMask is empty, return 
-		if (*lpszString == _T('\0') && *lpszMask != _T('\0'))
-			return false;
-		if (*lpszString == _T('\0') && *lpszMask == _T('\0'))
-			return true;
-		// else search substring
-		LPCTSTR wdsCopy = lpszMask;
-		LPCTSTR lpszStringCopy = lpszString;
-		bool bMatch = true;
-		do
+			return std::regex_match(strText, pattern);
+		}
+
+		case EPatternType::eType_FullPathWildcard:
 		{
-			if (!MatchMask(lpszMask, lpszString)) lpszStringCopy++;
-			lpszMask = wdsCopy;
-			lpszString = lpszStringCopy;
-			while (!(_tcicmp(*lpszMask, *lpszString)) && (*lpszString != '\0')) lpszString++;
-			wdsCopy = lpszMask;
-			lpszStringCopy = lpszString;
-		} while ((*lpszString != _T('\0')) ? !MatchMask(lpszMask, lpszString) : (bMatch = false) != false);
+			if(m_strPattern == L"*" || m_strPattern == L"*.*")
+				return true;
 
-		if (*lpszString == _T('\0') && *lpszMask == _T('\0')) return true;
+			std::wstring strPattern = ConvertGlobToRegex();
+			std::wstring strText(pathToMatch.ToString());
+			std::wregex pattern(strPattern, std::regex_constants::icase | std::regex_constants::ECMAScript);
 
-		return bMatch;
-	}
+			return std::regex_match(strText, pattern);
+		}
 
-	bool TStringPattern::Matches(const TSmartPath& pathToMatch) const
-	{
-		switch(m_ePatternType)
+		case EPatternType::eType_FilenameRegex:
 		{
-		case EPatternType::eType_Wildcard:
-			return MatchMask(m_strPattern.c_str(), pathToMatch.GetFileName().ToString());
+			std::wstring strText(pathToMatch.GetFileName().ToString());
+			std::wregex pattern(m_strPattern.c_str(), std::regex_constants::icase | std::regex_constants::ECMAScript);
+
+			return std::regex_match(strText, pattern);
+		}
+
+		case EPatternType::eType_FullPathRegex:
+		{
+			std::wstring strText(pathToMatch.ToString());
+			std::wregex pattern(m_strPattern.c_str(), std::regex_constants::icase | std::regex_constants::ECMAScript);
+
+			return std::regex_match(strText, pattern);
+		}
+
 		default:
 			throw std::invalid_argument("Unsupported pattern type");
 		}
@@ -163,4 +177,27 @@
 		m_ePatternType = ePatternType;
 		m_strPattern = strPattern;
 	}
+
+	std::wstring TStringPattern::ConvertGlobToRegex() const
+	{
+		std::wstring strPattern = m_strPattern.c_str();
+
+		boost::replace_all(strPattern, L"\\", L"\\\\");
+		boost::replace_all(strPattern, L"^", L"\\^");
+		boost::replace_all(strPattern, L".", L"\\.");
+		boost::replace_all(strPattern, L"$", L"\\$");
+		boost::replace_all(strPattern, L"|", L"\\|");
+		boost::replace_all(strPattern, L"(", L"\\(");
+		boost::replace_all(strPattern, L")", L"\\)");
+		boost::replace_all(strPattern, L"{", L"\\{");
+		boost::replace_all(strPattern, L"{", L"\\}");
+		boost::replace_all(strPattern, L"[", L"\\[");
+		boost::replace_all(strPattern, L"]", L"\\]");
+		boost::replace_all(strPattern, L"+", L"\\+");
+		boost::replace_all(strPattern, L"/", L"\\/");
+		boost::replace_all(strPattern, L"*", L".*");
+		boost::replace_all(strPattern, L"?", L".");
+
+		return strPattern;
+	}
 }