function bos-namespaces/encode-into() {
local -n result="$1"; shift
local idx char tmp
result=''
while [[ "${#*}" -gt 0 ]]; do
for (( idx=0 ; idx < "${#1}" ; ++idx )); do
char="${1:$idx:1}"
case "$char" in
[0-9A-Za-z]) tmp="$char";;
*) printf -v tmp _%02x "'$char"
esac
result+="$tmp"
done
result+='__'
shift
done
}
function bos-namespaces/store-scalar-for-into() {
local -n result="$1"; shift
local name; bos-namespaces/encode-into name "bos" "$@"
declare -g "$name"
result="$name"
}
function bos-namespaces/store-array-for-into() {
local -n result="$1"; shift
local name; bos-namespaces/encode-into name "bos" "$@"
declare -ga "$name"
result="$name"
}
function bos-namespaces/store-assoc-for-into() {
local -n result="$1"; shift
local name; bos-namespaces/encode-into name "bos" "$@"
declare -gA "$name"
result="$name"
}
declare -a bos_namespace_stack
function bos-namespaces/current-namespace-into() {
local -n bos_namespace_current_namespace_result="$1"
local IFS=/
bos_namespace_current_namespace_result="${bos_namespace_stack[*]}"
}
function bos-namespaces/push() {
bos_namespace_stack+=( "$1" )
}
function bos-namespaces/pop() {
unset "bos_namespace_stack[-1]"
}
function bos-namespaces/save-funcs() {
local namespace; bos-namespaces/current-namespace-into namespace
local ns_store; bos-namespaces/store-assoc-for-into ns_store saved_funcs "$namespace"
local -n saved_funcs="$ns_store"
local _ funcname
while read -r _ _ funcname; do
saved_funcs+=( ["$funcname"]="$(declare -pf "$funcname")" )
done < <( declare -pF )
return 0
}
function bos-namespaces/list-new-funcs-into() {
local -n result="$1"
local namespace; bos-namespaces/current-namespace-into namespace
local ns_store; bos-namespaces/store-assoc-for-into ns_store saved_funcs "$namespace"
local -n saved_funcs="$ns_store"
local _ funcname new_function
while read -r _ _ funcname; do
if [[ "$funcname" == "$namespace"/* ]]; then
continue
fi
new_function="$(declare -pf "$funcname")"
if [[ "$new_function" != "${saved_funcs["$funcname"]}" ]]; then
result+=( "${funcname}" )
fi
done < <( declare -pF )
return 0
}
function bos-namespaces/qualify-funcs() {
local namespace; bos-namespaces/current-namespace-into namespace
local ns_store; bos-namespaces/store-assoc-for-into ns_store saved_funcs "$namespace"
local -n saved_funcs="$ns_store"
local _ funcname new_function
for funcname in "$@"; do
new_function="$(declare -pf "$funcname")"
eval "${namespace}/${new_function}"
if [[ -n "${saved_funcs["$funcname"]}" ]]; then
eval "${saved_funcs["$funcname"]}"
else
unset -f "$funcname"
fi
done
return 0
}
function bos-namespaces/namespace-open() {
bos-namespaces/push "$1"
bos-namespaces/save-funcs
return 0
}
function bos-namespaces/namespace-close() {
local -a methods_list; bos-namespaces/list-new-funcs-into methods_list
bos-namespaces/qualify-funcs "${methods_list[@]}"
bos-namespaces/pop
return 0
}