summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authordteske <dteske@FreeBSD.org>2016-02-03 04:02:50 +0000
committerdteske <dteske@FreeBSD.org>2016-02-03 04:02:50 +0000
commit0129d4cd2c7ad3bc5d278e7ac95f23ffbe04166f (patch)
tree1618decdbc535b78dd31aa748bd950646e9f0c37 /usr.sbin
parentb2bf30d1a948ddce18a8a4178be88dde5ec18c69 (diff)
downloadFreeBSD-src-0129d4cd2c7ad3bc5d278e7ac95f23ffbe04166f.zip
FreeBSD-src-0129d4cd2c7ad3bc5d278e7ac95f23ffbe04166f.tar.gz
f_substr(): Optimized recipe if running under bash
This makes runnig f_substr() faster than it was when running under bash, but both sh and dash are still faster when using the non-bash recipe which features dynamically unrolled loops.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bsdconfig/share/strings.subr173
1 files changed, 104 insertions, 69 deletions
diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr
index f9e33c7..f33f4df 100644
--- a/usr.sbin/bsdconfig/share/strings.subr
+++ b/usr.sbin/bsdconfig/share/strings.subr
@@ -67,52 +67,58 @@ f_isinteger()
# Similar to awk(1)'s substr(), return length substring of string that begins
# at start position counted from 1.
#
-f_substr()
-{
- local OPTIND=1 OPTARG __flag __var_to_set=
- while getopts v: __flag; do
- case "$__flag" in
- v) __var_to_set="$OPTARG" ;;
+case "$BASH_VERSION" in
+*?*)
+ f_substr()
+ {
+ local __var_to_set=
+ case "$1" in
+ -v) __var_to_set="$2"; shift 2 ;;
+ -v?*) __var_to_set="${2#-v}"; shift 1 ;;
esac
- done
- shift $(( $OPTIND - 1 ))
-
- local __tmp="$1" __start="${2:-1}" __size="$3"
- local __tbuf __tbuf_len __trim __trimq
+ local __tmp="$1" __start="${2:-1}" __len="$3"
+ [ "$__start" -gt 0 ] 2> /dev/null &&
+ __start=$(( $__start - 1 ))
+ if [ ! "$__var_to_set" ]; then
+ eval echo \"\${__tmp:\$__start${__len:+:\$__len}}\"
+ return $?
+ fi
+ if [ "$__len" ]; then
+ eval $__var_to_set=\"\${__tmp:\$__start:\$__len}\"
+ else
+ eval $__var_to_set=\"\${__tmp:\$__start}\"
+ fi
+ }
+ ;;
+*)
+ # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above
+ f_substr()
+ {
+ local OPTIND=1 OPTARG __flag __var_to_set=
+ while getopts v: __flag; do
+ case "$__flag" in
+ v) __var_to_set="$OPTARG" ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
- if [ ! "$__tmp" ]; then
- [ "$__var_to_set" ] && setvar "$__var_to_set" ""
- return ${SUCCESS:-0}
- fi
- [ "$__start" -ge 1 ] 2> /dev/null || __start=1
- if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then
- [ "$__var_to_set" ] && setvar "$__var_to_set" ""
- return ${FAILURE:-1}
- fi
+ local __tmp="$1" __start="${2:-1}" __size="$3"
+ local __tbuf __tbuf_len __trim __trimq
- __trim=$(( $__start - 1 ))
- while [ $__trim -gt 0 ]; do
- __tbuf="?"
- __tbuf_len=1
- while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]; do
- __tbuf="$__tbuf?"
- __tbuf_len=$(( $__tbuf_len + 1 ))
- done
- __trimq=$(( $__trim / $__tbuf_len ))
- __trim=$(( $__trim - $__tbuf_len * $__trimq ))
- while [ $__trimq -gt 0 ]; do
- __tmp="${__tmp#$__tbuf}"
- __trimq=$(( $__trimq - 1 ))
- done
- done
+ if [ ! "$__tmp" ]; then
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return ${SUCCESS:-0}
+ fi
+ [ "$__start" -ge 1 ] 2> /dev/null || __start=1
+ if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return ${FAILURE:-1}
+ fi
- local __tmp_size=${#__tmp}
- local __mask __mask_len
- __trim=$(( $__tmp_size - ${__size:-$__tmp_size} ))
- while [ $__trim -gt 0 ]; do
- __tbuf="?"
- __tbuf_len=1
- if [ $__trim -le $__size ]; then
+ __trim=$(( $__start - 1 ))
+ while [ $__trim -gt 0 ]; do
+ __tbuf="?"
+ __tbuf_len=1
while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]
do
__tbuf="$__tbuf?"
@@ -121,37 +127,66 @@ f_substr()
__trimq=$(( $__trim / $__tbuf_len ))
__trim=$(( $__trim - $__tbuf_len * $__trimq ))
while [ $__trimq -gt 0 ]; do
- __tmp="${__tmp%$__tbuf}"
+ __tmp="${__tmp#$__tbuf}"
__trimq=$(( $__trimq - 1 ))
done
- else
- __mask="$__tmp"
- while [ $__tbuf_len -lt $(( $__size / $__tbuf_len )) ]
- do
- __tbuf="$__tbuf?"
- __tbuf_len=$(( $__tbuf_len + 1 ))
- done
- __trimq=$(( $__size / $__tbuf_len ))
- if [ $(( $__trimq * $__tbuf_len )) -ne $__size ]; then
- __tbuf="$__tbuf?"
- __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+
+ local __tmp_size=${#__tmp}
+ local __mask __mask_len
+ __trim=$(( $__tmp_size - ${__size:-$__tmp_size} ))
+ while [ $__trim -gt 0 ]; do
+ __tbuf="?"
+ __tbuf_len=1
+ if [ $__trim -le $__size ]; then
+ while [ $__tbuf_len -lt $((
+ $__trim / $__tbuf_len
+ )) ]; do
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+ __trimq=$(( $__trim / $__tbuf_len ))
+ __trim=$(( $__trim - $__tbuf_len * $__trimq ))
+ while [ $__trimq -gt 0 ]; do
+ __tmp="${__tmp%$__tbuf}"
+ __trimq=$(( $__trimq - 1 ))
+ done
+ else
+ __mask="$__tmp"
+ while [ $__tbuf_len -lt $((
+ $__size / $__tbuf_len
+ )) ]; do
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+ __trimq=$(( $__size / $__tbuf_len ))
+ if [ $__size -ne $((
+ $__trimq * $__tbuf_len
+ )) ]; then
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ fi
+ __mask_len=$((
+ $__tmp_size - $__tbuf_len * $__trimq
+ ))
+ __trim=$((
+ $__tmp_size - $__mask_len - $__size
+ ))
+ while [ $__trimq -gt 0 ]; do
+ __mask="${__mask#$__tbuf}"
+ __trimq=$(( $__trimq - 1 ))
+ done
+ __tmp="${__tmp%"$__mask"}"
fi
- __mask_len=$(( $__tmp_size - $__tbuf_len * $__trimq ))
- __trim=$(( $__tmp_size - $__mask_len - $__size ))
- while [ $__trimq -gt 0 ]; do
- __mask="${__mask#$__tbuf}"
- __trimq=$(( $__trimq - 1 ))
- done
- __tmp="${__tmp%"$__mask"}"
- fi
- done
+ done
- if [ "$__var_to_set" ]; then
- setvar "$__var_to_set" "$__tmp"
- else
- echo "$__tmp"
- fi
-}
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__tmp"
+ else
+ echo "$__tmp"
+ fi
+ }
+esac
# f_sprintf $var_to_set $format [$arguments ...]
#
OpenPOWER on IntegriCloud