11local NULL = {}
22
3- local find , sub , tonumber , error = string.find , string.sub , tonumber , error
3+ local find , match , sub , byte , tonumber , error = string.find , string.match , string. sub, string.byte , tonumber , error
44local function decode (json --[[ @param json string]] ) --- @return any
55 local ptr = 1
66
7- local function consume (pattern --[[ @param pattern string]] ) --- @return string ?
8- local _ , finish , match = find (json , pattern , ptr )
7+ local function skip (pattern --[[ @param pattern string]] ) --- @return true ?
8+ local finish = match (json , pattern , ptr )
99 if finish then
10- ptr = finish + 1
11- return match or true
10+ ptr = finish
11+ return true
1212 end
1313 end
1414
1515 local function slowstring () -- string parser that supports escapes.
16- local start = ptr + 1 -- skip initial quote
17- ptr = start
18-
16+ local start = ptr
1917 while true do
20- local start , finish = find (json , " \\ *\" " , ptr )
21- if finish then
22- ptr = finish + 1
23- if (finish - start ) % 2 == 0 then
24- return sub (json , start , finish - 1 ) -- return (gsub(sub(json, start, finish - 1), "\\([bfnrt\\\"])", ESCAPES))
18+ local _start , before_quote , after_quote = match (json , " () \\ *() \" () " , ptr )
19+ if _start then
20+ ptr = after_quote
21+ if (before_quote - _start ) % 2 == 0 then
22+ return sub (json , start , after_quote ) -- return (gsub(sub(json, start, finish - 1), "\\([bfnrt\\\"])", ESCAPES))
2523 end
2624 else
2725 error (" Missing end quote for string at char " .. ptr )
@@ -31,67 +29,80 @@ local function decode(json --[[@param json string]]) ---@return any
3129
3230
3331 local function number ()
34- return tonumber (consume (" ^(-?%d*.?%d+[eE]?[+-]?%d*)" ))
32+ local number , finish = match (json , " ^(-?%d*.?%d+[eE]?[+-]?%d*)()" , ptr - 1 )
33+ if finish then
34+ ptr = finish
35+ return tonumber (number )
36+ end
3537 end
3638
3739 local value
3840 local function whitespace ()
39- ptr = find (json , " %S " , ptr ) or ptr -- skip past whitespace, return immediate value
41+ ptr = match (json , " ^%s*() " , ptr ) or ptr -- skip past whitespace, return immediate value
4042 return value ()
4143 end
4244
43- local function string ()
44- local start = ptr + 1
45- local quot = find (json , ' "' , start , true )
46- local prev = quot - 1
47- if sub (json , prev , prev ) ~= " \\ " then
48- ptr = quot + 1
49- return sub (json , start , prev )
50- else
51- return slowstring ()
52- end
53- end
54-
5545 local peek = {
56- [" \" " ] = string ,
57- [" t" ] = function ()
58- if sub (json , ptr , ptr + 3 ) == " true" then
59- ptr = ptr + 4
46+ [34 --[[ "]] ] = function ()
47+ local start = ptr
48+ local quot = find (json , ' "' , start , true )
49+ local prev = quot - 1
50+ if byte (json , prev ) ~= 92 --[[ \]] then
51+ ptr = quot + 1
52+ return sub (json , start , prev )
53+ else
54+ return slowstring ()
55+ end
56+ end ,
57+ [116 --[[ t]] ] = function ()
58+ if sub (json , ptr , ptr + 2 ) == " rue" then
59+ ptr = ptr + 3
6060 return true
6161 end
6262 end ,
63- [" f " ] = function ()
64- if sub (json , ptr , ptr + 4 ) == " false " then
65- ptr = ptr + 5
63+ [102 --[[ f ]] ] = function ()
64+ if sub (json , ptr , ptr + 3 ) == " alse " then
65+ ptr = ptr + 4
6666 return false
6767 end
6868 end ,
69- [" n " ] = function ()
70- if sub (json , ptr , ptr + 3 ) == " null " then
71- ptr = ptr + 4
69+ [110 --[[ n ]] ] = function ()
70+ if sub (json , ptr , ptr + 2 ) == " ull " then
71+ ptr = ptr + 3
7272 return NULL
7373 end
7474 end ,
7575
76- [" 0" ] = number , [" 1" ] = number , [" 2" ] = number ,
77- [" 3" ] = number , [" 4" ] = number , [" 5" ] = number ,
78- [" 6" ] = number , [" 7" ] = number , [" 8" ] = number ,
79- [" 9" ] = number , [" -" ] = number ,
80-
81- [" {" ] = function ()
82- ptr = ptr + 1
76+ [48 --[[ 0]] ] = number , [49 ] = number , [50 ] = number ,
77+ [51 ] = number , [52 ] = number , [53 ] = number ,
78+ [54 ] = number , [55 ] = number , [56 ] = number ,
79+ [57 --[[ 9]] ] = number , [45 --[[ -]] ] = number ,
8380
81+ [123 --[[ {]] ] = function ()
8482 local fields = {}
85- if consume (" ^%s*}" ) then return fields end
83+ if skip (" ^%s*}() " ) then return fields end
8684
8785 repeat
88- ptr = find (json , " %S" , ptr ) or ptr -- skip whitespace inline
89- local key = string ()
90- if not key then
86+ ptr = match (json , " () %S" , ptr ) or ptr -- skip whitespace inline
87+
88+ if byte ( json , ptr ) ~= 34 --[[ " ]] then
9189 error (" Expected field for object at char " .. ptr )
9290 end
9391
94- if not consume (" ^%s*:" ) then
92+ local start = ptr + 1
93+ local quot = find (json , ' "' , start , true )
94+
95+ local prev = quot - 1
96+ local key
97+
98+ if byte (json , prev ) ~= 92 --[[ \]] then
99+ ptr = quot + 1
100+ key = sub (json , start , prev )
101+ else
102+ key = slowstring ()
103+ end
104+
105+ if not skip (" ^%s*:()" ) then
95106 error (" Expected : to follow key for object at char " .. ptr )
96107 end
97108
@@ -102,38 +113,38 @@ local function decode(json --[[@param json string]]) ---@return any
102113 error (" Expected value for field " .. key .. " at char " .. ptr )
103114 end
104115
105- consume ( " ^%s*," )
106- until consume (" ^%s*}" )
116+ ptr = match ( json , " ^%s*,() " , ptr ) or ptr
117+ until skip (" ^%s*}() " )
107118
108119 return fields
109120 end ,
110121
111- [" [" ] = function ()
112- ptr = ptr + 1 -- Already know we're at the [ from value()
113-
122+ [91 --[=[ ]]=] ] = function ()
114123 local values , nvalues = {}, 0
115- if consume (" ^%s*%]" ) then return values end
124+ if skip (" ^%s*%]() " ) then return values end
116125
117126 repeat
118- nvalues = nvalues + 1
119127 local value = value ()
120128 if value ~= nil then
129+ nvalues = nvalues + 1
121130 values [nvalues ] = value
122131 else
123- error (" Expected value for field #" .. nvalues + 1 .. " at char " .. ptr )
132+ error (" Expected value for field #" .. nvalues .. " at char " .. ptr )
124133 end
125- consume (" ^%s*," )
126- until consume (" ^%s*%]" )
134+
135+ ptr = match (json , " ^%s*,()" , ptr ) or ptr
136+ until skip (" ^%s*%]()" )
127137
128138 return values
129139 end ,
130140
131- [" " ] = whitespace , [" \t " ] = whitespace , [" \n " ] = whitespace , [" \r " ] = whitespace ,
141+ [9 --[[ \t ]] ] = whitespace , [10 --[[ \n ]] ] = whitespace , [13 --[[ \r ]] ] = whitespace , [32 --[[ ]] ] = whitespace ,
132142 }
133143
134144 function value ()
135- local p = peek [sub (json , ptr , ptr )]
145+ local p = peek [byte (json , ptr )]
136146 if p then
147+ ptr = ptr + 1
137148 return p ()
138149 else
139150 error (" Failed parsing at character " .. ptr )
@@ -183,12 +194,11 @@ function _encode(tbl --[[@param tbl table]], buffer --[[@param buffer table]], n
183194 buffer [nbuffer ] = " ,"
184195 end
185196
186- if len ~= 0 then
187- buffer [nbuffer ] = " ]"
188- else
197+ if len == 0 then -- no trailing comma to replace. need to increment ptr
189198 nbuffer = nbuffer + 1
190- buffer [nbuffer ] = " ]"
191199 end
200+
201+ buffer [nbuffer ] = " ]"
192202 else
193203 nbuffer = nbuffer + 1
194204 buffer [nbuffer ] = " {"
@@ -201,12 +211,11 @@ function _encode(tbl --[[@param tbl table]], buffer --[[@param buffer table]], n
201211 buffer [nbuffer ] = " ,"
202212 end
203213
204- if nbuffer ~= prev then
205- buffer [nbuffer ] = " }"
206- else
214+ if nbuffer == prev then -- no trailing comma to replace. need to increment ptr
207215 nbuffer = nbuffer + 1
208- buffer [nbuffer ] = " }"
209216 end
217+
218+ buffer [nbuffer ] = " }"
210219 end
211220
212221 return nbuffer
0 commit comments