aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-07-18 12:34:52 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-07-18 12:54:55 +0300
commit47d5b304235c5b1f409b01cab95a2191eac5a230 (patch)
treedc82e4971e7c0124a5953b6ab75ec017c6124c83
parentef81695c5fa356529bac6f8aa7d9bfe1f1c84473 (diff)
Add $regex.find_match() and $regex.find_search() functions
-rw-r--r--NEWS2
-rw-r--r--libbuild2/functions-regex.cxx98
-rw-r--r--tests/function/regex/testscript84
3 files changed, 184 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index f5e2016..5999e49 100644
--- a/NEWS
+++ b/NEWS
@@ -187,6 +187,8 @@ Version 0.13.0
See the "Install Module" chapter in the manual for details.
+ * New $regex.find_{match,search}() functions that operate on lists.
+
* The $process.run*() functions now recognize a number of portable builtins.
Refer to the Testscript manual for the list and details.
diff --git a/libbuild2/functions-regex.cxx b/libbuild2/functions-regex.cxx
index 10067a4..a59d808 100644
--- a/libbuild2/functions-regex.cxx
+++ b/libbuild2/functions-regex.cxx
@@ -397,6 +397,63 @@ namespace build2
return r;
}
+ static regex::flag_type
+ parse_find_flags (optional<names>&& flags)
+ {
+ regex::flag_type r (regex::ECMAScript);
+
+ if (flags)
+ {
+ for (auto& f: *flags)
+ {
+ string s (convert<string> (move (f)));
+
+ if (s == "icase")
+ r |= regex::icase;
+ else
+ throw invalid_argument ("invalid flag '" + s + "'");
+ }
+ }
+
+ return r;
+ }
+
+ // Return true if any of the list elements match the regular expression.
+ // See find_match() overloads (below) for details.
+ //
+ static bool
+ find_match (names&& s, const string& re, optional<names>&& flags)
+ {
+ regex::flag_type fl (parse_find_flags (move (flags)));
+ regex rge (parse_regex (re, fl));
+
+ for (auto& v: s)
+ {
+ if (regex_match (convert<string> (move (v)), rge))
+ return true;
+ }
+
+ return false;
+ }
+
+ // Return true if a part of any of the list elements matches the regular
+ // expression. See find_search() overloads (below) for details.
+ //
+ static bool
+ find_search (names&& s, const string& re, optional<names>&& flags)
+ {
+ regex::flag_type fl (parse_find_flags (move (flags)));
+ regex rge (parse_regex (re, fl));
+
+ for (auto& v: s)
+ {
+ if (regex_search (convert<string> (move (v)), rge))
+ return true;
+ }
+
+ return false;
+ }
+
// Replace matched parts of list elements using the format string and
// concatenate the transformed elements. See merge() overloads (below) for
// details.
@@ -474,6 +531,25 @@ namespace build2
return match (move (s), convert<string> (move (re)), move (flags));
};
+ // $regex.find_match(<vals>, <pat> [, <flags>])
+ //
+ // Match list elements against the regular expression and return true if
+ // the match is found. Convert the elements to string prior to matching.
+ //
+ // The following flags are supported:
+ //
+ // icase - match ignoring case
+ //
+ f[".find_match"] = [](names s, string re, optional<names> flags)
+ {
+ return find_match (move (s), re, move (flags));
+ };
+
+ f[".find_match"] = [](names s, names re, optional<names> flags)
+ {
+ return find_match (move (s), convert<string> (move (re)), move (flags));
+ };
+
// $regex.search(<val>, <pat> [, <flags>])
//
// Determine if there is a match between the regular expression and some
@@ -507,6 +583,28 @@ namespace build2
return search (move (s), convert<string> (move (re)), move (flags));
};
+ // $regex.find_search(<vals>, <pat> [, <flags>])
+ //
+ // Determine if there is a match between the regular expression and some
+ // part of any of the list elements. Convert the elements to string prior
+ // to matching.
+ //
+ // The following flags are supported:
+ //
+ // icase - match ignoring case
+ //
+ f[".find_search"] = [](names s, string re, optional<names> flags)
+ {
+ return find_search (move (s), re, move (flags));
+ };
+
+ f[".find_search"] = [](names s, names re, optional<names> flags)
+ {
+ return find_search (move (s),
+ convert<string> (move (re)),
+ move (flags));
+ };
+
// $regex.replace(<val>, <pat>, <fmt> [, <flags>])
//
// Replace matched parts in a value of an arbitrary type, using the format
diff --git a/tests/function/regex/testscript b/tests/function/regex/testscript
index 95dfbb8..5167390 100644
--- a/tests/function/regex/testscript
+++ b/tests/function/regex/testscript
@@ -436,6 +436,90 @@
EOI
}
+: find-match
+:
+{
+ : match
+ :
+ {
+ : string
+ :
+ $* <<EOI >'true'
+ print $regex.find_match(-g -O3, [string] '-O[23]')
+ EOI
+
+ : untyped
+ :
+ $* <<EOI >'true'
+ print $regex.find_match(-g -O3, '-O[23]')
+ EOI
+
+ : strings
+ :
+ $* <<EOI >'true'
+ print $regex.find_match([strings] -g -O3, '-O[23]')
+ EOI
+
+ : nomatch
+ :
+ $* <<EOI >'false'
+ print $regex.find_match(-g -O1, '-O[23]')
+ EOI
+ }
+
+ : flags
+ :
+ {
+ : icase
+ :
+ $* <<EOI >'true'
+ print $regex.find_match(Foo.cxx, 'f[^.]+.*', icase)
+ EOI
+ }
+}
+
+: find-search
+:
+{
+ : match
+ :
+ {
+ : string
+ :
+ $* <<EOI >'true'
+ print $regex.find_search(-g -O3, [string] '-O')
+ EOI
+
+ : untyped
+ :
+ $* <<EOI >'true'
+ print $regex.find_search(-g -O3, '-O')
+ EOI
+
+ : strings
+ :
+ $* <<EOI >'true'
+ print $regex.find_search([strings] -g -O3, '-O')
+ EOI
+
+ : nomatch
+ :
+ $* <<EOI >'false'
+ print $regex.find_search(-g, '-O')
+ EOI
+ }
+
+ : flags
+ :
+ {
+ : icase
+ :
+ $* <<EOI >'true'
+ print $regex.find_search(Foo.cxx, 'f', icase)
+ EOI
+ }
+}
+
: merge
:
{