commit: 449fed1c13525c8420b4366014ba34616cb20239
Author: Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Tue Jun 11 05:26:41 2024 +0000
Commit: Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Fri Jun 14 00:27:44 2024 +0000
URL:
https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=449fed1c
Add the is_anyof() and is_subset() functions
Examples follow.
is_anyof y x y z # returns 0
is_anoyf y x w z # returns 1
is_subset x y -- x y z # returns 0
is_subset x y z -- z y x # returns 0
is_subset x y -- x w z # returns 1
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
functions.sh | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
test-functions | 49 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+)
diff --git a/functions.sh b/functions.sh
index 7d146c8..166f184 100644
--- a/functions.sh
+++ b/functions.sh
@@ -446,6 +446,28 @@ is_int()
esac
}
+#
+# Determines whether the first parameter matches any of the parameters that
+# follow it.
+#
+is_anyof()
+{
+ local arg needle
+
+ if [ "$#" -eq 0 ]; then
+ warn "is_anyof: too few arguments (got $#, expected at least 1)"
+ else
+ needle=$1
+ shift
+ for arg; do
+ if [ "${arg}" = "${needle}" ]; then
+ return
+ fi
+ done
+ fi
+ false
+}
+
#
# Takes the first parameter as a reference file/directory then determines
# whether any of the following parameters refer to newer files/directories.
@@ -468,6 +490,46 @@ is_older_than()
| read -r _
}
+#
+# Collects the intersection of the parameters up to - but not including - a
+# sentinel value then determines whether the resulting set is a subset of the
+# interection of the remaining parameters. If the SENTINEL variable is set and
+# non-empty, it shall be taken as the value of the sentinel. Otherwise, the
+# value of the sentinel shall be defined as <hyphen-dash><hyphen-dash>. If the
+# sentinel value is not encountered or if either set is empty then the returm
+# value shall be greater than 1.
+#
+is_subset()
+{
+ SENTINEL=${SENTINEL:-'--'} awk -f - -- "$@" <<-'EOF'
+ BEGIN {
+ argc = ARGC
+ ARGC = 1
+ for (i = 1; i < argc; i++) {
+ word = ARGV[i]
+ if (word == ENVIRON["SENTINEL"]) {
+ break
+ } else {
+ set1[word] = ""
+ }
+ }
+ if (i == 1 || argc - i < 2) {
+ exit 1
+ }
+ for (i++; i < argc; i++) {
+ word = ARGV[i]
+ set2[word] = ""
+ }
+ for (word in set2) {
+ delete set1[word]
+ }
+ for (word in set1) {
+ exit 1
+ }
+ }
+ EOF
+}
+
#
# Considers one or more pathnames and prints the one having the newest
# modification time. If at least one parameter is provided, all parameters
shall
diff --git a/test-functions b/test-functions
index 1a2eb81..0b987ab 100755
--- a/test-functions
+++ b/test-functions
@@ -575,6 +575,53 @@ test_parallel_run() {
iterate_tests 4 "$@"
}
+test_is_anyof() {
+ set -- \
+ ge 1 N/A N/A N/A \
+ ge 1 x N/A N/A \
+ ge 1 x y N/A \
+ ge 1 x y z \
+ eq 0 x x N/A \
+ eq 0 x x y \
+ eq 0 x y x
+
+ callback() {
+ shift
+ test_description="is_anyof $(quote_args "$@")"
+ is_anyof "$@"
+ }
+
+ iterate_tests 5 "$@"
+}
+
+test_is_subset() {
+ set -- \
+ ge 1 N/A N/A N/A N/A N/A \
+ ge 1 -- N/A N/A N/A N/A \
+ ge 1 -- -- N/A N/A N/A \
+ ge 1 -- x N/A N/A N/A \
+ ge 1 x -- N/A N/A N/A \
+ ge 1 x y N/A N/A N/A \
+ ge 1 x y x N/A N/A \
+ eq 0 x -- x N/A N/A \
+ eq 0 x -- x y N/A \
+ eq 0 x -- y x N/A \
+ eq 0 x y -- x y \
+ eq 0 x y -- y x \
+ ge 1 x y -- x z \
+ ge 1 y x -- z x \
+ ge 1 x z -- x y \
+ ge 1 z x -- y x
+
+ callback() {
+ shift
+ test_description="is_subset $(quote_args "$@")"
+ is_subset "$@"
+ }
+
+ iterate_tests 7 "$@"
+}
+
iterate_tests() {
slice_width=$1
shift
@@ -641,6 +688,8 @@ test_trim || rc=1
test_hr || rc=1
test_whenceforth || rc=1
test_parallel_run || rc=1
+test_is_anyof || rc=1
+test_is_subset || rc=1
cleanup_tmpdir