changeset 511:4186db70abe6

array.sh: REFACTOR: All functions that are value getters (get, tryget, find, length) set a variable now. This is similar to the shell's builtin "read". This is to behave better for errors: no subshells invoked: because $(foo bar) would invoke a subshell and prohibit proper fatal exits. BUGS: Name clases on variables. Check that _varname does not clash with a declared local.
author Franz Glasner <fzglas.hg@dom66.de>
date Sun, 01 Sep 2024 11:15:01 +0200
parents 5f8c4c4546b1
children 5cc6ea0ef965
files share/local-bsdtools/array.sh
diffstat 1 files changed, 122 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/share/local-bsdtools/array.sh	Sat Aug 31 23:20:03 2024 +0200
+++ b/share/local-bsdtools/array.sh	Sun Sep 01 11:15:01 2024 +0200
@@ -135,6 +135,41 @@
 }
 
 
+
+#:
+#: Get the length of an array and put it into a variable
+#:
+#: Args:
+#:   $1 (str): The name of the variable to put the length into
+#:   $2 (str): The name of the array.
+#:
+#: Returns:
+#:   0 (truthy) if the array exists,
+#:   1 (falsy) if the array does not exist
+#:
+array_length() {
+    local _varname _name
+
+    local _gvrname _l
+
+    [ $# -lt 1 ] && _array_fatal "missing variable name"
+    _varname=$1
+    [ $# -lt 2 ] && _array_fatal "missing array name"
+    _name=$2
+    _gvrname=${_farr_global_prefix}$2
+
+    # Check whether the variable already exists
+    eval _l=\${${_gvrname}__:-${_farr_unset}}
+
+    if [ "${_l}" = ${_farr_unset} ]; then
+	return 1
+    else
+        eval ${_varname}=${_l}
+        return 0
+    fi
+}
+
+
 #:
 #: Get the length of an array.
 #:
@@ -145,22 +180,20 @@
 #:   The number of elements of the array.
 #:   If the array does not exist the output is -1.
 #:
-array_length() {
+array_print_length() {
     local _name
 
-    local _gvrname _l
+    local _vn
 
     [ $# -lt 1 ] && _array_fatal "missing array name"
     _name=$1
-    _gvrname=${_farr_global_prefix}$1
 
-    # Check whether the variable already exists
-    eval _l=\${${_gvrname}__:-${_farr_unset}}
-
-    if [ "${_l}" = ${_farr_unset} ]; then
-	printf "%s" "-1"
+    if array_length _vn ${_name}; then
+        printf "%s" "${_vn}"
+        return 0
     else
-	printf "%s" "${_l}"
+        printf "%s" "-1"
+        return 1
     fi
 }
 
@@ -254,25 +287,25 @@
 
 
 #:
-#: Get an array value from a given index.
+#: Get an array value from a given index and put it into given variable.
 #:
 #: Args:
-#:   $1 (str): The name of the existing array
-#:   $2 (int): The index
-#:
-#: Output (stdout):
-#:   The value at index $2.
+#:   $1 (str): The name of the variable to put the value into
+#:   $2 (str): The name of the existing array
+#:   $3 (int): The index
 #:
 array_get() {
-    local _name _index
+    local _varname _name _index
 
     local _gvrname _l _value
 
-    [ $# -lt 1 ] && _array_fatal "missing array name"
-    _name=$1
-    _gvrname=${_farr_global_prefix}$1
-    [ $# -lt 2 ] && _array_fatal "missing array index"
-    _index=$2
+    [ $# -lt 1 ] && _array_fatal "missing variable name"
+    _varname=$1
+    [ $# -lt 2 ] && _array_fatal "missing array name"
+    _name=$2
+    _gvrname=${_farr_global_prefix}$2
+    [ $# -lt 3 ] && _array_fatal "missing array index"
+    _index=$3
 
     # Check whether the variable already exists
     eval _l=\${${_gvrname}__:-${_farr_unset}}
@@ -285,8 +318,52 @@
 	_array_fatal "array index out of bounds"
     fi
 
-    eval _value=\"\${${_gvrname}_${_index}}\"
-    printf "%s" "${_value}"
+    eval ${_varname}=\"\${${_gvrname}_${_index}}\"
+}
+
+
+#:
+#: Try to get an array value from a given index into a variable
+#:
+#: Args:
+#:   $1 (str): The name of the variable to put the value into
+#:   $2 (str): The name of the existing array
+#:   $3 (int): The index
+#:
+#: Returns:
+#:   0 (truthy) on success,
+#:   1 (falsy) if the given index is out of bounds (i.e. EOD)
+#:
+#: Exit:
+#:   Other errors (missing array name, missing index value) are considered
+#:   fatal and call `_array_fatal` (i.e. `exit`).
+#:
+array_tryget() {
+    local _varname _name _index
+
+    local _gvrname _l _value
+
+    [ $# -lt 1 ] && _array_fatal "missing variable name"
+    _varname=$1
+    [ $# -lt 2 ] && _array_fatal "missing array name"
+    _name=$2
+    _gvrname=${_farr_global_prefix}$2
+    [ $# -lt 3 ] && _array_fatal "missing array index"
+    _index=$3
+
+    # Check whether the variable already exists
+    eval _l=\${${_gvrname}__:-${_farr_unset}}
+    if [ "${_l}" = ${_farr_unset} ]; then
+	_array_fatal "array \`${_name}' does not exist"
+    fi
+
+    # check index range
+    if [ \( "${_index}" -lt 1 \) -o \( "${_index}" -gt ${_l} \) ]; then
+	return 1
+    fi
+
+    eval ${_varname}=\"\${${_gvrname}_${_index}}\"
+    return 0
 }
 
 
@@ -337,52 +414,6 @@
 
 
 #:
-#: Try to get an array value from a given index.
-#:
-#: Args:
-#:   $1 (str): The name of the existing array
-#:   $2 (int): The index
-#:
-#: Output (stdout):
-#:   The value at index $2.
-#:
-#: Returns:
-#:   0 (truthy) on success,
-#:   1 (falsy) if the given index is out of bounds (i.e. EOD)
-#:
-#: Exit:
-#:   Other errors (missing array name, missing index value) are considered
-#:   fatal and call `_array_fatal` (i.e. `exit`).
-#:
-array_tryget() {
-    local _name _index
-
-    local _gvrname _l _value
-
-    [ $# -lt 1 ] && _array_fatal "missing array name"
-    _name=$1
-    _gvrname=${_farr_global_prefix}$1
-    [ $# -lt 2 ] && _array_fatal "missing array index"
-    _index=$2
-
-    # Check whether the variable already exists
-    eval _l=\${${_gvrname}__:-${_farr_unset}}
-    if [ "${_l}" = ${_farr_unset} ]; then
-	_array_fatal "array \`${_name}' does not exist"
-    fi
-
-    # check index range
-    if [ \( "${_index}" -lt 1 \) -o \( "${_index}" -gt ${_l} \) ]; then
-	return 1
-    fi
-
-    eval _value=\"\${${_gvrname}_${_index}}\"
-    printf "%s" "${_value}"
-    return 0
-}
-
-
-#:
 #: Empty an existing array.
 #:
 #: Args:
@@ -491,10 +522,11 @@
 #: Try to find the index of a given value in an existing array.
 #:
 #: Args:
-#:   $1: The name of an existing array
-#:   $2: The value to search for
-#:   $3 (int, optional): The start index to search for (inclusive)
-#:   $4 (int, optional):  The index to stop (inclusive)
+#:   $1 (str): The name of a variable where to put the found index into
+#:   $2 (str): The name of an existing array
+#:   $3: The value to search for
+#:   $4 (int, optional): The start index to search for (inclusive)
+#:   $5 (int, optional):  The index to stop (inclusive)
 #:
 #: Output (stdout):
 #:   The index number where the value is found -- if any
@@ -505,15 +537,17 @@
 #:   - 1 (falsy) otherwise
 #:
 array_find() {
-    local _name _searched_value _start _end
+    local _varname _name _searched_value _start _end
 
-    local _gvrname _l _idx _existing_value
+    local _gvrname _l _sidx _existing_value
 
-    [ $# -lt 1 ] && _array_fatal "missing array name"
-    _name=$1
-    _gvrname=${_farr_global_prefix}$1
-    [ $# -lt 2 ] && _array_fatal "missing value to search for"
-    _searched_value="$2"
+    [ $# -lt 1 ] && _array_fatal "missing variable name"
+    _varname=$1
+    [ $# -lt 2 ] && _array_fatal "missing array name"
+    _name=$2
+    _gvrname=${_farr_global_prefix}$2
+    [ $# -lt 3 ] && _array_fatal "missing value to search for"
+    _searched_value="$3"
 
     # Check whether the variable already exists
     eval _l=\${${_gvrname}__:-${_farr_unset}}
@@ -521,17 +555,18 @@
 	_array_fatal "array \`${_name}' does not exist"
     fi
 
-    _start=${3-1}
-    _end=${4-${_l}}
+    _start=${4-1}
+    _end=${5-${_l}}
 
-    _idx=${_start}
-    while [ ${_idx} -le ${_end} ]; do
-        eval _existing_value=\"\${${_gvrname}_${_idx}}\"
+    _sidx=${_start}
+    while [ ${_sidx} -le ${_end} ]; do
+        eval _existing_value=\"\${${_gvrname}_${_sidx}}\"
         if [ "${_existing_value}" = "${_searched_value}" ]; then
-            printf "%d" ${_idx}
+            #printf "%d" ${_isdx}
+            eval ${_varname}=${_sidx}
             return 0
         fi
-	_idx=$((${_idx} + 1))
+	_sidx=$((${_sidx} + 1))
     done
     return 1
 }