summaryrefslogtreecommitdiff
path: root/lua-resty-dns-0.23/t/lib/ljson.lua
blob: 1084724935b7625f694c13ee84bf9be34e4e6a4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
local ngx_null = ngx.null
local tostring = tostring
local byte = string.byte
local gsub = string.gsub
local sort = table.sort
local pairs = pairs
local ipairs = ipairs
local concat = table.concat

local ok, new_tab = pcall(require, "table.new")
if not ok then
    new_tab = function (narr, nrec) return {} end
end

local _M = {}

local metachars = {
    ['\t'] = '\\t',
    ["\\"] = "\\\\",
    ['"'] = '\\"',
    ['\r'] = '\\r',
    ['\n'] = '\\n',
}

local function encode_str(s)
    -- XXX we will rewrite this when string.buffer is implemented
    -- in LuaJIT 2.1 because string.gsub cannot be JIT compiled.
    return gsub(s, '["\\\r\n\t]', metachars)
end

local function is_arr(t)
    local exp = 1
    for k, _ in pairs(t) do
        if k ~= exp then
            return nil
        end
        exp = exp + 1
    end
    return exp - 1
end

local encode

encode = function (v)
    if v == nil or v == ngx_null then
        return "null"
    end

    local typ = type(v)
    if typ == 'string' then
        return '"' .. encode_str(v) .. '"'
    end

    if typ == 'number' or typ == 'boolean' then
        return tostring(v)
    end

    if typ == 'table' then
        local n = is_arr(v)
        if n then
            local bits = new_tab(n, 0)
            for i, elem in ipairs(v) do
                bits[i] = encode(elem)
            end
            return "[" .. concat(bits, ",") .. "]"
        end

        local keys = {}
        local i = 0
        for key, _ in pairs(v) do
            i = i + 1
            keys[i] = key
        end
        sort(keys)

        local bits = new_tab(0, i)
        i = 0
        for _, key in ipairs(keys) do
            i = i + 1
            bits[i] = encode(key) .. ":" .. encode(v[key])
        end
        return "{" .. concat(bits, ",") .. "}"
    end

    return '"<' .. typ .. '>"'
end
_M.encode = encode

return _M