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