|
|
@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
|
|
#pragma hdrstop |
|
|
|
#pragma hdrstop |
|
|
|
|
|
|
|
|
|
|
|
#include "plString.h" |
|
|
|
#include "plString.h" |
|
|
|
#include <pcre.h> |
|
|
|
#include <regex> |
|
|
|
|
|
|
|
|
|
|
|
const plString plString::Null; |
|
|
|
const plString plString::Null; |
|
|
|
|
|
|
|
|
|
|
@ -605,66 +605,44 @@ ssize_t plString::Find(const char *str, CaseSensitivity sense) const |
|
|
|
|
|
|
|
|
|
|
|
bool plString::REMatch(const char *pattern, CaseSensitivity sense) const |
|
|
|
bool plString::REMatch(const char *pattern, CaseSensitivity sense) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
int opts = PCRE_UTF8; |
|
|
|
auto opts = std::regex_constants::ECMAScript; |
|
|
|
if (sense == kCaseInsensitive) |
|
|
|
if (sense == kCaseInsensitive) |
|
|
|
opts |= PCRE_CASELESS; |
|
|
|
opts |= std::regex_constants::icase; |
|
|
|
|
|
|
|
|
|
|
|
plString pat_full = plString::Format("(?:%s)\\z", pattern); |
|
|
|
|
|
|
|
const char *errptr; |
|
|
|
|
|
|
|
int erroffs; |
|
|
|
|
|
|
|
std::unique_ptr<pcre, std::function<void (pcre *)>> |
|
|
|
|
|
|
|
re(pcre_compile(pat_full.c_str(), opts, &errptr, &erroffs, nullptr), pcre_free); |
|
|
|
|
|
|
|
if (!re.get()) { |
|
|
|
|
|
|
|
hsAssert(0, plString::Format("Invalid Regex pattern: %s (at %d)", errptr, erroffs).c_str()); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int result = pcre_exec(re.get(), nullptr, c_str(), GetSize(), 0, |
|
|
|
std::regex re; |
|
|
|
PCRE_ANCHORED, nullptr, 0); |
|
|
|
try { |
|
|
|
if (result >= 0) |
|
|
|
re = std::regex(pattern, opts); |
|
|
|
return true; |
|
|
|
if (std::regex_match(c_str(), re)) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} catch (const std::regex_error& e) { |
|
|
|
|
|
|
|
hsAssert(0, plString::Format("Regex match error: %s", e.what()).c_str()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hsAssert(result == PCRE_ERROR_NOMATCH, plString::Format("Regex match error: %d", result).c_str()); |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::vector<plString> plString::RESearch(const char *pattern, |
|
|
|
std::vector<plString> plString::RESearch(const char *pattern, |
|
|
|
CaseSensitivity sense) const |
|
|
|
CaseSensitivity sense) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
int opts = PCRE_UTF8; |
|
|
|
auto opts = std::regex_constants::ECMAScript; |
|
|
|
if (sense == kCaseInsensitive) |
|
|
|
if (sense == kCaseInsensitive) |
|
|
|
opts |= PCRE_CASELESS; |
|
|
|
opts |= std::regex_constants::icase; |
|
|
|
|
|
|
|
|
|
|
|
const char *errptr; |
|
|
|
|
|
|
|
int erroffs; |
|
|
|
|
|
|
|
std::unique_ptr<pcre, std::function<void (pcre *)>> |
|
|
|
|
|
|
|
re(pcre_compile(pattern, opts, &errptr, &erroffs, nullptr), pcre_free); |
|
|
|
|
|
|
|
if (!re.get()) { |
|
|
|
|
|
|
|
hsAssert(0, plString::Format("Invalid Regex pattern: %s (at %d)", errptr, erroffs).c_str()); |
|
|
|
|
|
|
|
return std::vector<plString>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ncaps = 0; |
|
|
|
std::vector<plString> substrings; |
|
|
|
pcre_fullinfo(re.get(), nullptr, PCRE_INFO_CAPTURECOUNT, &ncaps); |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
ncaps += 1; // For the whole-pattern capture
|
|
|
|
std::regex re(pattern, opts); |
|
|
|
std::unique_ptr<int> outvec(new int[ncaps * 3]); |
|
|
|
std::cmatch matches; |
|
|
|
memset(outvec.get(), -1, sizeof(int) * ncaps * 3); |
|
|
|
std::regex_search(c_str(), matches, re); |
|
|
|
int result = pcre_exec(re.get(), nullptr, c_str(), GetSize(), 0, 0, |
|
|
|
substrings.resize(matches.size()); |
|
|
|
outvec.get(), ncaps * 3); |
|
|
|
|
|
|
|
if (result >= 0) { |
|
|
|
for (size_t i = 0; i < matches.size(); ++i) |
|
|
|
std::vector<plString> caps; |
|
|
|
substrings[i] = matches[i].str().c_str(); |
|
|
|
caps.resize(ncaps); |
|
|
|
} catch (const std::regex_error& e) { |
|
|
|
for (int i = 0; i < ncaps; ++i) { |
|
|
|
hsAssert(0, plString::Format("Regex search error: %s", e.what()).c_str()); |
|
|
|
int start = outvec.get()[i*2], end = outvec.get()[i*2+1]; |
|
|
|
|
|
|
|
if (start >= 0) |
|
|
|
|
|
|
|
caps[i] = Substr(start, end - start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return caps; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hsAssert(result == PCRE_ERROR_NOMATCH, plString::Format("Regex search error: %d", result).c_str()); |
|
|
|
return substrings; |
|
|
|
return std::vector<plString>(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool in_set(char key, const char *charset) |
|
|
|
static bool in_set(char key, const char *charset) |
|
|
|