all: 5.2 compatibility
[luajson.git] / lua / json / encode / strings.lua
blob3330fe1c42d7d292f0237aa64ec4c3f6e36ac3c3
1 --[[
2 Licensed according to the included 'LICENSE' document
3 Author: Thomas Harning Jr <harningt@gmail.com>
4 ]]
5 local string_char = require("string").char
6 local pairs = pairs
8 local util_merge = require("json.util").merge
10 local is_52 = _VERSION == "Lua 5.2"
11 local _G = _G
13 if is_52 then
14 _ENV = nil
15 end
17 local normalEncodingMap = {
18 ['"'] = '\\"',
19 ['\\'] = '\\\\',
20 ['/'] = '\\/',
21 ['\b'] = '\\b',
22 ['\f'] = '\\f',
23 ['\n'] = '\\n',
24 ['\r'] = '\\r',
25 ['\t'] = '\\t',
26 ['\v'] = '\\v' -- not in official spec, on report, removing
29 local xEncodingMap = {}
30 for char, encoded in pairs(normalEncodingMap) do
31 xEncodingMap[char] = encoded
32 end
34 -- Pre-encode the control characters to speed up encoding...
35 -- NOTE: UTF-8 may not work out right w/ JavaScript
36 -- JavaScript uses 2 bytes after a \u... yet UTF-8 is a
37 -- byte-stream encoding, not pairs of bytes (it does encode
38 -- some letters > 1 byte, but base case is 1)
39 for i = 0, 255 do
40 local c = string_char(i)
41 if c:match('[%z\1-\031\128-\255]') and not normalEncodingMap[c] then
42 -- WARN: UTF8 specializes values >= 0x80 as parts of sequences...
43 -- without \x encoding, do not allow encoding > 7F
44 normalEncodingMap[c] = ('\\u%.4X'):format(i)
45 xEncodingMap[c] = ('\\x%.2X'):format(i)
46 end
47 end
49 local defaultOptions = {
50 xEncode = false, -- Encode single-bytes as \xXX
51 processor = nil, -- Simple processor for the string prior to quoting
52 -- / is not required to be quoted but it helps with certain decoding
53 -- Required encoded characters, " \, and 00-1F (0 - 31)
54 encodeSet = '\\"/%z\1-\031',
55 encodeSetAppend = nil -- Chars to append to the default set
58 local default = nil
59 local strict = nil
61 local function getEncoder(options)
62 options = options and util_merge({}, defaultOptions, options) or defaultOptions
63 local encodeSet = options.encodeSet
64 if options.encodeSetAppend then
65 encodeSet = encodeSet .. options.encodeSetAppend
66 end
67 local encodingMap = options.xEncode and xEncodingMap or normalEncodingMap
68 local encodeString
69 if options.processor then
70 local processor = options.processor
71 encodeString = function(s, state)
72 return '"' .. processor(s:gsub('[' .. encodeSet .. ']', encodingMap)) .. '"'
73 end
74 else
75 encodeString = function(s, state)
76 return '"' .. s:gsub('[' .. encodeSet .. ']', encodingMap) .. '"'
77 end
78 end
79 return {
80 string = encodeString
82 end
84 local strings = {
85 default = default,
86 strict = strict,
87 getEncoder = getEncoder
90 if not is_52 then
91 _G.json = _G.json or {}
92 _G.json.encode = _G.json.encode or {}
93 _G.json.encode.strings = strings
94 end
96 return strings