Move all regex matching to library/string.cpp
This is in preparation to having an option to use std::regex. Also should fix a few bugs with trace log.
This commit is contained in:
parent
94b603c9f2
commit
54cbe456b4
3 changed files with 109 additions and 46 deletions
|
@ -230,14 +230,33 @@ private:
|
|||
regex_results regex(const std::string& regex, const std::string& str, const char* ex = NULL)
|
||||
throw(std::bad_alloc, std::runtime_error);
|
||||
|
||||
enum regex_match_mode
|
||||
{
|
||||
REGEX_MATCH_REGEX = 0,
|
||||
REGEX_MATCH_LITERIAL = 1,
|
||||
REGEX_MATCH_IWILDCARDS = 2,
|
||||
REGEX_MATCH_IREGEX = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Regexp a string and return match result.
|
||||
*
|
||||
* Parameter regex: The regexp to apply.
|
||||
* Parameter str: The string to apply the regexp to.
|
||||
* Parameter mode: Match mode.
|
||||
* 0 => Case-senstive regex (default).
|
||||
* 1 => Case-insensitive regex.
|
||||
* 2 =>
|
||||
* Returns: True if matches, false if not.
|
||||
*/
|
||||
bool regex_match(const std::string& regex, const std::string& str) throw(std::bad_alloc, std::runtime_error);
|
||||
bool regex_match(const std::string& regex, const std::string& str, enum regex_match_mode mode = REGEX_MATCH_REGEX)
|
||||
throw(std::bad_alloc, std::runtime_error);
|
||||
|
||||
/**
|
||||
* Try match a case-insensitive string fragment and return the result.
|
||||
*
|
||||
* \param pattern The pattern to match a
|
||||
*/
|
||||
|
||||
/**
|
||||
* Cast string to bool.
|
||||
|
|
|
@ -119,9 +119,78 @@ regex_results regex(const std::string& regexp, const std::string& str, const cha
|
|||
return regex_results();
|
||||
}
|
||||
|
||||
bool regex_match(const std::string& regexp, const std::string& str) throw(std::bad_alloc, std::runtime_error)
|
||||
bool regex_match(const std::string& regexp, const std::string& str, enum regex_match_mode mode)
|
||||
throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
return regex(regexp, str);
|
||||
static threads::lock m;
|
||||
static std::map<std::string, map_pointer<boost::regex>> regexps;
|
||||
static std::map<std::pair<regex_match_mode, std::string> , std::pair<std::string, bool>> transform_cache;
|
||||
std::string _regexp;
|
||||
bool icase = false;
|
||||
std::ostringstream y;
|
||||
{
|
||||
//See if we have cached transform.
|
||||
threads::alock h(m);
|
||||
auto key = std::make_pair(mode, regexp);
|
||||
if(transform_cache.count(key)) {
|
||||
auto entry = transform_cache[key];
|
||||
_regexp = entry.first;
|
||||
icase = entry.second;
|
||||
goto transformed;
|
||||
}
|
||||
}
|
||||
switch(mode) {
|
||||
case REGEX_MATCH_REGEX:
|
||||
icase = false;
|
||||
_regexp = regexp;
|
||||
break;
|
||||
case REGEX_MATCH_IWILDCARDS:
|
||||
case REGEX_MATCH_LITERIAL:
|
||||
for(size_t i = 0; i < regexp.length(); i++)
|
||||
if(regexp[i] == '?' && mode == REGEX_MATCH_IWILDCARDS)
|
||||
y << ".";
|
||||
else if(regexp[i] == '*' && mode == REGEX_MATCH_IWILDCARDS)
|
||||
y << ".*";
|
||||
else if(regexp[i] >= 'A' && regexp[i] <= 'Z')
|
||||
y << regexp[i];
|
||||
else if(regexp[i] >= 'a' && regexp[i] <= 'z')
|
||||
y << regexp[i];
|
||||
else if(regexp[i] >= '0' && regexp[i] <= '9')
|
||||
y << regexp[i];
|
||||
else if((unsigned char)regexp[i] > 127) //UTF-8.
|
||||
y << regexp[i];
|
||||
else
|
||||
y << "\\" << regexp[i];
|
||||
_regexp = ".*" + y.str() + ".*";
|
||||
icase = true;
|
||||
break;
|
||||
case REGEX_MATCH_IREGEX:
|
||||
icase = true;
|
||||
_regexp = ".*" + regexp + ".*";
|
||||
break;
|
||||
}
|
||||
transformed:
|
||||
threads::alock h(m);
|
||||
auto key = std::make_pair(mode, regexp);
|
||||
if(!transform_cache.count(key))
|
||||
transform_cache[key] = std::make_pair(_regexp, icase);
|
||||
|
||||
if(!regexps.count(regexp)) {
|
||||
boost::regex* y = NULL;
|
||||
auto flags = boost::regex::extended & ~boost::regex::collate;
|
||||
flags |= boost::regex::nosubs;
|
||||
if(icase) flags |= boost::regex::icase;
|
||||
try {
|
||||
y = new boost::regex(_regexp, flags);
|
||||
regexps[_regexp] = y;
|
||||
} catch(std::bad_alloc& e) {
|
||||
delete y;
|
||||
throw;
|
||||
} catch(std::exception& e) {
|
||||
throw std::runtime_error(e.what());
|
||||
}
|
||||
}
|
||||
return boost::regex_match(str.begin(), str.end(), *(regexps[_regexp]));
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
|
@ -845,49 +845,15 @@ namespace
|
|||
static boost::regex regex;
|
||||
if(pattern == "")
|
||||
return false;
|
||||
if(pattern[0] == 'F') {
|
||||
//Substring find.
|
||||
if(pattern != last_find) {
|
||||
std::string tmp = pattern;
|
||||
tmp = tmp.substr(1);
|
||||
regex = boost::regex(tmp, boost::regex_constants::literal |
|
||||
boost::regex_constants::icase);
|
||||
last_find = pattern;
|
||||
}
|
||||
}
|
||||
if(pattern[0] == 'W') {
|
||||
//wildcard find.
|
||||
if(pattern != last_find) {
|
||||
std::ostringstream y;
|
||||
for(size_t i = 1; i < pattern.length(); i++)
|
||||
if(pattern[i] == '?')
|
||||
y << ".";
|
||||
else if(pattern[i] == '*')
|
||||
y << ".*";
|
||||
else if(pattern[i] >= 'A' && pattern[i] <= 'Z')
|
||||
y << pattern[i];
|
||||
else if(pattern[i] >= 'a' && pattern[i] <= 'z')
|
||||
y << pattern[i];
|
||||
else if(pattern[i] >= '0' && pattern[i] <= '9')
|
||||
y << pattern[i];
|
||||
else
|
||||
y << "\\" << pattern[i];
|
||||
std::string tmp = y.str();
|
||||
regex = boost::regex(tmp, boost::regex_constants::extended);
|
||||
last_find = pattern;
|
||||
}
|
||||
}
|
||||
if(pattern[0] == 'R') {
|
||||
//regexp find.
|
||||
if(pattern != last_find) {
|
||||
std::string tmp = pattern;
|
||||
tmp = tmp.substr(1);
|
||||
regex = boost::regex(tmp, boost::regex_constants::extended |
|
||||
boost::regex_constants::icase);
|
||||
last_find = pattern;
|
||||
}
|
||||
}
|
||||
return regex_search(candidate, regex);
|
||||
std::string tmp = pattern;
|
||||
tmp = tmp.substr(1);
|
||||
if(pattern[0] == 'F')
|
||||
return regex_match(tmp, candidate, REGEX_MATCH_LITERIAL);
|
||||
if(pattern[0] == 'W')
|
||||
return regex_match(tmp, candidate, REGEX_MATCH_IWILDCARDS);
|
||||
if(pattern[0] == 'R')
|
||||
return regex_match(tmp, candidate, REGEX_MATCH_IREGEX);
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxwin_tracelog::on_menu(wxCommandEvent& e)
|
||||
|
@ -933,6 +899,15 @@ namespace
|
|||
find_active = false;
|
||||
return;
|
||||
}
|
||||
//Do syntax check.
|
||||
try {
|
||||
find_match(tmp, "");
|
||||
} catch(...) {
|
||||
find_active = false;
|
||||
wxMessageBox(towxstring("Invalid search pattern"), _T("Invalid pattern"),
|
||||
wxICON_EXCLAMATION | wxOK, this);
|
||||
return;
|
||||
}
|
||||
find_string = tmp;
|
||||
find_active = true;
|
||||
find_line = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue