#!/bin/sh -efu
### This file is covered by the GNU General Public License,
### which should be included with libshell as the file LICENSE.
### All copyright information are listed in the COPYING.

if [ -z "${__included_shell_ini_config-}" ]; then
__included_shell_ini_config=1

shell_ini_config_comment='#'
shell_ini_config_prefix='	'

. shell-error
. shell-var

__ini_config_print()
{
	local p="$1"; shift
	printf '%s%s\n' "${p:+${shell_ini_config_prefix-}}" "$@"
}

### Usage: ini_config_get file section var
ini_config_get()
{
	local fn section var sect= str eof= n v
	fn="$1" section="$2" var="$3"

	while [ -z "$eof" ]; do
		read -r str || eof=1

		case "$str" in
			"["*"]")
				[ "$str" != "[$section]" ] ||
					sect=1
				;;
			"$shell_ini_config_comment"*|'')
				;;
			*)
				if [ -n "$sect" ]; then
					shell_var_trim n "${str%%=*}"

					if [ "$n" = "$var" ]; then
						shell_var_trim v "${str#*=}"
						printf '%s\n' "$v"
						break
					fi
				fi
				;;
		esac
	done < "$fn"
}

### Usage: ini_config_set file section var value
ini_config_set()
{
	local fn fn_tmp section var value sect= don= str eof= n v

	fn="$1" section="$2" var="$3" value="$4"
	fn_tmp="$(mktemp "$fn.XXXXXX")"

	while [ -z "$eof" ]; do
		read -r str || eof=1

		case "$str" in
			"[$section]")
				sect=2
				printf '%s\n' "$str"
				;;
			"["*"]")
				if [ "$sect" = 2 -a -z "$don" ]; then
					__ini_config_print 1 "$var = $value"
					don=1
				fi
				sect=1
				printf '%s\n' "$str"
				;;
			"$shell_ini_config_comment"*|'')
				[ -n "$str" ] &&
					__ini_config_print "$sect" "$str" ||
					{ [ -n "$eof" ] || printf '\n'; }
				;;
			*)
				shell_var_trim n "${str%%=*}"
				shell_var_trim v "${str#*=}"

				if [ "$sect" = 2 -a "$n" = "$var" ]; then
					[ -n "$don" ] ||
						__ini_config_print 1 "$n = $value"
					don=1
					continue
				fi
				__ini_config_print 1 "$n = $v"
				;;
		esac

		if [ -n "$eof" -a -z "$don" ]; then
			[ "$sect" = 2 ] ||
				printf '[%s]\n' "$section"
			__ini_config_print 1 "$var = $value"
		fi

	done < "$fn" > "$fn_tmp"
	mv -f -- "$fn_tmp" "$fn"
}

__ini_config_del_comment()
{
	local fn_tmp sect= str eof= n v
	fn_tmp="$(mktemp "$fn.XXXXXX")"

	while [ -z "$eof" ]; do
		read -r str || eof=1

		case "$str" in
			"["*"]")
				sect=1
				[ "$str" != "[$section]" ] ||
					sect=2
				printf '%s\n' "$str"
				;;
			"$shell_ini_config_comment"*|'')
				[ -n "$str" ] &&
					__ini_config_print "$sect" "$str" ||
					printf '\n'
				;;
			*)
				shell_var_trim n "${str%%=*}"
				shell_var_trim v "${str#*=}"

				[ "$sect" = 2 ] &&
					__ini_config_action "$n" "$v" ||
					__ini_config_print 1 "$n = $v"
				;;
		esac
	done < "$fn" > "$fn_tmp"
	mv -f -- "$fn_tmp" "$fn"
	unset __ini_config_action
}

### Usage: ini_config_del file section [var]
ini_config_del()
{
	local fn="$1" section="$2" var="${3-}"

	__ini_config_action()
	{
		[ -z "$var" -o "$1" = "$var" ] ||
			__ini_config_print 1 "$1 = $2"
	}
	__ini_config_del_comment
}

### Usage: ini_config_comment file section [var]
ini_config_comment()
{
	local fn="$1" section="$2" var="${3-}"

	__ini_config_action()
	{
		if [ -n "$var" -a "$1" != "$var" ]; then
			__ini_config_print 1 "$1 = $2"
			return
		fi
		__ini_config_print 1 "$shell_ini_config_comment $1 = $2"
	}
	__ini_config_del_comment
}

fi #__included_shell_ini_config
