aboutsummaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorMark Pulford <mark@kyne.com.au>2012-01-13 07:17:48 +1030
committerMark Pulford <mark@kyne.com.au>2012-03-04 18:54:34 +1030
commit5fb9fe1c67a070d1e83497c44b7b7364da9f1975 (patch)
tree861deaac983fcc04801e1f9f645f3dc7729f773b /lua
parent3871cb71c858b8e542b78677f782b88ddd820cb3 (diff)
downloadlua-cjson-5fb9fe1c67a070d1e83497c44b7b7364da9f1975.tar.gz
lua-cjson-5fb9fe1c67a070d1e83497c44b7b7364da9f1975.tar.bz2
lua-cjson-5fb9fe1c67a070d1e83497c44b7b7364da9f1975.zip
Move cjson-misc and scripts to "lua" directory
Diffstat (limited to 'lua')
-rw-r--r--lua/cjson-misc.lua277
-rwxr-xr-xlua/json2lua.lua14
-rwxr-xr-xlua/lua2json.lua20
3 files changed, 311 insertions, 0 deletions
diff --git a/lua/cjson-misc.lua b/lua/cjson-misc.lua
new file mode 100644
index 0000000..2142464
--- /dev/null
+++ b/lua/cjson-misc.lua
@@ -0,0 +1,277 @@
1local json = require "cjson"
2
3-- Various common routines used by the Lua CJSON package
4--
5-- Mark Pulford <mark@kyne.com.au>
6
7-- Determine with a Lua table can be treated as an array.
8-- Explicitly returns "not an array" for very sparse arrays.
9-- Returns:
10-- -1 Not an array
11-- 0 Empty table
12-- >0 Highest index in the array
13local function is_array(table)
14 local max = 0
15 local count = 0
16 for k, v in pairs(table) do
17 if type(k) == "number" then
18 if k > max then max = k end
19 count = count + 1
20 else
21 return -1
22 end
23 end
24 if max > count * 2 then
25 return -1
26 end
27
28 return max
29end
30
31local serialise_value
32
33local function serialise_table(value, indent, depth)
34 local spacing, spacing2, indent2
35 if indent then
36 spacing = "\n" .. indent
37 spacing2 = spacing .. " "
38 indent2 = indent .. " "
39 else
40 spacing, spacing2, indent2 = " ", " ", false
41 end
42 depth = depth + 1
43 if depth > 50 then
44 return "Cannot serialise any further: too many nested tables"
45 end
46
47 local max = is_array(value)
48
49 local comma = false
50 local fragment = { "{" .. spacing2 }
51 if max > 0 then
52 -- Serialise array
53 for i = 1, max do
54 if comma then
55 table.insert(fragment, "," .. spacing2)
56 end
57 table.insert(fragment, serialise_value(value[i], indent2, depth))
58 comma = true
59 end
60 elseif max < 0 then
61 -- Serialise table
62 for k, v in pairs(value) do
63 if comma then
64 table.insert(fragment, "," .. spacing2)
65 end
66 table.insert(fragment, string.format(
67 "[%s] = %s", serialise_value(k, indent2, depth),
68 serialise_value(v, indent2, depth))
69 )
70 comma = true
71 end
72 end
73 table.insert(fragment, spacing .. "}")
74
75 return table.concat(fragment)
76end
77
78function serialise_value(value, indent, depth)
79 if indent == nil then indent = "" end
80 if depth == nil then depth = 0 end
81
82 if value == json.null then
83 return "json.null"
84 elseif type(value) == "string" then
85 return string.format("%q", value)
86 elseif type(value) == "nil" or type(value) == "number" or
87 type(value) == "boolean" then
88 return tostring(value)
89 elseif type(value) == "table" then
90 return serialise_table(value, indent, depth)
91 else
92 return "\"<" .. type(value) .. ">\""
93 end
94end
95
96local function file_load(filename)
97 local file
98 if filename == nil then
99 file = io.stdin
100 else
101 local err
102 file, err = io.open(filename)
103 if file == nil then
104 error(string.format("Unable to read '%s': %s", filename, err))
105 end
106 end
107 local data = file:read("*a")
108
109 if filename ~= nil then
110 file:close()
111 end
112
113 if data == nil then
114 error("Failed to read " .. filename)
115 end
116
117 return data
118end
119
120local function file_save(filename, data)
121 local file
122 if filename == nil then
123 file = io.stdout
124 else
125 local err
126 file, err = io.open(filename, "w")
127 if file == nil then
128 error(string.format("Unable to write '%s': %s", filename, err))
129 end
130 end
131 file:write(data)
132 if filename ~= nil then
133 file:close()
134 end
135end
136
137local function compare_values(val1, val2)
138 local type1 = type(val1)
139 local type2 = type(val2)
140 if type1 ~= type2 then
141 return false
142 end
143
144 -- Check for NaN
145 if type1 == "number" and val1 ~= val1 and val2 ~= val2 then
146 return true
147 end
148
149 if type1 ~= "table" then
150 return val1 == val2
151 end
152
153 -- check_keys stores all the keys that must be checked in val2
154 local check_keys = {}
155 for k, _ in pairs(val1) do
156 check_keys[k] = true
157 end
158
159 for k, v in pairs(val2) do
160 if not check_keys[k] then
161 return false
162 end
163
164 if not compare_values(val1[k], val2[k]) then
165 return false
166 end
167
168 check_keys[k] = nil
169 end
170 for k, _ in pairs(check_keys) do
171 -- Not the same if any keys from val1 were not found in val2
172 return false
173 end
174 return true
175end
176
177local test_count_pass = 0
178local test_count_total = 0
179
180local function run_test_summary()
181 return test_count_pass, test_count_total
182end
183
184local function run_test(testname, func, input, should_work, output)
185 local function status_line(name, status, value)
186 local statusmap = { [true] = ":success", [false] = ":error" }
187 if status ~= nil then
188 name = name .. statusmap[status]
189 end
190 print(string.format("[%s] %s", name, serialise_value(value, false)))
191 end
192
193 local result = { pcall(func, unpack(input)) }
194 local success = table.remove(result, 1)
195
196 local correct = false
197 if success == should_work and compare_values(result, output) then
198 correct = true
199 test_count_pass = test_count_pass + 1
200 end
201 test_count_total = test_count_total + 1
202
203 local teststatus = { [true] = "PASS", [false] = "FAIL" }
204 print(string.format("==> Test[%d] / %s: %s",
205 test_count_total, testname, teststatus[correct]))
206
207 status_line("Input", nil, input)
208 if not correct then
209 status_line("Expected", should_work, output)
210 end
211 status_line("Received", success, result)
212 print()
213
214 return correct, result
215end
216
217local function run_test_group(testgroup, tests)
218 local function run_config(configname, func)
219 local success, msg = pcall(func)
220 if msg then
221 print(string.format("==> Config %s: %s", configname, msg))
222 end
223 print()
224 end
225
226 local function test_id(group, id)
227 return string.format("%s[%d]", group, id)
228 end
229
230 for k, v in ipairs(tests) do
231 if type(v) == "function" then
232 -- Useful for changing configuration during a batch
233 run_config(test_id(testgroup, k), v)
234 elseif type(v) == "table" then
235 run_test(test_id(testgroup, k), unpack(v))
236 else
237 error("Testgroup can only contain functions and tables")
238 end
239 end
240end
241
242-- Run a Lua script in a separate environment
243local function run_script(script, env)
244 local env = env or {}
245 local func
246
247 -- Use setfenv() if it exists, otherwise assume Lua 5.2 load() exists
248 if _G.setfenv then
249 func = loadstring(script)
250 if func then
251 setfenv(func, env)
252 end
253 else
254 func = load(script, nil, nil, env)
255 end
256
257 if func == nil then
258 error("Invalid syntax.")
259 end
260 func()
261
262 return env
263end
264
265-- Export functions
266return {
267 serialise_value = serialise_value,
268 file_load = file_load,
269 file_save = file_save,
270 compare_values = compare_values,
271 run_test_summary = run_test_summary,
272 run_test = run_test,
273 run_test_group = run_test_group,
274 run_script = run_script
275}
276
277-- vi:ai et sw=4 ts=4:
diff --git a/lua/json2lua.lua b/lua/json2lua.lua
new file mode 100755
index 0000000..050b89d
--- /dev/null
+++ b/lua/json2lua.lua
@@ -0,0 +1,14 @@
1#!/usr/bin/env lua
2
3-- usage: json2lua.lua [json_file]
4--
5-- Eg:
6-- echo '[ "testing" ]' | ./json2lua.lua
7-- ./json2lua.lua test.json
8
9local json = require "cjson"
10local misc = require "cjson-misc"
11
12local json_text = misc.file_load(arg[1])
13local t = json.decode(json_text)
14print(misc.serialise_value(t))
diff --git a/lua/lua2json.lua b/lua/lua2json.lua
new file mode 100755
index 0000000..2a9ddf9
--- /dev/null
+++ b/lua/lua2json.lua
@@ -0,0 +1,20 @@
1#!/usr/bin/env lua
2
3-- usage: lua2json.lua [lua_file]
4--
5-- Eg:
6-- echo '{ "testing" }' | ./lua2json.lua
7-- ./lua2json.lua test.lua
8
9local json = require "cjson"
10local misc = require "cjson-misc"
11
12local env = {
13 json = { null = json.null },
14 null = json.null
15}
16
17local t = misc.run_script("data = " .. misc.file_load(arg[1]), env)
18print(json.encode(t.data))
19
20-- vi:ai et sw=4 ts=4: