Fixed std::regex-based parsing.

This commit is contained in:
Alexander Shaduri
2024-05-16 16:41:39 +04:00
parent 1df72dc2e0
commit 791cc93f5f
5 changed files with 34 additions and 15 deletions
+6 -6
View File
@@ -164,9 +164,9 @@ inline bool app_regex_partial_match(const std::regex& re, const std::string& str
return false;
}
for (std::size_t i = 1; i < matches_vector.size(); ++i) {
if (matches_vector[i - 1]) {
*(matches_vector[i - 1]) = matches.str(i);
for (std::size_t i = 0; i < matches_vector.size(); ++i) {
if (matches_vector[i]) {
*(matches_vector[i]) = matches.str(i + 1);
}
}
@@ -283,9 +283,9 @@ inline bool app_regex_full_match(const std::regex& re, const std::string& str, s
return false;
}
for (std::size_t i = 1; i < matches_vector.size(); ++i) {
if (matches_vector[i - 1]) {
*(matches_vector[i - 1]) = matches.str(i);
for (std::size_t i = 0; i < matches_vector.size(); ++i) {
if (matches_vector[i]) {
*(matches_vector[i]) = matches.str(i + 1);
}
}
+1 -1
View File
@@ -319,7 +319,7 @@ hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_info(
// split by lines.
// e.g. Device Model: ST3500630AS
const auto re = app_regex_re("/^([^\\n]+): [ \\t]*(.*)$/mi"); // MUST BE Ungreedy!
const auto re = app_regex_re("/^([^:]+):[ \\t]+(.*)$/i"); // MUST BE Ungreedy!
std::vector<std::string> lines;
hz::string_split(body, '\n', lines, false);
+1 -1
View File
@@ -30,7 +30,7 @@ bool SmartctlVersionParser::parse_version_text(const std::string& s, std::string
// "smartctl 5.39 2009-08-08 r2873" (svn versions)
// "smartctl 7.3 (build date Feb 11 2022)" (git versions)
// "smartctl pre-7.4 2023-06-13 r5481" (pre-releases)
if (!app_regex_partial_match(R"(/^smartctl (?:version )?(?:pre-)?(([0-9][^ \t\n\r]+)(?: [0-9 r:-]+)?)/mi)", s, {&version_only, &version_full})) {
if (!app_regex_partial_match(R"(/^smartctl (?:version )?((?:pre-)?([0-9][^ \t\n\r]+)(?: [0-9 r:-]+)?)/mi)", s, {&version_full, &version_only})) {
debug_out_error("app", DBG_FUNC_MSG << "No smartctl version information found in supplied string.\n");
return false;
}
+20 -7
View File
@@ -35,7 +35,7 @@ TEST_CASE("AppRegexFlags", "[app][regex]")
TEST_CASE("AppRegexBasic", "[app][regex]")
{
const std::vector<std::string> output_lines = {
const std::vector<std::string> input_lines = {
"major minor",
"31 0 128 mtdblock0",
"3 1 1638598 ide/host0/bus0/target0/lun0/part1 0 0 0 0 0 0 0 0 0 0 0",
@@ -44,26 +44,26 @@ TEST_CASE("AppRegexBasic", "[app][regex]")
{
std::smatch matches;
const bool matched = app_regex_partial_match(R"(/^[ \t]*[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+([^ \t\n]+)/)", output_lines.at(0), matches);
const bool matched = app_regex_partial_match(R"(/^[ \t]*[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+([^ \t\n]+)/)", input_lines.at(0), matches);
REQUIRE(matched == false);
}
{
std::smatch matches;
const bool matched = app_regex_partial_match(R"(/^[ \t]*[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+([^ \t\n]+)/)", output_lines.at(1), matches);
const bool matched = app_regex_partial_match(R"(/^[ \t]*[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+([^ \t\n]+)/)", input_lines.at(1), matches);
REQUIRE(matched == true);
REQUIRE(matches.size() == 2);
REQUIRE(matches[1].str() == "mtdblock0");
}
{
std::smatch matches;
const bool matched = app_regex_partial_match(R"(/^[ \t]*[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+([^ \t\n]+)/)", output_lines.at(2), matches);
const bool matched = app_regex_partial_match(R"(/^[ \t]*[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+([^ \t\n]+)/)", input_lines.at(2), matches);
REQUIRE(matched == true);
REQUIRE(matches.size() == 2);
REQUIRE(matches[1].str() == "ide/host0/bus0/target0/lun0/part1");
}
{
std::smatch matches;
const bool matched = app_regex_partial_match(R"(/^[ \t]*[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+([^ \t\n]+)/)", output_lines.at(3), matches);
const bool matched = app_regex_partial_match(R"(/^[ \t]*[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+[^ \t\n]+[ \t]+([^ \t\n]+)/)", input_lines.at(3), matches);
REQUIRE(matched == true);
REQUIRE(matches.size() == 2);
REQUIRE(matches[1].str() == "sda");
@@ -72,9 +72,22 @@ TEST_CASE("AppRegexBasic", "[app][regex]")
TEST_CASE("AppRegexLines", "[app][regex]")
{
const std::string input = R"(Device Model: ST3500630AS)";
std::string name, value;
const bool matched = app_regex_full_match("/^([^:]+):[ \\t]+(.*)$/i", input, {&name, &value});
REQUIRE(matched == true);
REQUIRE(name == "Device Model");
REQUIRE(value == "ST3500630AS");
}
TEST_CASE("AppRegexMultiline", "[app][regex]")
{
const std::string output = R"(
const std::string input = R"(
Copyright (C) 2002-23, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
@@ -86,7 +99,7 @@ Test will complete after Thu May 16 14:31:06 2024 +04
Use smartctl -X to abort test.
)";
const bool matched = app_regex_partial_match(R"(/^Drive command .* successful\.\nTesting has begun\.$/mi)", output);
const bool matched = app_regex_partial_match(R"(/^Drive command .* successful\.\nTesting has begun\.$/mi)", input);
REQUIRE(matched == true);
}
@@ -47,6 +47,12 @@ TEST_CASE("SmartctlVersionParser", "[app][parser]")
REQUIRE(version_full == "5.39 2009-08-08 r2873");
}
SECTION("Parse pre-releases") {
SmartctlVersionParser::parse_version_text("smartctl pre-7.4 2023-06-13 r5481", version_only, version_full);
REQUIRE(version_only == "7.4");
REQUIRE(version_full == "pre-7.4 2023-06-13 r5481");
}
SECTION("Parse old 5.0") {
SmartctlVersionParser::parse_version_text("smartctl version 5.0-49", version_only, version_full);
REQUIRE(version_only == "5.0-49");