scripts/library: add human_to_size
This is a bash wrapper around an awk function that parses human readable sizes and returns their representative values in bytes, as a string. A small test harness is added to validate the functionality. Signed-off-by: Dave Reisner <dreisner@archlinux.org>
This commit is contained in:
parent
e183522e31
commit
b58489d29a
|
@ -41,6 +41,8 @@ test-vercmp: test/util src/util
|
||||||
test-parseopts: test/scripts scripts
|
test-parseopts: test/scripts scripts
|
||||||
$(BASH_SHELL) $(top_srcdir)/test/scripts/parseopts_test.sh \
|
$(BASH_SHELL) $(top_srcdir)/test/scripts/parseopts_test.sh \
|
||||||
$(top_srcdir)/scripts/library/parseopts.sh
|
$(top_srcdir)/scripts/library/parseopts.sh
|
||||||
|
$(BASH_SHELL) $(top_srcdir)/test/scripts/human_to_size_test.sh \
|
||||||
|
$(top_srcdir)/scripts/library/human_to_size.sh
|
||||||
|
|
||||||
# create the pacman DB and cache directories upon install
|
# create the pacman DB and cache directories upon install
|
||||||
install-data-local:
|
install-data-local:
|
||||||
|
|
|
@ -27,7 +27,8 @@ EXTRA_DIST = \
|
||||||
|
|
||||||
LIBRARY = \
|
LIBRARY = \
|
||||||
library/output_format.sh \
|
library/output_format.sh \
|
||||||
library/parseopts.sh
|
library/parseopts.sh \
|
||||||
|
library/human_to_size.sh
|
||||||
|
|
||||||
# Files that should be removed, but which Automake does not know.
|
# Files that should be removed, but which Automake does not know.
|
||||||
MOSTLYCLEANFILES = $(bin_SCRIPTS)
|
MOSTLYCLEANFILES = $(bin_SCRIPTS)
|
||||||
|
|
|
@ -27,3 +27,11 @@ Reccommended Usage:
|
||||||
Returns:
|
Returns:
|
||||||
0: parse success
|
0: parse success
|
||||||
1: parse failure (error message supplied)
|
1: parse failure (error message supplied)
|
||||||
|
|
||||||
|
human_to_size.sh:
|
||||||
|
A function to convert human readable sizes (such as "5.3 GiB") to raw byte
|
||||||
|
equivalents. base10 and base2 suffixes are supported, case sensitively. If
|
||||||
|
successful, the converted byte value is written to stdout and the function
|
||||||
|
returns 0. If an error occurs, nothing in written and the function returns 1.
|
||||||
|
Results may be inaccurate when using a broken implementation of awk, such
|
||||||
|
as mawk or busybox awk.
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
human_to_size() {
|
||||||
|
awk -v human="$1" '
|
||||||
|
function trim(s) {
|
||||||
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", s)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_units(units) {
|
||||||
|
if (!units || units == "B")
|
||||||
|
return 1
|
||||||
|
if (match(units, /^.iB$/))
|
||||||
|
return 1024
|
||||||
|
if (match(units, /^.B$/))
|
||||||
|
return 1000
|
||||||
|
if (length(units) == 1)
|
||||||
|
return 1024
|
||||||
|
|
||||||
|
# parse failure: invalid base
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_scale(s) {
|
||||||
|
return index("BKMGTPE", s) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function isnumeric(string) {
|
||||||
|
return match(string, /^[-+]?[[:digit:]]*(\.[[:digit:]]*)?/)
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
# peel off the leading number as the size, fail on invalid number
|
||||||
|
human = trim(human)
|
||||||
|
if (isnumeric(human))
|
||||||
|
size = substr(human, RSTART, RLENGTH)
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
# the trimmed remainder is assumed to be the units
|
||||||
|
units = trim(substr(human, RLENGTH + 1))
|
||||||
|
|
||||||
|
base = parse_units(units)
|
||||||
|
if (base < 0)
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
scale = parse_scale(substr(units, 1, 1))
|
||||||
|
if (scale < 0)
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
printf "%d\n", size * base^scale + (size + 0 > 0 ? 0.5 : -0.5)
|
||||||
|
}'
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
check_SCRIPTS = \
|
check_SCRIPTS = \
|
||||||
parseopts_test.sh
|
parseopts_test.sh \
|
||||||
|
human_to_size_test.sh
|
||||||
|
|
||||||
noinst_SCRIPTS = $(check_SCRIPTS)
|
noinst_SCRIPTS = $(check_SCRIPTS)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# source the library function
|
||||||
|
if [[ -z $1 || ! -f $1 ]]; then
|
||||||
|
printf "error: path to human_to_size library not provided or does not exist\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
. "$1"
|
||||||
|
|
||||||
|
if ! type -t human_to_size >/dev/null; then
|
||||||
|
printf 'human_to_size function not found\n'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
parse_hts() {
|
||||||
|
local input=$1 expected=$2 result
|
||||||
|
|
||||||
|
(( ++testcount ))
|
||||||
|
|
||||||
|
result=$(human_to_size "$1")
|
||||||
|
if [[ $result = "$expected" ]]; then
|
||||||
|
(( ++pass ))
|
||||||
|
else
|
||||||
|
(( ++fail ))
|
||||||
|
printf '[TEST %3s]: FAIL\n' "$testcount"
|
||||||
|
printf ' input: %s\n' "$input"
|
||||||
|
printf ' output: %s\n' "$result"
|
||||||
|
printf ' expected: %s\n' "$expected"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
summarize() {
|
||||||
|
if (( !fail )); then
|
||||||
|
printf 'All %s tests successful\n' "$testcount"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
printf '%s of %s tests failed\n' "$fail" "$testcount"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap 'summarize' EXIT
|
||||||
|
|
||||||
|
printf 'Beginning human_to_size tests\n'
|
||||||
|
|
||||||
|
# parse_hts <input> <expected output>
|
||||||
|
|
||||||
|
parse_hts '1MiB' 1048576
|
||||||
|
|
||||||
|
parse_hts '10XiB' ''
|
||||||
|
|
||||||
|
parse_hts '10 MiB' 10485760
|
||||||
|
|
||||||
|
parse_hts '10 XiB' ''
|
||||||
|
|
||||||
|
parse_hts '.1 TiB' 109951162778
|
||||||
|
|
||||||
|
parse_hts ' -3 KiB ' -3072
|
||||||
|
|
||||||
|
parse_hts 'foo3KiB' ''
|
||||||
|
|
||||||
|
parse_hts '3KiBfoo' ''
|
||||||
|
|
||||||
|
parse_hts '3kib' ''
|
||||||
|
|
||||||
|
parse_hts '+1KiB' 1024
|
||||||
|
|
||||||
|
parse_hts '+1.0 KiB' 1024
|
||||||
|
|
||||||
|
parse_hts '1MB' 1000000
|
||||||
|
|
||||||
|
parse_hts '1M' 1048576
|
||||||
|
|
||||||
|
parse_hts ' 1 G ' 1073741824
|
||||||
|
|
||||||
|
parse_hts '1Q' ''
|
Loading…
Reference in New Issue