diff --git a/src/applib/app_regex.h b/src/applib/app_regex.h index 830d7c0..2d63bdc 100644 --- a/src/applib/app_regex.h +++ b/src/applib/app_regex.h @@ -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); } } diff --git a/src/applib/smartctl_text_ata_parser.cpp b/src/applib/smartctl_text_ata_parser.cpp index 4d1f522..82c41ac 100644 --- a/src/applib/smartctl_text_ata_parser.cpp +++ b/src/applib/smartctl_text_ata_parser.cpp @@ -319,7 +319,7 @@ hz::ExpectedVoid 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 lines; hz::string_split(body, '\n', lines, false); diff --git a/src/applib/smartctl_version_parser.cpp b/src/applib/smartctl_version_parser.cpp index 563689b..6fcdc69 100644 --- a/src/applib/smartctl_version_parser.cpp +++ b/src/applib/smartctl_version_parser.cpp @@ -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; } diff --git a/src/applib/tests/test_app_regex.cpp b/src/applib/tests/test_app_regex.cpp index c812aae..92d503b 100644 --- a/src/applib/tests/test_app_regex.cpp +++ b/src/applib/tests/test_app_regex.cpp @@ -35,7 +35,7 @@ TEST_CASE("AppRegexFlags", "[app][regex]") TEST_CASE("AppRegexBasic", "[app][regex]") { - const std::vector output_lines = { + const std::vector 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); } diff --git a/src/applib/tests/test_smartctl_version_parser.cpp b/src/applib/tests/test_smartctl_version_parser.cpp index 2ec3207..ad0c19c 100644 --- a/src/applib/tests/test_smartctl_version_parser.cpp +++ b/src/applib/tests/test_smartctl_version_parser.cpp @@ -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");