#!/bin/bash

# This is my attempt for a hash library
HashVarnamePrefix=__hash__

#===  FUNCTION  ================================================================
#         NAME: hash_set
#  DESCRIPTION: Set the key for the given hash to a value: hash[key] = value
# PARAMETER  1: Name of the hash
# PARAMETER  2: Name of the key
# PARAMETER  3: Value to set
#===  FUNCTION  ================================================================
function hash_set #{{{
{
	eval "${HashVarnamePrefix}${1}_${2}=\"${3}\""
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_get
#  DESCRIPTION: Gets the value of a given hash and key: OUTPUT = hash[key]
# PARAMETER  1: Name of the hash
# PARAMETER  2: Name of the key
#       OUTPUT: The stored value
#===============================================================================
function hash_get #{{{
{
	eval "echo \"\$${HashVarnamePrefix}${1}_${2}\""
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_copy
#  DESCRIPTION: Copies the values for one hash and key to another hash and key:
#               hash1[key1] = hash2[key2]
# PARAMETER  1: Name of the hash to copy to
# PARAMETER  2: Name of the key to copy to
# PARAMETER  3: Name of the hash to copy from
# PARAMETER  4: Name of the key to copy from
#===============================================================================
function hash_copy #{{{
{
	eval "${HashVarnamePrefix}${1}_${2}=\"\$${HashVarnamePrefix}${3}_${4}\""
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_dup
#  DESCRIPTION: Copy the value of the first key of a given hash to the rest of
#               the keys in that hash: hash[keyN-1]=hash[key2]=...hash[key1] 
# PARAMETER  1: Name of the hash
# PARAMETER  2: Name of the first key
# PARAMETER  3: Name of the second key
# PARAMETER  N: Name of the Nth key
#===============================================================================
function hash_dup #{{{
{
	local hash_name="$1"
	local key_name="$2"
	shift 2
	until [ ${#} -le 0 ]
	do
		eval "${HashVarnamePrefix}${hash_name}_${1}=\"\$${HashVarnamePrefix}${hash_name}_${key_name}\""
		shift
	done
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_unset
#  DESCRIPTION: Unsets the given key for the given hash: unset hash[key]
# PARAMETER  1: Name of the hash
# PARAMETER  2: Name of the key
#===============================================================================
function hash_unset #{{{
{
	eval "unset ${HashVarnamePrefix}${1}_${2}"
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_get_ref
#  DESCRIPTION: Returns the name of the (global) variable that represents the
#               hash and key and that holds the value: Similar to:
#               OUT = &hash[key]
# PARAMETER  1: Name of the hash
# PARAMETER  2: Name of the key
#       OUTPUT: The name of the global storage variable
#===============================================================================
function hash_get_ref #{{{
{
	eval "echo \"${HashVarnamePrefix}${1}_${2}\""
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_call
#  DESCRIPTION: Treat the name stored as a value as a function name and call
#               this function with the given parameters. Similar to:
#               $$hash[key](param1, param2, ...)
# PARAMETER  1: Name of the hash
# PARAMETER  2: Name of the key
# PARAMETER  3: The first parameter to pass
# PARAMETER  4: The second parameter to pass
# PARAMETER  N: The Nth parameter to pass
#===============================================================================
function hash_call #{{{
{
	local hash=$1
	local key=$2
	shift 2
	eval "eval \"\$${HashVarnamePrefix}${hash}_${key} \\\"\\\$@\\\"\""
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_isset
#  DESCRIPTION: Test if a value for a given hash and key is available
# PARAMETER  1: Name of the hash
# PARAMETER  2: Name of the key
#       RETURN: 0 When the key is available, 1 when not available
#===============================================================================
function hash_isset #{{{
{
	eval "if [[ \"\${${HashVarnamePrefix}${1}_${2}-a}\" = \"a\" && \"\${${HashVarnamePrefix}${1}_${2}-b}\" = \"b\" ]]; then return 1; else return 0; fi"
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_make_valid_key
#  DESCRIPTION: Utility function to convert a given key to a key that will not
#               cause problems in the hash library. This utility function is
#               not called from other hash library functions to avoid
#               unnecessary slow-downs in the case where the user knows what he
#               was doing.
# PARAMETER  1: Name of the key to make valid.
#       OUTPUT: The valid key.
#===============================================================================
function hash_make_valid_key #{{{
{
	local key=$1

	key=${key//\//_}
	key=${key//./_}
	key=${key//-/_}

	echo "$key"
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_foreach
#  DESCRIPTION: Iterate over all keys in the given hash and call the given
#               function. The first parameter ($1) to the function is the key,
#               the second ($2) is the value.
# PARAMETER  1: Name of the hash
# PARAMETER  2: The name of the function to call
#===============================================================================
function hash_foreach #{{{
{
	local oifs="$IFS"
	IFS=' '
	for hash_varname in $(eval "echo \${!${HashVarnamePrefix}${1}_*}")
	do
		local key_name=$(eval "echo \${hash_varname##${HashVarnamePrefix}${1}_}")
		eval "$2 $key_name \"\$$hash_varname\""
	done
	IFS="$oifs"
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_clear
#  DESCRIPTION: Unsets the entire hash in one call
# PARAMETER  1: Name of the hash
#===============================================================================
function hash_clear #{{{
{
    local oifs="$IFS"
    IFS=' '
    for hash_varname in $(eval "echo \${!${HashVarnamePrefix}${1}_*}"); do
        eval "unset $hash_varname"
    done
    IFS="$oifs"
} #}}}

#===  FUNCTION  ================================================================
#         NAME: hash_set_from_array
#  DESCRIPTION: Add the entries of a given array to a given hash table, where
#               the value for each indexed entry in the array will be a new kay
#               and the index in that array its value. This fcuntion is
#               primarily used to create fast lookup tables.
# PARAMETER  1: Name of the hash
# PARAMETER  2: Name of the array
#===============================================================================
function hash_set_from_array # {{{
{
	local hash_name=$1
	local array_name=$2

	for ((i=0; i<$(eval "echo \"\${#$array_name[@]}\""); i++))
	do
		local key=$(eval "echo \"\${$array_name[$i]}\"")
		hash_set $hash_name $(hash_make_valid_key ${key}) $i
	done
} # }}}

#===  FUNCTION  ================================================================
#         NAME: array_foreach
#  DESCRIPTION: Iterate over all entries in a given array and call the given
#               function with the entry as argument.
# PARAMETER  1: The name of the array
# PARAMETER  2: The name of the function to call
#===============================================================================
function array_foreach #{{{
{
	local oifs="$IFS"
	IFS=' '
	for entry in $(eval "echo \${${1}[@]}")
	do
		eval "$2 \"$entry\""
	done
	IFS="$oifs"
} #}}}

#===  FUNCTION  ================================================================
#         NAME: pattern_match
#  DESCRIPTION: Test is a given text matches a given pattern. An empty text and
#               a non-empty pattern always return 1.
# PARAMETER  1: Text to match
# PARAMETER  2: Pattern to test against
#       RETURN: 0 When the pattern matches, 1 when there is no match (or the
#               text is empty). 
#===============================================================================
function pattern_match #{{{
{
	[ -z $1 -a ! -z $2 ] && return 1

	local match=${1##${2}}
	if [ ${#match} -eq 0 ] && return 0

	return 1
} #}}}

#-------------------------------------------------------------------------------
# Test area
#-------------------------------------------------------------------------------
hash_set myhash one    1
hash_set myhash two    2
hash_set myhash three  3
hash_set myhash four   4
hash_set myhash five   5
hash_set myhash six    6

boem=$(hash_get myhash seven)
echo "boem = $boem"

#for ((i=0; i<10000; i++))
#do
#	hash_set myhash "a@$i" $i
#done

#filename=/one/two/three_four/_five.txt
#echo "filename=$filename"
#
#filename=${filename//_/__}
#echo "filename=$filename"
#
#filename=${filename//\//_}
#echo "filename=$filename"
#
#filename=${filename//__/_}
#echo "filename=$filename"


#function print_key_value
#{
#	echo "key=$1; value=$2"
#}
#
#hash_foreach myhash print_key_value

# vim: set ts=4 sw=4 foldmethod=marker noexpandtab:

