diff options
author | dteske <dteske@FreeBSD.org> | 2016-02-03 04:02:50 +0000 |
---|---|---|
committer | dteske <dteske@FreeBSD.org> | 2016-02-03 04:02:50 +0000 |
commit | 0129d4cd2c7ad3bc5d278e7ac95f23ffbe04166f (patch) | |
tree | 1618decdbc535b78dd31aa748bd950646e9f0c37 /usr.sbin/bsdconfig | |
parent | b2bf30d1a948ddce18a8a4178be88dde5ec18c69 (diff) | |
download | FreeBSD-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/bsdconfig')
-rw-r--r-- | usr.sbin/bsdconfig/share/strings.subr | 173 |
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 ...] # |