changeset 571:a6cebc41a659

farray.sh: Implement falist_trydel() to remove a key/value from an alist
author Franz Glasner <fzglas.hg@dom66.de>
date Fri, 13 Sep 2024 23:04:17 +0200
parents 594390cc2e28
children 687d458b27f3
files share/local-bsdtools/farray.sh
diffstat 1 files changed, 102 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/share/local-bsdtools/farray.sh	Fri Sep 13 23:01:51 2024 +0200
+++ b/share/local-bsdtools/farray.sh	Fri Sep 13 23:04:17 2024 +0200
@@ -1372,6 +1372,90 @@
 
 
 #:
+#: Internal helper to delete an item from an alist storage.
+#:
+#: Args:
+#:   $1 (str): The name of the storage object
+#:   $2 (int): The current length of the storage object (i.e. the current
+#:             length of the alist)
+#:   $3 (int): The storage index that will be deleted
+#:
+#: Returns:
+#:   int: Always 0
+#:
+#: Important:
+#:   This is an internal function. No index and other storage consistency
+#:   checks are done.
+#:
+#: Note:
+#:   The implementation is very similar to `farray_del`.
+#:   But the new length must be managed by the caller.
+#:
+_farr_alist_del_storage_at_index() {
+    local __farr_storage_name __farr_storage_length __farr_storage_index
+
+    local __farr_idx
+
+    __farr_storage_name="$1"
+    __farr_storage_length="$2"
+    __farr_storage_index="$3"
+
+    __farr_idx=${__farr_storage_index}
+    while [ ${__farr_idx} -lt ${__farr_storage_length} ] ; do
+        # copy the following value to the current index
+        eval ${__farr_storage_name}_${__farr_idx}=\"\$\{${__farr_storage_name}_$((__farr_idx + 1))\}\"
+        __farr_idx=$((__farr_idx + 1))
+    done
+    # Drop the last item
+    eval unset ${__farr_storage_name}_${__farr_idx}
+    return 0
+}
+
+
+#:
+#: Try to delete an item with a given key from the alist.
+#:
+#: Args:
+#:   $1 (str): The name of the alist.
+#:   $2: The key of the key-value pair to delete to
+#:
+#: Returns:
+#:   int: 0 if the key has been found and is deleted,
+#:        1 if the key has not been found.
+#:
+falist_trydel() {
+    local __farr_name __farr_delkey
+
+    local __farr_token __farr_objname __farr_keyname __farr_valname __farr_len
+    local __farr_idx __farr_curkey
+
+    _farr_alist_get_meta "$@"
+    [ $# -lt 2 ] && _farr_fatal "missing key"
+    __farr_delkey="$2"
+
+    __farr_idx=1
+    while [ ${__farr_idx} -le ${__farr_len} ] ; do
+        eval __farr_curkey=\"\$\{${__farr_keyname}_${__farr_idx}+SET\}\"
+        if [ -n "${__farr_curkey}" ]; then
+            eval __farr_curkey=\"\$\{${__farr_keyname}_${__farr_idx}\}\"
+            if [ "${__farr_curkey}" = "${__farr_delkey}" ]; then
+                _farr_alist_del_storage_at_index "${__farr_valname}" ${__farr_len} ${__farr_idx}
+                _farr_alist_del_storage_at_index "${__farr_keyname}" ${__farr_len} ${__farr_idx}
+                # Reduce the length by 1
+                eval ${__farr_objname}__=$((__farr_len - 1))
+                return 0
+            fi
+        else
+            _farr_fatal "key unexpectedly unset (index ${__farr_idx})"
+        fi
+        __farr_idx=$((__farr_idx + 1))
+    done
+    # Not found
+    return 1
+}
+
+
+#:
 #: Call a function for every key-value pair in an alist starting in index order.
 #:
 #: The function to be called must accept three or four arguments:
@@ -1633,6 +1717,24 @@
     if falist_destroy LIST ; then
         echo "DESTROY SUCCEEDED (ERROR)"
     fi
+
+    # Deletion of keys
+    falist_create LIST
+    falist_set LIST 'key 1' 'value 1'
+    falist_set LIST 'key 2' 'value 2'
+    falist_set LIST 'key 3' 'value 3'
+    falist_set LIST 'key 4' 'value 4'
+    falist_set LIST 'key 5' 'value 5'
+    falist_trydel LIST 'key 1' || echo "cannot del key 1"
+    falist_trydel LIST 'key 5'  || echo "cannot del key 5"
+    falist_trydel LIST 'key 3' || echo "cannot del key 3"
+    [ "$(falist_print_length LIST)" -eq 2 ] || echo "length mismatch"
+    falist_get _var LIST 'key 2'
+    [ "$_var" = 'value 2' ] || echo "value mismatch"
+    falist_get _var LIST 'key 4'
+    [ "$_var" = 'value 4' ] || echo "value mismatch"
+    falist_destroy LIST
+
     # set
     echo "============================================================"
     echo "OK."