@@ -31,23 +31,23 @@ local json = { _version = "0.1.2" }
3131local encode
3232
3333local escape_char_map = {
34- [ " \\ " ] = " \\\\ " ,
35- [ " \" " ] = " \\\ " " ,
36- [ " \b " ] = " \\ b" ,
37- [ " \f " ] = " \\ f" ,
38- [ " \n " ] = " \\ n" ,
39- [ " \r " ] = " \\ r" ,
40- [ " \t " ] = " \\ t" ,
34+ [ " \\ " ] = " \\ " ,
35+ [ " \" " ] = " \" " ,
36+ [ " \b " ] = " b" ,
37+ [ " \f " ] = " f" ,
38+ [ " \n " ] = " n" ,
39+ [ " \r " ] = " r" ,
40+ [ " \t " ] = " t" ,
4141}
4242
43- local escape_char_map_inv = { [ " \\ /" ] = " /" }
43+ local escape_char_map_inv = { [ " /" ] = " /" }
4444for k , v in pairs (escape_char_map ) do
4545 escape_char_map_inv [v ] = k
4646end
4747
4848
4949local function escape_char (c )
50- return escape_char_map [c ] or string.format (" \\ u%04x" , c :byte ())
50+ return " \\ " .. ( escape_char_map [c ] or string.format (" u%04x" , c :byte () ))
5151end
5252
5353
204204
205205
206206local function parse_unicode_escape (s )
207- local n1 = tonumber ( s :sub (3 , 6 ), 16 )
208- local n2 = tonumber ( s :sub (9 , 12 ), 16 )
209- -- Surrogate pair?
207+ local n1 = tonumber ( s :sub (1 , 4 ), 16 )
208+ local n2 = tonumber ( s :sub (7 , 10 ), 16 )
209+ -- Surrogate pair?
210210 if n2 then
211211 return codepoint_to_utf8 ((n1 - 0xd800 ) * 0x400 + (n2 - 0xdc00 ) + 0x10000 )
212212 else
@@ -216,54 +216,42 @@ end
216216
217217
218218local function parse_string (str , i )
219- local has_unicode_escape = false
220- local has_surrogate_escape = false
221- local has_escape = false
222- local last
223- for j = i + 1 , # str do
219+ local res = " "
220+ local j = i + 1
221+ local k = j
222+
223+ while j <= # str do
224224 local x = str :byte (j )
225225
226226 if x < 32 then
227227 decode_error (str , j , " control character in string" )
228- end
229228
230- if last == 92 then -- "\\" (escape char)
231- if x == 117 then -- "u" (unicode escape sequence)
232- local hex = str :sub (j + 1 , j + 5 )
233- if not hex :find (" %x%x%x%x" ) then
234- decode_error (str , j , " invalid unicode escape in string" )
235- end
236- if hex :find (" ^[dD][89aAbB]" ) then
237- has_surrogate_escape = true
238- else
239- has_unicode_escape = true
240- end
229+ elseif x == 92 then -- `\`: Escape
230+ res = res .. str :sub (k , j - 1 )
231+ j = j + 1
232+ local c = str :sub (j , j )
233+ if c == " u" then
234+ local hex = str :match (" ^[dD][89aAbB]%x%x\\ u%x%x%x%x" , j + 1 )
235+ or str :match (" ^%x%x%x%x" , j + 1 )
236+ or decode_error (str , j - 1 , " invalid unicode escape in string" )
237+ res = res .. parse_unicode_escape (hex )
238+ j = j + # hex
241239 else
242- local c = string.char (x )
243240 if not escape_chars [c ] then
244- decode_error (str , j , " invalid escape char '" .. c .. " ' in string" )
241+ decode_error (str , j - 1 , " invalid escape char '" .. c .. " ' in string" )
245242 end
246- has_escape = true
247- end
248- last = nil
249-
250- elseif x == 34 then -- '"' (end of string)
251- local s = str :sub (i + 1 , j - 1 )
252- if has_surrogate_escape then
253- s = s :gsub (" \\ u[dD][89aAbB]..\\ u...." , parse_unicode_escape )
254- end
255- if has_unicode_escape then
256- s = s :gsub (" \\ u...." , parse_unicode_escape )
257- end
258- if has_escape then
259- s = s :gsub (" \\ ." , escape_char_map_inv )
243+ res = res .. escape_char_map_inv [c ]
260244 end
261- return s , j + 1
245+ k = j + 1
262246
263- else
264- last = x
247+ elseif x == 34 then -- `"`: End of string
248+ res = res .. str :sub (k , j - 1 )
249+ return res , j + 1
265250 end
251+
252+ j = j + 1
266253 end
254+
267255 decode_error (str , i , " expected closing quote for string" )
268256end
269257
0 commit comments