1- # -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
21# @str-parse-json
32#
43# Parses the buffer ($1) with JSON and returns:
1615#
1716# Example:
1817#
19- # {"zplugin -ices":{
18+ # {"zi -ices":{
2019# "default":{
2120# "wait":"1",
2221# "lucid":"",
6261# $3 - the name of the output hash parameter
6362
6463@str-parse-json() {
65- emulate -LR zsh -o extendedglob -o warncreateglobal -o typesetsilent
64+ emulate -LR zsh -o extendedglob -o warncreateglobal -o typesetsilent
6665
67- local -A __pos_to_level __level_to_pos __pair_map \
68- __final_pairs __Strings __Counts
69- local __input=$1 __workbuf=$1 __key=$2 __varname=$3 \
70- __style __quoting
71- integer __nest=${4:- 1} __idx=0 __pair_idx __level=0 \
72- __start __end __sidx=1 __had_quoted_value=0
73- local -a match mbegin mend __pair_order
66+ local -A __pos_to_level __level_to_pos __pair_map \
67+ __final_pairs __Strings __Counts
68+ local __input=$1 __workbuf=$1 __key=$2 __varname=$3 \
69+ __style __quoting
70+ integer __nest=${4:-1} __idx=0 __pair_idx __level=0 \
71+ __start __end __sidx=1 __had_quoted_value=0
72+ local -a match mbegin mend __pair_order
7473
75- (( ${(P)+__varname} )) || typeset -gA " $__varname "
74+ (( ${(P)+__varname} )) || typeset -gA "$__varname"
7675
77- __pair_map=( " (" " )" " {" " }" " [" " ]" )
78- while [[ $__workbuf = (# b)[^"{}()[]\\\"'":,]#((["({[]})\"'":,])|[\\](*))(*) ]]; do
79- [[ -n ${match[3]} ]] && {
80- __idx+=${mbegin[1]}
76+ __pair_map=( "(" ")" "{" "}" "[" "]" )
77+ while [[ $__workbuf = (#b)[^"{}()[]\\\"'":,]#((["({[]})\"'":,])|[\\](*))(*) ]]; do
78+ [[ -n ${match[3]} ]] && {
79+ __idx+=${mbegin[1]}
8180
82- [[ $__quoting = \' ]] && \
83- { __workbuf=${match[3]} ; } || \
84- { __workbuf=${match[3]: 1} ; (( ++ __idx )) ; }
81+ [[ $__quoting = \' ]] && \
82+ { __workbuf=${match[3]}; } || \
83+ { __workbuf=${match[3]:1}; (( ++ __idx )); }
8584
86- } || {
87- __idx+=${mbegin[1]}
88- [[ -z $__quoting ]] && {
89- if [[ ${match[1]} = [" ({[" ] ]]; then
90- __Strings[$__level /${__Counts[$__level]} ]+=" $'\0'--object--$'\0'"
91- __pos_to_level[$__idx ]=$(( ++ __level ))
92- __level_to_pos[$__level ]=$__idx
93- (( __Counts[$__level ] += 1 ))
94- __sidx=__idx+1
95- __had_quoted_value=0
96- elif [[ ${match[1]} = [" ]})" ] ]]; then
97- (( ! __had_quoted_value )) && \
98- __Strings[$__level /${__Counts[$__level]} ]+=" ${(q)__input[__sidx,__idx-1]// ((# s)[[:blank:]]## |([[:blank:]]## (# e)))} "
99- __had_quoted_value=1
100- if (( __level > 0 )) ; then
101- __pair_idx=${__level_to_pos[$__level]}
102- __pos_to_level[$__idx ]=$(( __level -- ))
103- [[ ${__pair_map[${__input[__pair_idx]} ]} = ${__input[__idx]} ]] && {
104- __final_pairs[$__idx ]=$__pair_idx
105- __final_pairs[$__pair_idx ]=$__idx
106- __pair_order+=( $__idx )
107- }
108- else
109- __pos_to_level[$__idx ]=-1
110- fi
111- fi
112- }
113-
114- [[ ${match[1]} = \" && $__quoting != \' ]] && \
115- if [[ $__quoting = ' "' ]]; then
116- __Strings[$__level /${__Counts[$__level]} ]+=" ${(q)__input[__sidx,__idx-1]} "
117- __quoting=" "
118- else
119- __had_quoted_value=1
120- __sidx=__idx+1
121- __quoting=' "'
122- fi
85+ } || {
86+ __idx+=${mbegin[1]}
87+ [[ -z $__quoting ]] && {
88+ if [[ ${match[1]} = ["({["] ]]; then
89+ __Strings[$__level/${__Counts[$__level]}]+=" $'\0'--object--$'\0'"
90+ __pos_to_level[$__idx]=$(( ++ __level ))
91+ __level_to_pos[$__level]=$__idx
92+ (( __Counts[$__level] += 1 ))
93+ __sidx=__idx+1
94+ __had_quoted_value=0
95+ elif [[ ${match[1]} = ["]})"] ]]; then
96+ (( !__had_quoted_value )) && \
97+ __Strings[$__level/${__Counts[$__level]}]+=" ${(q)__input[__sidx,__idx-1]//((#s)[[:blank:]]##|([[:blank:]]##(#e)))}"
98+ __had_quoted_value=1
99+ if (( __level > 0 )); then
100+ __pair_idx=${__level_to_pos[$__level]}
101+ __pos_to_level[$__idx]=$(( __level -- ))
102+ [[ ${__pair_map[${__input[__pair_idx]}]} = ${__input[__idx]} ]] && {
103+ __final_pairs[$__idx]=$__pair_idx
104+ __final_pairs[$__pair_idx]=$__idx
105+ __pair_order+=( $__idx )
106+ }
107+ else
108+ __pos_to_level[$__idx]=-1
109+ fi
110+ fi
111+ }
123112
124- [[ ${match[1]} = , && -z $__quoting ]] && \
125- {
126- (( ! __had_quoted_value )) && \
127- __Strings[$__level /${__Counts[$__level]} ]+=" ${(q)__input[__sidx,__idx-1]// ((# s)[[:blank:]]## |([[:blank:]]## (# e)))} "
128- __sidx=__idx+1
129- __had_quoted_value=0
130- }
113+ [[ ${match[1]} = \" && $__quoting != \' ]] && \
114+ if [[ $__quoting = '"' ]]; then
115+ __Strings[$__level/${__Counts[$__level]}]+=" ${(q)__input[__sidx,__idx-1]}"
116+ __quoting=""
117+ else
118+ __had_quoted_value=1
119+ __sidx=__idx+1
120+ __quoting='"'
121+ fi
131122
132- [[ ${match[1]} = : && -z $__quoting ]] && \
133- {
134- __had_quoted_value=0
135- __sidx=__idx+1
136- }
123+ [[ ${match[1]} = , && -z $__quoting ]] && \
124+ {
125+ (( !__had_quoted_value )) && \
126+ __Strings[$__level/${__Counts[$__level]}]+=" ${(q)__input[__sidx,__idx-1]//((#s)[[:blank:]]##|([[:blank:]]##(#e)))}"
127+ __sidx=__idx+1
128+ __had_quoted_value=0
129+ }
137130
138- [[ ${match[1]} = \' && $__quoting != \" ]] && \
139- if [[ $__quoting = " '" ]]; then
140- __Strings[$__level /${__Counts[$__level]} ]+=" ${(q)__input[__sidx,__idx-1]} "
141- __quoting=" "
142- else
143- __had_quoted_value=1
144- __sidx=__idx+1
145- __quoting=" '"
146- fi
131+ [[ ${match[1]} = : && -z $__quoting ]] && \
132+ {
133+ __had_quoted_value=0
134+ __sidx=__idx+1
135+ }
147136
148- __workbuf=${match[4]}
149- }
150- done
137+ [[ ${match[1]} = \' && $__quoting != \" ]] && \
138+ if [[ $__quoting = "'" ]]; then
139+ __Strings[$__level/${__Counts[$__level]}]+=" ${(q)__input[__sidx,__idx-1]}"
140+ __quoting=""
141+ else
142+ __had_quoted_value=1
143+ __sidx=__idx+1
144+ __quoting="'"
145+ fi
151146
152- local __text value __found
153- integer __pair_a __pair_b
154- for __pair_a ( " ${__pair_order[@]} " ) {
155- __pair_b=" ${__final_pairs[$__pair_a]} "
156- __text=" ${__input[__pair_b,__pair_a]} "
157- if [[ $__text = [[:space:]]# \{[[:space:]]#[\"\']${__key}[\"\']* ]]; then
158- if (( __nest != 2 )) {
159- __found=" $__text "
160- break
161- }
162- fi
163- }
147+ __workbuf=${match[4]}
148+ }
149+ done
164150
165- if [[ -n $__found && $__nest -lt 2 ]] {
166- @str-parse-json " $__found " " $__key " " $__varname " 2
167- }
151+ local __text value __found
152+ integer __pair_a __pair_b
153+ for __pair_a ( "${__pair_order[@]}" ) {
154+ __pair_b="${__final_pairs[$__pair_a]}"
155+ __text="${__input[__pair_b,__pair_a]}"
156+ if [[ $__text = [[:space:]]#\{[[:space:]]#[\"\']${__key}[\"\']* ]]; then
157+ if (( __nest != 2 )) {
158+ __found="$__text"
159+ break
160+ }
161+ fi
162+ }
168163
169- if (( __nest == 2 )) {
170- : ${(PAA)__varname::= " ${(kv)__Strings[@]} " }
171- }
172- }
164+ if [[ -n $__found && $__nest -lt 2 ]] {
165+ @str-parse-json "$__found" "$__key" "$__varname" 2
166+ }
173167
174- # vim:ft=zsh:sts=4:sw=4:et
168+ if (( __nest == 2 )) {
169+ : ${(PAA)__varname::="${(kv)__Strings[@]}"}
170+ }
171+ }
0 commit comments