Skip to content

Instantly share code, notes, and snippets.

@rindeal
Forked from bmc/stack.sh
Last active July 29, 2016 23:13
Show Gist options
  • Save rindeal/7d87e6a146c1dc95faf5df0978c2c57b to your computer and use it in GitHub Desktop.
Save rindeal/7d87e6a146c1dc95faf5df0978c2c57b to your computer and use it in GitHub Desktop.
A stack implementation, in bash
#!/bin/bash
# A stack, using bash arrays.
#
# Based on: https://gist.github.com/bmc/1323553 by Brian Clapper (bmc) <bmc@clapper.org>
# ---------------------------------------------------------------------------
# Check if a stack exists
#
# Usage: stack_exists name
stack_exists() {
: ${1?'Missing stack name'}
local _sname="${1}"
eval '_i=$'"_stack_${_sname}_i"
[[ -n "${_i}" ]]
}
# Create a new stack.
#
# Usage: stack_new name
#
# Example: stack_new x
stack_new() {
: ${1?'Missing stack name'}
local _sname="${1}"
if stack_exists "${_sname}" ; then
echo "Stack already exists -- '${_sname}'" >&2
return 1
fi
# create main stack array
eval "declare -ag _stack_${_sname}"
# create stack offset variable
eval "declare -ig _stack_${_sname}_i=0"
return 0
}
# Destroy a stack
#
# Usage: stack_destroy name
stack_destroy() {
: ${1?'Missing stack name'}
local _sname="${1}"
eval "unset _stack_${_sname}"{,_i}
return 0
}
# Push one or more items onto a stack.
#
# Usage: stack_push stack item ...
stack_push() {
: ${1?'Missing stack name'}
: ${2?'Missing item(s) to push'}
local _sname="${1}"
shift 1
local _items=( "${@}" )
if ! stack_exists "${_sname}" ; then
echo "No such stack -- '${_sname}'" >&2
return 1
fi
eval "local _i=\${_stack_${_sname}_i}"
local _item
for _item in "${_items[@]}" ; do
eval "_stack_${_sname}[${_i}]='${_item}'"
let _i+=1
done
eval "let _stack_${_sname}_i=${_i}"
return 0
}
# Print a stack to stdout.
#
# Usage: stack_print name
stack_print() {
: ${1?'Missing stack name'}
local _sname="${1}"
if ! stack_exists "${_sname}" ; then
echo "No such stack -- ${_sname}" >&2
return 1
fi
echo "Stack '${_sname}':"
local val
eval "local _i=\${_stack_${_sname}_i}"
while (( ${_i} > 0 )) ; do
let _i-=1
eval 'val=$'"{_stack_${_sname}[${_i}]}"
printf " [%02d] = '%s'\n" \
"$((_i+1))" "${val}"
done
}
# Get the size of a stack
#
# Usage: stack_size name var
#
# Example:
# stack_size mystack n
# echo "Size is $n"
stack_size() {
: ${1?'Missing stack name'}
: ${2?'Missing name of variable for stack size result'}
local _sname="${1}"
local _rname="${2}"
if ! stack_exists "${_sname}" ; then
echo "No such stack -- ${_sname}" >&2
return 1
fi
eval "${_rname}=\${_stack_${_sname}_i}"
}
# Pop the top element from the stack.
#
# Usage: stack_pop name var
#
# Example:
# stack_pop mystack top
# echo "Got $top"
stack_pop() {
: ${1?'Missing stack name'}
: ${2?'Missing name of variable for popped result'}
local _sname="${1}"
local _rname="${2}"
if ! stack_exists "${_sname}" ; then
echo "No such stack -- ${_sname}" >&2
return 1
fi
local _i
eval 'let _i=$'"_stack_${_sname}_i"
if [[ ${_i} == 0 ]] ; then
echo "Empty stack -- ${_sname}" >&2
return 1
fi
let _i-=1
eval "${_rname}=\${_stack_${_sname}[${_i}]}"
eval "unset _stack_${_sname}[${_i}]"
eval "_stack_${_sname}_i=${_i}"
return 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment