#### Hashing functions

### Clear the hash index
function hash_clear {
	for hash in $@; do
		hash="${hash//[-.+]/_}"
		local idx="${hash}index"       
		eval "export -n $idx"
	done
}

### Reading aliases from map-file
function hash_import {
	local hash="$1"
	hash="${hash//[-.+]/_}"
	local file="$2"
	if [ -r "$file" ]; then
		while read name value; do
			name="${name//[-.+]/_}"
		        case "$name" in
		                ("#"*) ;;
		                ("") ;;
		                (*) 
					value="${value/\\#*/ }"
					value="${value//,/ }"
					if [ "$name" -a "$value" ]; then
						hash_put $hash $name "$value"
					fi
		        esac
		done < "$file"
	else
		error $FUNCNAME $LINENO "File '$file' cannot be read."
	fi
}


### Checks if variabele exists in hash
function hash_exists {
	local hash="$1"
	hash="${hash//[-.+]/_}"
	local name="$2"
	name="${name//[-.+]/_}"
	local str="${hash}_$name"
	if [ "${!str}" ]; then
		return 0;
	fi
	return 1;
}

### Put variabeles in a hash
function hash_put {
	local hash="$1"
	hash="${hash//[-.+]/_}"
	local name="$2"
	name="${name//[-.+]/_}"
	local str="${hash}_$name" 
	local idx="${hash}index"       
	shift 2
	local value="$*"
	if [ "$value" ]; then
		if ! hash_exists $hash $name; then
			eval "export $idx=\"${!idx} $name\""
			eval "export $str=\"$value\""
			return 0
		fi
		error $FUNCNAME $LINENO "Name '$name' already exists in hash '$hash' with value '$value'."
	fi
	return 1
}

### Get variables from a hash
function hash_get {
	local hash="$1"
	hash="${hash//[-.+]/_}"
	local name="$2"
	name="${name//[-.+]/_}"
	local str="${hash}_$name"
	if [ "${!str}" ]; then
		echo -n ${!str}
		return 0;
	fi
	return 1;
}

### Delete variables from a hash
function hash_delete {
	local hash="$1"
	hash="${hash//[-.+]/_}"
	shift
	local idx="${hash}index"
	local idxstr="${!idx}"
	for name in $@; do
		name="${name//[-.+]/_}"
		local str="${hash}_$name"
		eval "export $str=\"\""
		idxstr="${idxstr/%$name/}"
	done
	eval "export $idx=\"$idxstr\""
}

### Returns the hash index
function hash_list {
	for hash in $@; do
		hash="${hash//[-.+]/_}"
		local idx="${hash}index"
#		local test="${!${hash}_*}"
#		echo "${test//${hash}_/}"
		echo ${!idx}
	done
}

### List all variables in a hash
function hash_print {
	for hash in $@; do
		hash="${hash//[-.+]/_}"
		echo "Elements in hash \"$hash\":"
		for var in $(hash_list $hash); do
		        echo -e "\t$var = \"$(hash_get $hash $var)\"";
		done
		echo
	done
}

### Expand hash-values by other hash-values
function hash_subst_min {
	local hash="$1"
	hash="${hash//[-.+]/_}"
	for name in $(hash_list $hash); do
		local str=""
		name="${name//[-.+]/_}"
		for i in $(hash_get $hash $name); do
			str="$str$i "
		done
		hash_delete $hash $name
		hash_put $hash $name "$str"
	done
}

### Expand hash-values by other hash-values (to fullful test)
function hash_subst {
	local hash="$1"
	hash="${hash//[-.+]/_}"
	local test="$2"
	for name in $(hash_list $hash); do
	        local str=""
		name="${name//[-.+]/_}"
	        for i in $(hash_get $hash $name); do
	                if $test $i; then
	                        str="$str$i "
	                else
	                        if hash_exists $hash $i; then
	                                str="$str$(hash_get $hash $i) "
	                        else
	                                error $FUNCNAME $LINENO "$str does not exists"
	                        fi
	                fi
	        done
		hash_delete $hash $name
	        hash_put $hash $name "$str"
	done
}
