From b3e4deb32f12303688d8f09448809d59bb43bb11 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 9 Nov 2025 21:26:48 +0100 Subject: [PATCH] Prefer std::regex over C regex_t --- libs/pbd/file_utils.cc | 28 ++++--------- libs/pbd/pathexpand.cc | 95 +++++++++++++++--------------------------- wscript | 4 -- 3 files changed, 42 insertions(+), 85 deletions(-) diff --git a/libs/pbd/file_utils.cc b/libs/pbd/file_utils.cc index c8b0fc792e..232c29486f 100644 --- a/libs/pbd/file_utils.cc +++ b/libs/pbd/file_utils.cc @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef HAVE_UNISTD_H #include @@ -60,7 +61,6 @@ #include // Microsoft's nearest equivalent to #include #else -#include #endif #include "pbd/compose.h" @@ -243,8 +243,8 @@ static bool regexp_filter (const string& str, void *arg) { - regex_t* pattern = (regex_t*)arg; - return regexec (pattern, str.c_str(), 0, 0, 0) == 0; + std::regex* pattern = static_cast(arg); + return std::regex_search(str, *pattern); } void @@ -253,21 +253,11 @@ find_files_matching_regex (vector& result, const std::string& regexp, bool recurse) { - int err; - char msg[256]; - regex_t compiled_pattern; - - if ((err = regcomp (&compiled_pattern, regexp.c_str(), - REG_EXTENDED|REG_NOSUB))) { - - regerror (err, &compiled_pattern, - msg, sizeof (msg)); - - error << "Cannot compile soundfile regexp for use (" - << msg - << ")" - << endmsg; - + std::regex compiled_pattern; + try { + compiled_pattern = std::regex(regexp); + } catch (const std::regex_error& e) { + error << "Cannot compile soundfile regexp for use (" << e.what() << ")" << endmsg; return; } @@ -277,8 +267,6 @@ find_files_matching_regex (vector& result, find_files_matching_filter (result, paths, regexp_filter, &compiled_pattern, true, true, recurse); - - regfree (&compiled_pattern); } void diff --git a/libs/pbd/pathexpand.cc b/libs/pbd/pathexpand.cc index 4aba783b5d..cd528a67ea 100644 --- a/libs/pbd/pathexpand.cc +++ b/libs/pbd/pathexpand.cc @@ -24,8 +24,7 @@ #include #include #include - -#include +#include #include #include @@ -42,69 +41,43 @@ using std::vector; string PBD::path_expand (string path) { - if (path.empty()) { - return path; - } - - /* tilde expansion */ - - if (path[0] == '~') { - if (path.length() == 1) { - return Glib::get_home_dir(); - } - - if (path[1] == '/') { - path.replace (0, 1, Glib::get_home_dir()); - } else { - /* can't handle ~roger, so just leave it */ - } - } - - /* now do $VAR substitution, since wordexp isn't reliable */ - - regex_t compiled_pattern; - const int nmatches = 100; - regmatch_t matches[nmatches]; - - if (regcomp (&compiled_pattern, "\\$([a-zA-Z_][a-zA-Z0-9_]*|\\{[a-zA-Z_][a-zA-Z0-9_]*\\})", REG_EXTENDED)) { - std::cerr << "bad regcomp\n"; - return path; - } - - while (true) { - - if (regexec (&compiled_pattern, path.c_str(), nmatches, matches, 0)) { - break; - } - - /* matches[0] gives the entire match */ - - string match = path.substr (matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so); - - /* try to get match from the environment */ - - if (match[1] == '{') { - /* ${FOO} form */ - match = match.substr (2, match.length() - 3); - } - - char* matched_value = getenv (match.c_str()); - - if (matched_value) { - path.replace (matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so, matched_value); - } else { - path.replace (matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so, string()); - } - - /* go back and do it again with whatever remains after the - * substitution - */ + if (path.empty()) { + return path; } - regfree (&compiled_pattern); + /* tilde expansion */ + + if (path[0] == '~') { + if (path.length() == 1) { + return Glib::get_home_dir(); + } + + if (path[1] == '/') { + path.replace (0, 1, Glib::get_home_dir()); + } else { + /* can't handle ~roger, so just leave it */ + } + } + + /* now do $VAR or ${VAR} substitution, since wordexp isn't reliable */ + + static const std::regex var_regex (R"(\$([A-Za-z_][A-Za-z0-9_]*|\{[A-Za-z_][A-Za-z0-9_]*\}))"); + + std::smatch m; + + while (std::regex_search (path, m, var_regex)) { + std::string var = m[1].str(); // "$FOO" or "${FOO}" + + if (var[0] == '{') { + var = var.substr(1, var.size() - 2); + } + + const char* val = g_getenv (var.c_str()); + + path.replace (m.position(0), m.length(0), val ? val : ""); + } /* canonicalize */ - return canonical_path (path); } diff --git a/wscript b/wscript index e58b794da9..4b36f23048 100644 --- a/wscript +++ b/wscript @@ -1227,10 +1227,6 @@ int main () { int x = SFC_RF64_AUTO_DOWNGRADE; return 0; } conf.env.append_value('LIB', 'uuid') # needed for mingw64 packages, not harmful on normal mingw build conf.env.append_value('LIB', 'intl') - conf.check_cc(function_name='regcomp', header_name='regex.h', - lib='regex', uselib_store="REGEX", define_name='HAVE_REGEX_H') - # TODO put this only where it is needed - conf.env.append_value('LIB', 'regex') # TODO this should only be necessary for a debug build conf.env.append_value('LIB', 'dbghelp')