Skip to content

Commit b27d67c

Browse files
committed
fixed #14261 - Regex: added std::regex implementation [skip ci]
1 parent cf93424 commit b27d67c

6 files changed

Lines changed: 75 additions & 2 deletions

File tree

cli/cmdlineparser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
13561356
if (std::strcmp(engine, "pcre") == 0) {
13571357
rule.engine = Regex::Engine::Pcre;
13581358
}
1359+
else if (std::strcmp(engine, "std") == 0) {
1360+
rule.engine = Regex::Engine::Std;
1361+
}
13591362
else {
13601363
mLogger.printError(std::string("unknown regex engine '") + engine + "'.");
13611364
return Result::Fail;

lib/regex.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "regex.h"
2222

23+
#include <regex>
2324
#include <utility>
2425

2526
#ifdef _WIN32
@@ -246,6 +247,51 @@ namespace {
246247
}
247248
}
248249

250+
namespace {
251+
class StdRegex : public Regex
252+
{
253+
public:
254+
explicit StdRegex(std::string pattern)
255+
: mPattern(std::move(pattern))
256+
{}
257+
258+
std::string compile()
259+
{
260+
if (mCompiled)
261+
return "regular expression has already been compiled";
262+
263+
try {
264+
mRegex = std::regex(mPattern);
265+
} catch (const std::exception& e) {
266+
return e.what();
267+
}
268+
mCompiled = true;
269+
return "";
270+
}
271+
272+
std::string match(const std::string& str, const MatchFn& matchFn) const override
273+
{
274+
if (!mCompiled)
275+
return "regular expression has not been compiled yet";
276+
277+
auto I = std::sregex_iterator(str.cbegin(), str.cend(), mRegex);
278+
const auto E = std::sregex_iterator();
279+
while (I != E)
280+
{
281+
const std::smatch& match = *I;
282+
matchFn(match.position(), match.position() + match.length());
283+
++I;
284+
}
285+
return "";
286+
}
287+
288+
private:
289+
std::string mPattern;
290+
std::regex mRegex;
291+
bool mCompiled{};
292+
};
293+
}
294+
249295
template<typename T>
250296
static T* createAndCompileRegex(std::string pattern, std::string& err)
251297
{
@@ -259,6 +305,8 @@ std::shared_ptr<Regex> Regex::create(std::string pattern, Engine engine, std::st
259305
Regex* regex = nullptr;
260306
if (engine == Engine::Pcre)
261307
regex = createAndCompileRegex<PcreRegex>(std::move(pattern), err);
308+
else if (engine == Engine::Std)
309+
regex = createAndCompileRegex<StdRegex>(std::move(pattern), err);
262310
else {
263311
err = "unknown regular expression engine";
264312
}

lib/regex.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class CPPCHECKLIB Regex
4141
enum class Engine : std::uint8_t
4242
{
4343
Unknown = 0,
44-
Pcre = 1
44+
Pcre = 1,
45+
Std = 2
4546
};
4647

4748
static std::shared_ptr<Regex> create(std::string pattern, Engine engine, std::string& err);

releasenotes.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ Infrastructure & dependencies:
2121

2222
Other:
2323
- Make it possible to specify the regular expression engine using the `engine` element in a rule XML.
24+
- Added support for `std::regex` as the regular engine for rules. It can be specified using `std` in the engine` element in a rule XML.
25+
-

test/testcmdlineparser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2674,6 +2674,7 @@ class TestCmdlineParser : public TestFixture {
26742674
"</message>\n"
26752675
"</rule>\n"
26762676
"<rule>\n"
2677+
"<engine>std</engine>\n"
26772678
"<tokenlist>define</tokenlist>\n"
26782679
"<pattern>.*</pattern>\n"
26792680
"<message>\n"
@@ -2694,7 +2695,7 @@ class TestCmdlineParser : public TestFixture {
26942695
ASSERT_EQUALS("ruleId1", it->id);
26952696
ASSERT_EQUALS("ruleSummary1", it->summary);
26962697
++it;
2697-
ASSERT_EQUALS_ENUM(Regex::Engine::Pcre, it->engine);
2698+
ASSERT_EQUALS_ENUM(Regex::Engine::Std, it->engine);
26982699
ASSERT_EQUALS("define", it->tokenlist);
26992700
ASSERT_EQUALS(".*", it->pattern);
27002701
ASSERT_EQUALS_ENUM(Severity::warning, it->severity);

test/testregex.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ class TestRegExBase : public TestFixture {
8585
std::string exp;
8686
if (mEngine == Regex::Engine::Pcre)
8787
exp = "missing terminating ] for character class";
88+
else if (mEngine == Regex::Engine::Std)
89+
{
90+
#if defined(_MSC_VER)
91+
exp = "regex_error(error_brack): The expression contained mismatched [ and ].";
92+
#elif defined(_LIBCPP_VERSION)
93+
exp = "The expression contained mismatched [ and ].";
94+
#elif defined(__clang__)
95+
exp = "Unexpected character within '[...]' in regular expression";
96+
#else
97+
exp = "Unexpected character in bracket expression.";
98+
#endif
99+
}
88100

89101
(void)assertRegex("[", exp);
90102
}
@@ -201,6 +213,12 @@ class TestRegExPcre : public TestRegExBase {
201213
TestRegExPcre() : TestRegExBase("TestRegExPcre", Regex::Engine::Pcre) {}
202214
};
203215

216+
class TestRegExStd : public TestRegExBase {
217+
public:
218+
TestRegExStd() : TestRegExBase("TestRegExStd", Regex::Engine::Std) {}
219+
};
220+
204221
REGISTER_TEST(TestRegExPcre)
222+
REGISTER_TEST(TestRegExStd)
205223

206224
#endif // HAVE_RULES

0 commit comments

Comments
 (0)