+-- Prosody IM
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
+--
+-- utf8char copyright (C) 2007 Rici Lake
+--
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
+--
local type = type;
-local t_insert, t_concat, t_remove = table.insert, table.concat, table.remove;
+local t_insert, t_concat, t_remove, t_sort = table.insert, table.concat, table.remove, table.sort;
local s_char = string.char;
local tostring, tonumber = tostring, tonumber;
local pairs, ipairs = pairs, ipairs;
if not escapes[ch] then escapes[ch] = ("\\u%.4X"):format(i); end
end
+local function utf8char(i)
+ if i >= 0 then
+ i = i - i%1
+ if i < 128 then
+ return s_char(i)
+ else
+ local c1 = i % 64
+ i = (i - c1) / 64
+ if i < 32 then
+ return s_char(0xC0+i, 0x80+c1)
+ else
+ local c2 = i % 64
+ i = (i - c2) / 64
+ if i < 16 and (i ~= 13 or c2 < 32) then
+ return s_char(0xE0+i, 0x80+c2, 0x80+c1)
+ elseif i >= 16 and i < 0x110 then
+ local c3 = i % 64
+ i = (i - c3) / 64
+ return s_char(0xF0+i, 0x80+c3, 0x80+c2, 0x80+c1)
+ end
+ end
+ end
+ end
+end
+
+
local valid_types = {
number = true,
string = true,
if next(__hash) ~= nil or next(hash) ~= nil or next(__array) == nil then
t_insert(buffer, "{");
local mark = #buffer;
- for k,v in pairs(hash) do
- stringsave(k, buffer);
- t_insert(buffer, ":");
- simplesave(v, buffer);
- t_insert(buffer, ",");
+ if buffer.ordered then
+ local keys = {};
+ for k in pairs(hash) do
+ t_insert(keys, k);
+ end
+ t_sort(keys);
+ for _,k in ipairs(keys) do
+ stringsave(k, buffer);
+ t_insert(buffer, ":");
+ simplesave(hash[k], buffer);
+ t_insert(buffer, ",");
+ end
+ else
+ for k,v in pairs(hash) do
+ stringsave(k, buffer);
+ t_insert(buffer, ":");
+ simplesave(v, buffer);
+ t_insert(buffer, ",");
+ end
end
if next(__hash) ~= nil then
t_insert(buffer, "\"__hash\":[");
simplesave(obj, t);
return t_concat(t);
end
+function json.encode_ordered(obj)
+ local t = { ordered = true };
+ simplesave(obj, t);
+ return t_concat(t);
+end
+function json.encode_array(obj)
+ local t = {};
+ arraysave(obj, t);
+ return t_concat(t);
+end
-----------------------------------
function json.decode(json)
+ json = json.." "; -- appending a space ensures valid json wouldn't touch EOF
local pos = 1;
local current = {};
local stack = {};
local ch, peek;
local function next()
ch = json:sub(pos, pos);
+ if ch == "" then error("Unexpected EOF"); end
pos = pos+1;
peek = json:sub(pos, pos);
return ch;
skipwhitespace();
if ch == "/" and peek == "*" then
skipstarcomment();
- elseif ch == "/" and peek == "*" then
+ elseif ch == "/" and peek == "/" then
skiplinecomment();
else
return;
if not ch:match("[0-9a-fA-F]") then error("invalid unicode escape sequence in string"); end
seq = seq..ch;
end
- s = s..s.char(tonumber(seq, 16)); -- FIXME do proper utf-8
+ s = s..utf8char(tonumber(seq, 16));
next();
else error("invalid escape sequence in string"); end
end