--- /dev/null
--- /dev/null
++#!/bin/sh
++
++# Copyright 2023, 2024 Paul Hänsch
++#
++# Permission to use, copy, modify, and/or distribute this software for any
++# purpose with or without fee is hereby granted, provided that the above
++# copyright notice and this permission notice appear in all copies.
++#
++# THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++
++[ -n "$include_db23" ] && return 0
++include_db23="$0"
++
++. "$_EXEC/cgilite/storage.sh"
++
++DB2() {
++ local call data file key val seq
++ data="${BR}${1}${BR}" call="$2"
++ shift 2
++
++ case $call in
++ new|discard)
++ printf ''
++ ;;
++ open|load) file="$1"
++ cat "$file" || return 1
++ ;;
++ check|contains) key="$(STRING "$1")" val=''
++ val="${data##*"${BR}${key}" }" val="${val%%"${BR}"*}"
++ [ "$val" = '' ] && return 1
++ ;;
++ count) key="$(STRING "$1")" val='' seq=0
++ val="${data##*"${BR}${key}" }" val="${val%%"${BR}"*}"
++ [ "$val" = '' ] || val="${val} "
++ while [ "$val" != '' ]; do
++ seq=$((seq + 1)) val="${val#* }"
++ done
++ printf "%i\n" "$seq"
++ [ $seq = 0 ] && return 1
++ ;;
++ get) key="$(STRING "$1")" seq="${2:-1}"
++ val="${data##*"${BR}${key}" }" val="${val%%"${BR}"*}"
++ [ "$val" = '' ] && return 1 || val="${val} "
++ while [ $seq -gt 1 ]; do
++ seq=$((seq - 1)) val="${val#* }"
++ done
++ [ "$val" = '' ] && return 1
++ UNSTRING "${val%% *}"
++ ;;
++ iterate|raw) key="$(STRING "$1")"
++ val="${data##*"${BR}${key}" }" val="${val%%"${BR}"*}"
++ [ "$val" = '' ] && return 1
++ printf '%s\n' $val
++ ;;
++ delete|remove) key="$(STRING "$1")"
++ val="${data#*"${BR}${key}" *"${BR}"}"
++ key="${data%"${BR}${key}" *"${BR}"*}"
++ [ "${key}${BR}${val}" = "${data}" ] && return 1
++ printf '%s' "${key#"${BR}"}${BR}${val%"${BR}"}"
++ ;;
++ set|store) key="$(STRING "$1")" val=""
++ shift 1
++ val="$(for v in "$@"; do STRING "$v"; printf \\t; done)"
++ if [ "${data#*"${BR}${key}" *}" != "$data" ]; then
++ data="${data%"${BR}${key}" *"${BR}"*}${BR}${key} ${val% }${BR}${data#*"${BR}${key}" *"${BR}"}"
++ data="${data#"${BR}"}" data="${data%"${BR}"}"
++ else
++ data="${data#"${BR}"}${key} ${val% }${BR}"
++ data="${data#"${BR}"}"
++ fi
++ printf %s\\n "${data}"
++ ;;
++ append) key="$(STRING "$1")" val=""
++ val="${data##*"${BR}${key}" }" val="${val%%"${BR}"*}"
++ if [ "$val" = '' ]; then
++ printf %s\\n "${data}"
++ return 1
++ else
++ shift 1
++ val="${val}$(for v in "$@"; do printf \\t; STRING "$v"; done)"
++ data="${data%"${BR}${key}" *"${BR}"*}${BR}${key} ${val% }${BR}${data#*"${BR}${key}" *"${BR}"}"
++ data="${data#"${BR}"}" data="${data%"${BR}"}"
++ printf %s\\n "${data}"
++ fi
++ ;;
++ flush|save|write) file="$1"
++ data="${data#"${BR}"}" data="${data%"${BR}"}"
++ printf '%s\n' "$data" >"$file" || return 1
++ ;;
++ esac
++ return 0
++}
++
++DB3() {
++ # wrapper function that allows easyer use of DB2
++ # by always keeping file data in $db3_data
++
++ case "$1" in
++ new|discard|open|load|delete|remove|set|store|append)
++ db3_data="$(DB2 "$db3_data" "$@")"
++ return "$?"
++ ;;
++ get|count|check|contains|iterate|raw|flush|save|write)
++ DB2 "$db3_data" "$@"
++ return "$?"
++ ;;
++ esac
++}