json_light.lua

Mon, 31 Mar 2025 16:19:17 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Mon, 31 Mar 2025 16:19:17 -0500
changeset 47
242ea28b8cad
permissions
-rw-r--r--

bib insertion plugin

47
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1 --
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2 -- json.lua
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
3 --
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
4 -- Copyright (c) 2020 rxi
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
5 --
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
6 -- Permission is hereby granted, free of charge, to any person obtaining a copy of
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
7 -- this software and associated documentation files (the "Software"), to deal in
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
8 -- the Software without restriction, including without limitation the rights to
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
9 -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
10 -- of the Software, and to permit persons to whom the Software is furnished to do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
11 -- so, subject to the following conditions:
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12 --
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13 -- The above copyright notice and this permission notice shall be included in all
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14 -- copies or substantial portions of the Software.
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15 --
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18 -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19 -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 -- SOFTWARE.
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23 --
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25 local json = { _version = "0.1.2" }
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 -------------------------------------------------------------------------------
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 -- Encode
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
29 -------------------------------------------------------------------------------
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
30
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
31 local encode
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33 local escape_char_map = {
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34 [ "\\" ] = "\\",
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35 [ "\"" ] = "\"",
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
36 [ "\b" ] = "b",
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37 [ "\f" ] = "f",
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38 [ "\n" ] = "n",
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
39 [ "\r" ] = "r",
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40 [ "\t" ] = "t",
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41 }
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 local escape_char_map_inv = { [ "/" ] = "/" }
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 for k, v in pairs(escape_char_map) do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
45 escape_char_map_inv[v] = k
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 local function escape_char(c)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50 return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 local function encode_nil(val)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
55 return "null"
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
56 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
57
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
58
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
59 local function encode_table(val, stack)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
60 local res = {}
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
61 stack = stack or {}
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
62
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
63 -- Circular reference?
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
64 if stack[val] then error("circular reference") end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
65
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
66 stack[val] = true
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
67
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
68 if rawget(val, 1) ~= nil or next(val) == nil then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
69 -- Treat as array -- check keys are valid and it is not sparse
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
70 local n = 0
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 for k in pairs(val) do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
72 if type(k) ~= "number" then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
73 error("invalid table: mixed or invalid key types")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
74 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
75 n = n + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
76 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 if n ~= #val then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78 error("invalid table: sparse array")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80 -- Encode
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
81 for i, v in ipairs(val) do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
82 table.insert(res, encode(v, stack))
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
83 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
84 stack[val] = nil
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
85 return "[" .. table.concat(res, ",") .. "]"
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
86
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
87 else
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88 -- Treat as an object
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
89 for k, v in pairs(val) do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
90 if type(k) ~= "string" then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
91 error("invalid table: mixed or invalid key types")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
92 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
93 table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
94 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
95 stack[val] = nil
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
96 return "{" .. table.concat(res, ",") .. "}"
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
97 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
98 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
99
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
100
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
101 local function encode_string(val)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
102 return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
103 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
104
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
106 local function encode_number(val)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
107 -- Check for NaN, -inf and inf
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
108 if val ~= val or val <= -math.huge or val >= math.huge then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
109 error("unexpected number value '" .. tostring(val) .. "'")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
110 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
111 return string.format("%.14g", val)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
112 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
113
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
114
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
115 local type_func_map = {
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
116 [ "nil" ] = encode_nil,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
117 [ "table" ] = encode_table,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
118 [ "string" ] = encode_string,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
119 [ "number" ] = encode_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
120 [ "boolean" ] = tostring,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
121 }
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
122
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
123
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
124 encode = function(val, stack)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
125 local t = type(val)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
126 local f = type_func_map[t]
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
127 if f then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
128 return f(val, stack)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
129 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
130 error("unexpected type '" .. t .. "'")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
131 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
132
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
133
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
134 function json.encode(val)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
135 return ( encode(val) )
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
136 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
137
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
138
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
139 -------------------------------------------------------------------------------
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
140 -- Decode
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
141 -------------------------------------------------------------------------------
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
142
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
143 local parse
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
144
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
145 local function create_set(...)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
146 local res = {}
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
147 for i = 1, select("#", ...) do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
148 res[ select(i, ...) ] = true
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
149 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
150 return res
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
151 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
152
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
153 local space_chars = create_set(" ", "\t", "\r", "\n")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
154 local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
155 local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
156 local literals = create_set("true", "false", "null")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
157
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
158 local literal_map = {
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
159 [ "true" ] = true,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160 [ "false" ] = false,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
161 [ "null" ] = nil,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
162 }
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
163
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
164
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
165 local function next_char(str, idx, set, negate)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
166 for i = idx, #str do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
167 if set[str:sub(i, i)] ~= negate then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
168 return i
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
169 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
170 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
171 return #str + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
172 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
174
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
175 local function decode_error(str, idx, msg)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
176 local line_count = 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
177 local col_count = 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
178 for i = 1, idx - 1 do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
179 col_count = col_count + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
180 if str:sub(i, i) == "\n" then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
181 line_count = line_count + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
182 col_count = 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
183 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
184 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
185 error( string.format("%s at line %d col %d", msg, line_count, col_count) )
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
186 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
187
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
188
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
189 local function codepoint_to_utf8(n)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
190 -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
191 local f = math.floor
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
192 if n <= 0x7f then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
193 return string.char(n)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
194 elseif n <= 0x7ff then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
195 return string.char(f(n / 64) + 192, n % 64 + 128)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
196 elseif n <= 0xffff then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
197 return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
198 elseif n <= 0x10ffff then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200 f(n % 4096 / 64) + 128, n % 64 + 128)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
201 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202 error( string.format("invalid unicode codepoint '%x'", n) )
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
203 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 local function parse_unicode_escape(s)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
207 local n1 = tonumber( s:sub(1, 4), 16 )
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 local n2 = tonumber( s:sub(7, 10), 16 )
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 -- Surrogate pair?
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
210 if n2 then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
211 return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
212 else
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
213 return codepoint_to_utf8(n1)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
214 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
215 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
216
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
217
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
218 local function parse_string(str, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219 local res = ""
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
220 local j = i + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
221 local k = j
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
222
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
223 while j <= #str do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
224 local x = str:byte(j)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
226 if x < 32 then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
227 decode_error(str, j, "control character in string")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
228
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
229 elseif x == 92 then -- `\`: Escape
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
230 res = res .. str:sub(k, j - 1)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
231 j = j + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
232 local c = str:sub(j, j)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
233 if c == "u" then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
234 local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
235 or str:match("^%x%x%x%x", j + 1)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
236 or decode_error(str, j - 1, "invalid unicode escape in string")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
237 res = res .. parse_unicode_escape(hex)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
238 j = j + #hex
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
239 else
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
240 if not escape_chars[c] then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
241 decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
242 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
243 res = res .. escape_char_map_inv[c]
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
244 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
245 k = j + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
246
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
247 elseif x == 34 then -- `"`: End of string
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
248 res = res .. str:sub(k, j - 1)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
249 return res, j + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
250 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
251
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
252 j = j + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
253 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
254
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
255 decode_error(str, i, "expected closing quote for string")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
256 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
257
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
258
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
259 local function parse_number(str, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
260 local x = next_char(str, i, delim_chars)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
261 local s = str:sub(i, x - 1)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
262 local n = tonumber(s)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
263 if not n then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
264 decode_error(str, i, "invalid number '" .. s .. "'")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
265 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
266 return n, x
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
267 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
268
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
269
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
270 local function parse_literal(str, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
271 local x = next_char(str, i, delim_chars)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
272 local word = str:sub(i, x - 1)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
273 if not literals[word] then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
274 decode_error(str, i, "invalid literal '" .. word .. "'")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
275 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
276 return literal_map[word], x
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
277 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
278
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
279
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
280 local function parse_array(str, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
281 local res = {}
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
282 local n = 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
283 i = i + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
284 while 1 do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
285 local x
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
286 i = next_char(str, i, space_chars, true)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
287 -- Empty / end of array?
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
288 if str:sub(i, i) == "]" then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
289 i = i + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
290 break
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
291 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
292 -- Read token
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
293 x, i = parse(str, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
294 res[n] = x
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
295 n = n + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
296 -- Next token
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
297 i = next_char(str, i, space_chars, true)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
298 local chr = str:sub(i, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
299 i = i + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
300 if chr == "]" then break end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
301 if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
302 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
303 return res, i
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
304 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
305
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
306
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
307 local function parse_object(str, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
308 local res = {}
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
309 i = i + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
310 while 1 do
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
311 local key, val
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
312 i = next_char(str, i, space_chars, true)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
313 -- Empty / end of object?
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
314 if str:sub(i, i) == "}" then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
315 i = i + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
316 break
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
317 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
318 -- Read key
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
319 if str:sub(i, i) ~= '"' then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
320 decode_error(str, i, "expected string for key")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
321 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
322 key, i = parse(str, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
323 -- Read ':' delimiter
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
324 i = next_char(str, i, space_chars, true)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
325 if str:sub(i, i) ~= ":" then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
326 decode_error(str, i, "expected ':' after key")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
327 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
328 i = next_char(str, i + 1, space_chars, true)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
329 -- Read value
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
330 val, i = parse(str, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
331 -- Set
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
332 res[key] = val
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
333 -- Next token
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
334 i = next_char(str, i, space_chars, true)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
335 local chr = str:sub(i, i)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
336 i = i + 1
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
337 if chr == "}" then break end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
338 if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
339 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
340 return res, i
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
341 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
342
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
343
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
344 local char_func_map = {
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
345 [ '"' ] = parse_string,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
346 [ "0" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
347 [ "1" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
348 [ "2" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
349 [ "3" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
350 [ "4" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
351 [ "5" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
352 [ "6" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
353 [ "7" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
354 [ "8" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
355 [ "9" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
356 [ "-" ] = parse_number,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
357 [ "t" ] = parse_literal,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
358 [ "f" ] = parse_literal,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
359 [ "n" ] = parse_literal,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
360 [ "[" ] = parse_array,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
361 [ "{" ] = parse_object,
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
362 }
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
363
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
364
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
365 parse = function(str, idx)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
366 local chr = str:sub(idx, idx)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
367 local f = char_func_map[chr]
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
368 if f then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
369 return f(str, idx)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
370 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
371 decode_error(str, idx, "unexpected character '" .. chr .. "'")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
372 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
373
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
374
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
375 function json.decode(str)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
376 if type(str) ~= "string" then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
377 error("expected argument of type string, got " .. type(str))
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
378 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
379 local res, idx = parse(str, next_char(str, 1, space_chars, true))
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
380 idx = next_char(str, idx, space_chars, true)
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
381 if idx <= #str then
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
382 decode_error(str, idx, "trailing garbage")
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
383 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
384 return res
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
385 end
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
386
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
387
242ea28b8cad bib insertion plugin
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
388 return json

mercurial