aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-09-29 13:12:19 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-09-29 14:14:51 +0200
commit785087aa43cf962855724b8fa5da393022204a14 (patch)
tree4a24ca94679d72cf160d2ef528bba2c8dac45cb4
parentd7cb460833e6dde3e3b958b993eee3eee4ae3bf0 (diff)
Add $find(<sequence>, <value>), $find_index(<sequence>, <value>) functions
The $find() function returns true if the sequence contains the specified value. The $find_index() function returns the index of the first element in the sequence that is equal to the specified value or $size(<sequence>) if none is found. For string sequences, it's possible to request case- insensitive comparison with a flag.
-rw-r--r--libbuild2/functions-builtin.cxx33
-rw-r--r--libbuild2/functions-name.cxx25
-rw-r--r--libbuild2/functions-path.cxx43
-rw-r--r--libbuild2/functions-string.cxx56
-rw-r--r--tests/function/builtin/testscript14
-rw-r--r--tests/function/name/testscript18
-rw-r--r--tests/function/path/testscript14
-rw-r--r--tests/function/string/testscript16
8 files changed, 215 insertions, 4 deletions
diff --git a/libbuild2/functions-builtin.cxx b/libbuild2/functions-builtin.cxx
index 7000f16..de79538 100644
--- a/libbuild2/functions-builtin.cxx
+++ b/libbuild2/functions-builtin.cxx
@@ -219,6 +219,39 @@ namespace build2
return v;
};
+ // $find(<ints>, <int>)
+ //
+ // Return true if the integer sequence contains the specified integer.
+ //
+ f["find"] += [](int64s vs, value v)
+ {
+ return find (vs.begin (), vs.end (),
+ convert<int64_t> (move (v))) != vs.end ();
+ };
+
+ f["find"] += [](uint64s vs, value v)
+ {
+ return find (vs.begin (), vs.end (),
+ convert<uint64_t> (move (v))) != vs.end ();
+ };
+
+ // $find_index(<ints>, <int>)
+ //
+ // Return the index of the first element in the integer sequence that is
+ // equal to the specified integer or $size(<ints>) if none is found.
+ //
+ f["find_index"] += [](int64s vs, value v)
+ {
+ auto i (find (vs.begin (), vs.end (), convert<int64_t> (move (v))));
+ return i != vs.end () ? i - vs.begin () : vs.size ();
+ };
+
+ f["find_index"] += [](uint64s vs, value v)
+ {
+ auto i (find (vs.begin (), vs.end (), convert<uint64_t> (move (v))));
+ return i != vs.end () ? i - vs.begin () : vs.size ();
+ };
+
// getenv
//
// Return NULL if the environment variable is not set, untyped value
diff --git a/libbuild2/functions-name.cxx b/libbuild2/functions-name.cxx
index 43de039..9011cc0 100644
--- a/libbuild2/functions-name.cxx
+++ b/libbuild2/functions-name.cxx
@@ -330,6 +330,31 @@ namespace build2
return ns;
};
+ // $find(<names>, <name>)
+ //
+ // Return true if the name sequence contains the specified name.
+ //
+ fn["find"] += [](names vs, names v)
+ {
+ //@@ TODO: shouldn't we do this in a pair-aware manner?
+
+ return find (vs.begin (), vs.end (),
+ convert<name> (move (v))) != vs.end ();
+ };
+
+ // $find_index(<names>, <name>)
+ //
+ // Return the index of the first element in the name sequence that is
+ // equal to the specified name or $size(<names>) if none is found.
+ //
+ fn["find_index"] += [](names vs, names v)
+ {
+ //@@ TODO: shouldn't we do this in a pair-aware manner?
+
+ auto i (find (vs.begin (), vs.end (), convert<name> (move (v))));
+ return i != vs.end () ? i - vs.begin () : vs.size ();
+ };
+
// Functions that can be called only on real targets.
//
function_family ft (m, "target");
diff --git a/libbuild2/functions-path.cxx b/libbuild2/functions-path.cxx
index b79585d..0c9b57f 100644
--- a/libbuild2/functions-path.cxx
+++ b/libbuild2/functions-path.cxx
@@ -541,8 +541,8 @@ namespace build2
// $sort(<paths> [, <flags>])
// $sort(<dir_paths> [, <flags>])
//
- // Sort paths in ascending order. Note that on case-insensitive filesystem
- // the order is case-insensitive.
+ // Sort paths in ascending order. Note that on hosts with a case-
+ // insensitive filesystem the order is case-insensitive.
//
// The following flags are supported:
//
@@ -568,6 +568,45 @@ namespace build2
return v;
};
+ // $find(<paths>, <path>)
+ // $find(<dir_paths>, <dir_path>)
+ //
+ // Return true if the path sequence contains the specified path. Note that
+ // on hosts with a case-insensitive filesystem the comparison is
+ // case-insensitive.
+ //
+ f["find"] += [](paths vs, value v)
+ {
+ return find (vs.begin (), vs.end (),
+ convert<path> (move (v))) != vs.end ();
+ };
+
+ f["find"] += [](dir_paths vs, value v)
+ {
+ return find (vs.begin (), vs.end (),
+ convert<dir_path> (move (v))) != vs.end ();
+ };
+
+ // $find_index(<paths>, <path>)
+ // $find_index(<dir_paths>, <dir_path>)
+ //
+ // Return the index of the first element in the path sequence that is
+ // equal to the specified path or $size(<paths>) if none is found. Note
+ // that on hosts with a case-insensitive filesystem the comparison is
+ // case-insensitive.
+ //
+ f["find_index"] += [](paths vs, value v)
+ {
+ auto i (find (vs.begin (), vs.end (), convert<path> (move (v))));
+ return i != vs.end () ? i - vs.begin () : vs.size ();
+ };
+
+ f["find_index"] += [](dir_paths vs, value v)
+ {
+ auto i (find (vs.begin (), vs.end (), convert<dir_path> (move (v))));
+ return i != vs.end () ? i - vs.begin () : vs.size ();
+ };
+
// $path.match(<val>, <pat> [, <start>])
//
// Match a filesystem entry name against a name pattern (both are strings),
diff --git a/libbuild2/functions-string.cxx b/libbuild2/functions-string.cxx
index 4a03a5e..a41449a 100644
--- a/libbuild2/functions-string.cxx
+++ b/libbuild2/functions-string.cxx
@@ -8,6 +8,32 @@ using namespace std;
namespace build2
{
+ static size_t
+ find_index (const strings& vs, value&& v, optional<names>&& fs)
+ {
+ bool ic (false);
+ if (fs)
+ {
+ for (name& f: *fs)
+ {
+ string s (convert<string> (move (f)));
+
+ if (s == "icase")
+ ic = true;
+ else
+ throw invalid_argument ("invalid flag '" + s + "'");
+ }
+ }
+
+ auto i (find_if (vs.begin (), vs.end (),
+ [ic, y = convert<string> (move (v))] (const string& x)
+ {
+ return (ic ? icasecmp (x, y) : x.compare (y)) == 0;
+ }));
+
+ return i != vs.end () ? i - vs.begin () : vs.size ();
+ };
+
void
string_functions (function_map& m)
{
@@ -135,6 +161,36 @@ namespace build2
return v;
};
+ // $find(<strings>, <string>[, <flags>])
+ //
+ // Return true if the string sequence contains the specified string.
+ //
+ // The following flags are supported:
+ //
+ // icase - compare ignoring case
+ //
+ // See also $regex.find_{match,search}().
+ //
+ f["find"] += [](strings vs, value v, optional<names> fs)
+ {
+ return find_index (vs, move (v), move (fs)) != vs.size ();
+ };
+
+ // $find_index(<strings>, <string>[, <flags>])
+ //
+ // Return the index of the first element in the string sequence that
+ // is equal to the specified string or $size(<strings>) if none is
+ // found.
+ //
+ // The following flags are supported:
+ //
+ // icase - compare ignoring case
+ //
+ f["find_index"] += [](strings vs, value v, optional<names> fs)
+ {
+ return find_index (vs, move (v), move (fs));
+ };
+
// String-specific overloads from builtins.
//
function_family b (m, "builtin");
diff --git a/tests/function/builtin/testscript b/tests/function/builtin/testscript
index bbfd4e5..3c430d7 100644
--- a/tests/function/builtin/testscript
+++ b/tests/function/builtin/testscript
@@ -100,6 +100,20 @@
$* <'print $sort([uint64s] 0 2 1 000, dedup)' >'0 1 2' : dedup
}
+: find
+:
+{
+ $* <'print $find([uint64s] 1 2 3, 2)' >'true' : basics-true
+ $* <'print $find([uint64s] 1 2 3, 0)' >'false' : basics-false
+}
+
+: find_index
+:
+{
+ $* <'print $find_index([int64s] -1 -2 -3, -2)' >'1' : basics-true
+ $* <'print $find_index([int64s] -1 -2 -3, 0)' >'3' : basics-false
+}
+
: getenv
:
{
diff --git a/tests/function/name/testscript b/tests/function/name/testscript
index 6222167..4588e1d 100644
--- a/tests/function/name/testscript
+++ b/tests/function/name/testscript
@@ -49,6 +49,20 @@
: sort
:
{
- $* <'print $sort( d/t{a} t{c b} d/t{a})' >'t{b} t{c} d/t{a} d/t{a}' : basics
- $* <'print $sort( d/t{a} t{c b} d/t{a}, dedup)' >'t{b} t{c} d/t{a}' : dedup
+ $* <'print $sort(d/t{a} t{c b} d/t{a})' >'t{b} t{c} d/t{a} d/t{a}' : basics
+ $* <'print $sort(d/t{a} t{c b} d/t{a}, dedup)' >'t{b} t{c} d/t{a}' : dedup
+}
+
+: find
+:
+{
+ $* <'print $find([names] d/t{a} t{a b}, t{a})' >'true' : basics-true
+ $* <'print $find([names] d/t{a} t{a b}, d/t{b})' >'false' : basics-false
+}
+
+: find_index
+:
+{
+ $* <'print $find_index([names] d/t{a} t{a b}, t{a})' >'1' : basics-true
+ $* <'print $find_index([names] d/t{a} t{a b}, d/t{b})' >'3' : basics-false
}
diff --git a/tests/function/path/testscript b/tests/function/path/testscript
index 6219f3c..c58bbf8 100644
--- a/tests/function/path/testscript
+++ b/tests/function/path/testscript
@@ -158,6 +158,20 @@ if! $posix
$* <'print $size([dir_path] )' >'0' : dir-zero
}
+: find
+:
+{
+ $* <'print $find([paths] x y z, y)' >'true' : basics-true
+ $* <'print $find([paths] x y z, a)' >'false' : basics-false
+}
+
+: find_index
+:
+{
+ $* <'print $find_index([dir_paths] x y z, y)' >'1' : basics-true
+ $* <'print $find_index([dir_paths] x y z, a)' >'3' : basics-false
+}
+
: invalid-path
:
p = ($posix ? /../foo : 'c:/../foo');
diff --git a/tests/function/string/testscript b/tests/function/string/testscript
index 00835ce..364ce42 100644
--- a/tests/function/string/testscript
+++ b/tests/function/string/testscript
@@ -46,3 +46,19 @@
$* <'print $size([string] abc)' >'3' : basics
$* <'print $size([string] )' >'0' : zero
}
+
+: find
+:
+{
+ $* <'print $find([strings] x y z, y)' >'true' : basics-true
+ $* <'print $find([strings] x y z, Y)' >'false' : basics-false
+ $* <'print $find([strings] x y z, Y, icase)' >'true' : icase
+}
+
+: find_index
+:
+{
+ $* <'print $find_index([strings] x y z, y)' >'1' : basics-true
+ $* <'print $find_index([strings] x y z, Y)' >'3' : basics-false
+ $* <'print $find_index([strings] x y z, Y, icase)' >'1' : icase
+}