changeset 718:2502e077d5e9

farray.sh: Implement "falist_set_unique()" that does not overwrite existing key-value pairs
author Franz Glasner <fzglas.hg@dom66.de>
date Fri, 04 Oct 2024 18:20:15 +0200
parents f4725ad5cd21
children b2757e72b517
files share/local-bsdtools/farray.sh tests/farray-alist.t
diffstat 2 files changed, 71 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/share/local-bsdtools/farray.sh	Fri Oct 04 17:18:14 2024 +0200
+++ b/share/local-bsdtools/farray.sh	Fri Oct 04 18:20:15 2024 +0200
@@ -1804,6 +1804,68 @@
 
 
 #:
+#: Map a key to a value but error if the alist contains already an item
+#: with the given key.
+#:
+#: Args:
+#:   $1 (str): The name of an existing alist.
+#:   $2, $3 ... (optional): A sequence of key-value pairs the alist will be
+#:                          populated with.
+#:
+#: Returns:
+#:   int: 0 (truthy) if the item got set, 1 (falsy) if there is already an
+#:        item with key `$1` in the alist
+#:
+#: Exit:
+#:   If one of the underlying arrays that implement the alist does not exist
+#:   or if an internal inconsistency will be detected.
+#:
+falist_set_unique() {
+    local __farr_name __farr_key __farr_value
+
+    local __farr_token __farr_objname __farr_keyname __farr_valname __farr_len
+    local __farr_idx __farr_elkey
+
+    _farr_alist_get_meta "$@"
+    shift
+
+    while [ $# -ne 0 ]; do
+        [ $# -lt 1 ] && _farr_fatal "missing key"
+        __farr_key="$1"
+        [ $# -lt 2 ] && _farr_fatal "missing value"
+        __farr_value="$2"
+
+        __farr_idx=1
+        while [ ${__farr_idx} -le ${__farr_len} ]; do
+            eval __farr_elkey=\"\$\{${__farr_keyname}_${__farr_idx}+SET\}\"
+            if [ -n "${__farr_elkey}" ]; then
+                eval __farr_elkey=\"\$\{${__farr_keyname}_${__farr_idx}\}\"
+                if [ "${__farr_elkey}" = "${__farr_key}" ]; then
+                    return 1
+                fi
+            else
+                _farr_fatal "key unexpectedly unset (index ${__farr_idx})"
+            fi
+            __farr_idx=$((__farr_idx + 1))
+        done
+        #
+        # Not yet found: "append" ..
+        #
+        # NOTE: __farr_idx here already is the new correct length
+        #
+        __farr_len=${__farr_idx}
+        #   ... the key/value pairs to storage
+        eval ${__farr_keyname}_${__farr_len}="$(_farr_quote_for_eval "${__farr_key}")"
+        eval ${__farr_valname}_${__farr_len}="$(_farr_quote_for_eval "${__farr_value}")"
+        #   ... the new length
+        eval ${__farr_objname}__=${__farr_len}
+        shift 2
+    done
+    return 0
+}
+
+
+#:
 #: Update an alist from another alist.
 #:
 #: Key-values from the other alist are given precedence.
--- a/tests/farray-alist.t	Fri Oct 04 17:18:14 2024 +0200
+++ b/tests/farray-alist.t	Fri Oct 04 18:20:15 2024 +0200
@@ -90,6 +90,8 @@
   2 (no-eol)
 
   $ falist_set LIST K2 "V2 2"
+  $ falist_set_unique LIST K2 "V2 duplicate"
+  [1]
   $ falist_set LIST K3 $'" 111222333" \\\'444555 '    # '
   $ falist_debug LIST
   DEBUG: alist `LIST' has length 3
@@ -117,7 +119,13 @@
   ERROR: object `NON_EXISTING_LIST' not created properly: token empty
   $ echo "${_var}"
   -1
-
+  $ falist_set_unique LIST K4 "V4"
+  $ falist_debug LIST
+  DEBUG: alist `LIST' has length 4
+  DEBUG:     `K1' -> `V1'
+  DEBUG:     `K2' -> `V2 2'
+  DEBUG:     `K3' -> `" 111222333" \'444555 '
+  DEBUG:     `K4' -> `V4'
   $ falist_destroy LIST
   $ check_no_alist_artifacts