env/utils/scripts/color-hash.ksh

84 lines
1.5 KiB
Bash
Raw Normal View History

function _color_hash_djb2
{
local c h s
s=$1
h=${2:-5381}
while (( ${#s} > 0 )); do
c=0x${s%${s#??}}
s=${s#??}
h=$(( ((($h << 5) + $h) ^ $c) & 0xffff ))
done
print -nr -- $h
}
function _color_hash_fnv1
{
local c h s
s=$1
h=${2:-2166136261}
while (( ${#s} > 0 )); do
c=0x${s%${s#??}}
s=${s#??}
h=$(( (($h << 24) + ($h << 8) +
($h << 7) + ($h << 4) + ($h << 1) + $h) & 0xffffffff ))
h=$(( $h ^ $c ))
done
# xor-fold to 16 bits
print -nr -- $(( ($h >> 16) ^ ($h & 0xffff) ))
}
function _color_hash_fnv1a
{
local c h s
s=$1
h=${2:-2166136261}
while (( ${#s} > 0 )); do
c=0x${s%${s#??}}
s=${s#??}
h=$(( $h ^ $c ))
h=$(( (($h << 24) + ($h << 8) +
($h << 7) + ($h << 4) + ($h << 1) + $h) & 0xffffffff ))
done
# xor-fold to 16 bits
print -nr -- $(( ($h >> 16) ^ ($h & 0xffff) ))
}
function color_hash
{
local bright impl flag h n s
bright=false
impl=_color_hash_fnv1a
while getopts bi: flag; do
case $flag in
b) bright=true ;;
i) if [[ $OPTARG != @(djb2|fnv1|fnv1a) ]]; then
return 1
fi
impl=_color_hash_$OPTARG
;;
*) return 1 ;;
esac
done
shift $(($OPTIND - 1))
h=
s=$(print -nr -- "$1" | od -A n -t x1 | tr -d '[:space:]*')
while :; do
h=$($impl "$s" $h)
# Avoid modulo bias.
(( $h >= 4 )) && break
done
h=$(( $h % 12 ))
if $bright; then
# $h < 6 ? 8 + 1 + $h : 8 + 1 + $h - 6
n=$(( $h + ($h < 6 ? 9 : 3) ))
else
# $h < 6 ? 1 + $h : 8 + 1 + $h - 6
n=$(( $h + ($h < 6 ? 1 : 3) ))
fi
print -nr -- "$n"
}