2 Licensed according to the included 'LICENSE' document
3 Author: Thomas Harning Jr <harningt@gmail.com>
5 local string_char
= require("string").char
8 local jsonutil
= require("json.util")
9 local util_merge
= jsonutil
.merge
13 local normalEncodingMap
= {
22 ['\v'] = '\\v' -- not in official spec, on report, removing
25 local xEncodingMap
= {}
26 for char
, encoded
in pairs(normalEncodingMap
) do
27 xEncodingMap
[char
] = encoded
30 -- Pre-encode the control characters to speed up encoding...
31 -- NOTE: UTF-8 may not work out right w/ JavaScript
32 -- JavaScript uses 2 bytes after a \u... yet UTF-8 is a
33 -- byte-stream encoding, not pairs of bytes (it does encode
34 -- some letters > 1 byte, but base case is 1)
36 local c
= string_char(i
)
37 if c
:match('[%z\1-\031\128-\255]') and not normalEncodingMap
[c
] then
38 -- WARN: UTF8 specializes values >= 0x80 as parts of sequences...
39 -- without \x encoding, do not allow encoding > 7F
40 normalEncodingMap
[c
] = ('\\u%.4X'):format(i
)
41 xEncodingMap
[c
] = ('\\x%.2X'):format(i
)
45 local defaultOptions
= {
46 xEncode
= false, -- Encode single-bytes as \xXX
47 processor
= nil, -- Simple processor for the string prior to quoting
48 -- / is not required to be quoted but it helps with certain decoding
49 -- Required encoded characters, " \, and 00-1F (0 - 31)
50 encodeSet
= '\\"/%z\1-\031',
51 encodeSetAppend
= nil -- Chars to append to the default set
54 local modeOptions
= {}
56 local function mergeOptions(options
, mode
)
57 jsonutil
.doOptionMerge(options
, false, 'strings', defaultOptions
, mode
and modeOptions
[mode
])
60 local function getEncoder(options
)
61 options
= options
and util_merge({}, defaultOptions
, options
) or defaultOptions
62 local encodeSet
= options
.encodeSet
63 if options
.encodeSetAppend
then
64 encodeSet
= encodeSet
.. options
.encodeSetAppend
66 local encodingMap
= options
.xEncode
and xEncodingMap
or normalEncodingMap
68 if options
.processor
then
69 local processor
= options
.processor
70 encodeString
= function(s
, state
)
71 return '"' .. processor(s
:gsub('[' .. encodeSet
.. ']', encodingMap
)) .. '"'
74 encodeString
= function(s
, state
)
75 return '"' .. s
:gsub('[' .. encodeSet
.. ']', encodingMap
) .. '"'
84 mergeOptions
= mergeOptions
,
85 getEncoder
= getEncoder