From 459f98d796383806593ce457303efb291b8f6656 Mon Sep 17 00:00:00 2001 From: Mingye Wang Date: Fri, 16 Sep 2016 17:57:21 -0400 Subject: [PATCH 1/4] Use `printf %q` for simplicity and binary safety Minor performance improvement from 11.331s to 10.937s. Now it's able to hold arbitrary null-terminated bytes. --- quinedb | 138 +++++--------------------------------------------------- 1 file changed, 12 insertions(+), 126 deletions(-) diff --git a/quinedb b/quinedb index a6cfa17..d0254cf 100755 --- a/quinedb +++ b/quinedb @@ -10,79 +10,22 @@ declare -A db db=( ) -pr_str () { - s="$1" - if [[ "$s" =~ ^[-a-zA-Z0-9]+$ ]]; then - echo "$s" - else - ret=\$\' - for (( i=0; i<${#s}; i++ )); do - c="${s:$i:1}" - if [[ "$c" =~ [-_a-zA-Z0-9\ ] ]]; then - ret+="$c" - else - case "$c" in - $'\a') - ret+="\\a" - ;; - $'\b') - ret+="\\b" - ;; - $'\e') - ret+="\\e" - ;; - $'\E') - ret+="\\E" - ;; - $'\f') - ret+="\\f" - ;; - $'\n') - ret+="\\n" - ;; - $'\r') - ret+="\\r" - ;; - $'\t') - ret+="\\t" - ;; - $'\v') - ret+="\\v" - ;; - $'\\') - ret+="\\\\" - ;; - $'\'') - ret+="\\"\' - ;; - $'\"') - ret+="\\"\" - ;; - else) - ret+="\\$c" - esac - fi - done - echo "${ret}"\' - fi -} - print_db(){ echo "db=(" i=0 for k in "${!db[@]}"; do - escaped_keys[$i]=$(pr_str "$k") + escaped_keys[$i]=$(printf %q "$k") i=$((i+1)) done # sort the keys for deterministic printing - IFS=$'\n' sorted=($(for l in ${escaped_keys[@]}; do echo $l; done | sort)) + IFS=$'\n' sorted=($(printf '%s' "${escaped_keys[*]}" | sort)) unset IFS for k in "${sorted[@]}"; do unescaped=$(eval "echo $k") v=${db["$unescaped"]} - echo " [$k]=$(pr_str "$v")" + echo " [$k]=$(printf %q "$v")" done echo ")" } @@ -100,79 +43,22 @@ EOF ) SEC2=$(cat <<'EOF' -pr_str () { - s="$1" - if [[ "$s" =~ ^[-a-zA-Z0-9]+$ ]]; then - echo "$s" - else - ret=\$\' - for (( i=0; i<${#s}; i++ )); do - c="${s:$i:1}" - if [[ "$c" =~ [-_a-zA-Z0-9\ ] ]]; then - ret+="$c" - else - case "$c" in - $'\a') - ret+="\\a" - ;; - $'\b') - ret+="\\b" - ;; - $'\e') - ret+="\\e" - ;; - $'\E') - ret+="\\E" - ;; - $'\f') - ret+="\\f" - ;; - $'\n') - ret+="\\n" - ;; - $'\r') - ret+="\\r" - ;; - $'\t') - ret+="\\t" - ;; - $'\v') - ret+="\\v" - ;; - $'\\') - ret+="\\\\" - ;; - $'\'') - ret+="\\"\' - ;; - $'\"') - ret+="\\"\" - ;; - else) - ret+="\\$c" - esac - fi - done - echo "${ret}"\' - fi -} - print_db(){ echo "db=(" i=0 for k in "${!db[@]}"; do - escaped_keys[$i]=$(pr_str "$k") + escaped_keys[$i]=$(printf %q "$k") i=$((i+1)) done # sort the keys for deterministic printing - IFS=$'\n' sorted=($(for l in ${escaped_keys[@]}; do echo $l; done | sort)) + IFS=$'\n' sorted=($(printf '%s' "${escaped_keys[*]}" | sort)) unset IFS for k in "${sorted[@]}"; do unescaped=$(eval "echo $k") v=${db["$unescaped"]} - echo " [$k]=$(pr_str "$v")" + echo " [$k]=$(printf %q "$v")" done echo ")" } @@ -201,9 +87,9 @@ print_self(){ case "$1" in "get") - if [ ${db["$2"]+_} ]; then + if [ "${db["$2"]+_}" ]; then v=${db["$2"]} - echo "$(pr_str "$v")" >&2 + echo "$(printf %q "$v")" >&2 fi ;; "set") @@ -215,7 +101,7 @@ case "$1" in echo 'OK' >&2 ;; "keys") - for k in "${!db[@]}"; do echo "$(pr_str "$k")"; done >&2 + for k in "${!db[@]}"; do echo "$(printf %q "$k")"; done >&2 ;; *) echo "USAGE: quinedb [get k | set k v | delete k | keys]" >&2 @@ -247,9 +133,9 @@ print_self(){ case "$1" in "get") - if [ ${db["$2"]+_} ]; then + if [ "${db["$2"]+_}" ]; then v=${db["$2"]} - echo "$(pr_str "$v")" >&2 + echo "$(printf %q "$v")" >&2 fi ;; "set") @@ -261,7 +147,7 @@ case "$1" in echo 'OK' >&2 ;; "keys") - for k in "${!db[@]}"; do echo "$(pr_str "$k")"; done >&2 + for k in "${!db[@]}"; do echo "$(printf %q "$k")"; done >&2 ;; *) echo "USAGE: quinedb [get k | set k v | delete k | keys]" >&2 From fc00d50324a01c82d663b5d14a3e915f7b75dfc1 Mon Sep 17 00:00:00 2001 From: Mingye Wang Date: Sun, 18 Sep 2016 17:20:44 -0400 Subject: [PATCH 2/4] test: binary-safe escape --- test.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test.rb b/test.rb index 91bced9..b51b0de 100644 --- a/test.rb +++ b/test.rb @@ -24,9 +24,7 @@ def teardown end def pr_str s - s2 = "" - (0...(s.length)).each{|i|s2 << "\\#{s[i]}"} - s2 + "'#{s.gsub(/'/, "'\\\\''")}'" end def cmd *args From da8c3800c6bda1f852f6b36d5172fb3857794f2d Mon Sep 17 00:00:00 2001 From: Mingye Wang Date: Mon, 19 Sep 2016 09:30:57 -0400 Subject: [PATCH 3/4] fix deletion of "weird" keys See thread: https://lists.gnu.org/archive/html/help-bash/2016-09/msg00020.html test cases needed. --- quinedb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/quinedb b/quinedb index d0254cf..cc7a869 100755 --- a/quinedb +++ b/quinedb @@ -97,11 +97,11 @@ case "$1" in echo 'OK' >&2 ;; "delete") - unset db["$2"] + unset 'db[$2]' echo 'OK' >&2 ;; "keys") - for k in "${!db[@]}"; do echo "$(printf %q "$k")"; done >&2 + printf '%q\n' "${!db[@]}" >&2 ;; *) echo "USAGE: quinedb [get k | set k v | delete k | keys]" >&2 @@ -143,11 +143,11 @@ case "$1" in echo 'OK' >&2 ;; "delete") - unset db["$2"] + unset 'db[$2]' echo 'OK' >&2 ;; "keys") - for k in "${!db[@]}"; do echo "$(printf %q "$k")"; done >&2 + printf '%q\n' "${!db[@]}" >&2 ;; *) echo "USAGE: quinedb [get k | set k v | delete k | keys]" >&2 From b296b322a3f5835e6a7028d296565d4fd80a6651 Mon Sep 17 00:00:00 2001 From: Mingye Wang Date: Mon, 19 Sep 2016 22:47:39 -0400 Subject: [PATCH 4/4] silent printf %q if there is nothing to print --- quinedb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quinedb b/quinedb index cc7a869..b1a7f27 100755 --- a/quinedb +++ b/quinedb @@ -101,7 +101,7 @@ case "$1" in echo 'OK' >&2 ;; "keys") - printf '%q\n' "${!db[@]}" >&2 + if ((${#db[@]})); then printf '%q\n' "${!db[@]}"; fi >&2 ;; *) echo "USAGE: quinedb [get k | set k v | delete k | keys]" >&2 @@ -147,7 +147,7 @@ case "$1" in echo 'OK' >&2 ;; "keys") - printf '%q\n' "${!db[@]}" >&2 + if ((${#db[@]})); then printf '%q\n' "${!db[@]}"; fi >&2 ;; *) echo "USAGE: quinedb [get k | set k v | delete k | keys]" >&2