Skip to content

Commit d95bb11

Browse files
committed
Updated JSON to work with newer LPEG
1 parent cdb4461 commit d95bb11

18 files changed

+897
-271
lines changed

lua/json.lua

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
--[[
22
Licensed according to the included 'LICENSE' document
33
Author: Thomas Harning Jr <harningt@gmail.com>
4-
--]]
4+
]]
55
local decode = require("json.decode")
66
local encode = require("json.encode")
77
local util = require("json.util")
88

9-
module("json")
10-
_M.decode = decode
11-
_M.encode = encode
12-
_M.util = util
9+
local _G = _G
10+
11+
local _ENV = nil
12+
13+
local json = {
14+
_VERSION = "1.3.4",
15+
_DESCRIPTION = "LuaJSON : customizable JSON decoder/encoder",
16+
_COPYRIGHT = "Copyright (c) 2007-2014 Thomas Harning Jr. <harningt@gmail.com>",
17+
decode = decode,
18+
encode = encode,
19+
util = util
20+
}
21+
22+
_G.json = json
23+
24+
return json

lua/json/decode.lua

Lines changed: 93 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,137 @@
11
--[[
22
Licensed according to the included 'LICENSE' document
33
Author: Thomas Harning Jr <harningt@gmail.com>
4-
--]]
4+
]]
55
local lpeg = require("lpeg")
66

77
local error = error
8+
local pcall = pcall
89

9-
local object = require("json.decode.object")
10-
local array = require("json.decode.array")
11-
12-
local merge = require("json.util").merge
10+
local jsonutil = require("json.util")
11+
local merge = jsonutil.merge
1312
local util = require("json.decode.util")
1413

14+
local decode_state = require("json.decode.state")
15+
1516
local setmetatable, getmetatable = setmetatable, getmetatable
1617
local assert = assert
1718
local ipairs, pairs = ipairs, pairs
1819
local string_char = require("string").char
1920

21+
local type = type
22+
2023
local require = require
21-
module("json.decode")
24+
25+
local _ENV = nil
2226

2327
local modulesToLoad = {
24-
"array",
25-
"object",
28+
"composite",
2629
"strings",
2730
"number",
28-
"calls",
2931
"others"
3032
}
3133
local loadedModules = {
3234
}
3335

34-
default = {
36+
local json_decode = {}
37+
38+
json_decode.default = {
3539
unicodeWhitespace = true,
36-
initialObject = false
40+
initialObject = false,
41+
nothrow = false
3742
}
3843

3944
local modes_defined = { "default", "strict", "simple" }
4045

41-
simple = {}
46+
json_decode.simple = {}
4247

43-
strict = {
48+
json_decode.strict = {
4449
unicodeWhitespace = true,
45-
initialObject = true
50+
initialObject = true,
51+
nothrow = false
4652
}
4753

48-
-- Register generic value type
49-
util.register_type("VALUE")
5054
for _,name in ipairs(modulesToLoad) do
5155
local mod = require("json.decode." .. name)
52-
for _, mode in pairs(modes_defined) do
53-
if mod[mode] then
54-
_M[mode][name] = mod[mode]
56+
if mod.mergeOptions then
57+
for _, mode in pairs(modes_defined) do
58+
mod.mergeOptions(json_decode[mode], mode)
5559
end
5660
end
57-
loadedModules[name] = mod
58-
-- Register types
59-
if mod.register_types then
60-
mod.register_types()
61-
end
61+
loadedModules[#loadedModules + 1] = mod
6262
end
6363

6464
-- Shift over default into defaultOptions to permit build optimization
65-
local defaultOptions = default
66-
default = nil
67-
65+
local defaultOptions = json_decode.default
66+
json_decode.default = nil
67+
68+
local function generateDecoder(lexer, options)
69+
-- Marker to permit detection of final end
70+
local marker = {}
71+
local parser = lpeg.Ct((options.ignored * lexer)^0 * lpeg.Cc(marker)) * options.ignored * (lpeg.P(-1) + util.unexpected())
72+
local decoder = function(data)
73+
local state = decode_state.create(options)
74+
local parsed = parser:match(data)
75+
assert(parsed, "Invalid JSON data")
76+
local i = 0
77+
while true do
78+
i = i + 1
79+
local item = parsed[i]
80+
if item == marker then break end
81+
if type(item) == 'function' and item ~= jsonutil.undefined and item ~= jsonutil.null then
82+
item(state)
83+
else
84+
state:set_value(item)
85+
end
86+
end
87+
if options.initialObject then
88+
assert(type(state.previous) == 'table', "Initial value not an object or array")
89+
end
90+
-- Make sure stack is empty
91+
assert(state.i == 0, "Unclosed elements present")
92+
return state.previous
93+
end
94+
if options.nothrow then
95+
return function(data)
96+
local status, rv = pcall(decoder, data)
97+
if status then
98+
return rv
99+
else
100+
return nil, rv
101+
end
102+
end
103+
end
104+
return decoder
105+
end
68106

69107
local function buildDecoder(mode)
70108
mode = mode and merge({}, defaultOptions, mode) or defaultOptions
109+
for _, mod in ipairs(loadedModules) do
110+
if mod.mergeOptions then
111+
mod.mergeOptions(mode)
112+
end
113+
end
71114
local ignored = mode.unicodeWhitespace and util.unicode_ignored or util.ascii_ignored
72115
-- Store 'ignored' in the global options table
73116
mode.ignored = ignored
74117

75-
local value_id = util.types.VALUE
76-
local value_type = lpeg.V(value_id)
77-
local object_type = lpeg.V(util.types.OBJECT)
78-
local array_type = lpeg.V(util.types.ARRAY)
79-
local grammar = {
80-
[1] = mode.initialObject and (ignored * (object_type + array_type)) or value_type
81-
}
82-
for _, name in pairs(modulesToLoad) do
83-
local mod = loadedModules[name]
84-
mod.load_types(mode[name], mode, grammar)
85-
end
86-
-- HOOK VALUE TYPE WITH WHITESPACE
87-
grammar[value_id] = ignored * grammar[value_id] * ignored
88-
grammar = lpeg.P(grammar) * ignored * lpeg.Cp() * -1
89-
return function(data)
90-
local ret, next_index = lpeg.match(grammar, data)
91-
assert(nil ~= next_index, "Invalid JSON data")
92-
return ret
118+
--local grammar = {
119+
-- [1] = mode.initialObject and (ignored * (object_type + array_type)) or value_type
120+
--}
121+
local lexer
122+
for _, mod in ipairs(loadedModules) do
123+
local new_lexer = mod.generateLexer(mode)
124+
lexer = lexer and lexer + new_lexer or new_lexer
93125
end
126+
return generateDecoder(lexer, mode)
94127
end
95128

96129
-- Since 'default' is nil, we cannot take map it
97-
local defaultDecoder = buildDecoder(default)
130+
local defaultDecoder = buildDecoder(json_decode.default)
98131
local prebuilt_decoders = {}
99132
for _, mode in pairs(modes_defined) do
100-
if _M[mode] ~= nil then
101-
prebuilt_decoders[_M[mode]] = buildDecoder(_M[mode])
133+
if json_decode[mode] ~= nil then
134+
prebuilt_decoders[json_decode[mode]] = buildDecoder(json_decode[mode])
102135
end
103136
end
104137

@@ -110,23 +143,29 @@ Options:
110143
object => object decode options
111144
initialObject => whether or not to require the initial object to be a table/array
112145
allowUndefined => whether or not to allow undefined values
113-
--]]
114-
function getDecoder(mode)
115-
mode = mode == true and strict or mode or default
146+
]]
147+
local function getDecoder(mode)
148+
mode = mode == true and json_decode.strict or mode or json_decode.default
116149
local decoder = mode == nil and defaultDecoder or prebuilt_decoders[mode]
117150
if decoder then
118151
return decoder
119152
end
120153
return buildDecoder(mode)
121154
end
122155

123-
function decode(data, mode)
156+
local function decode(data, mode)
124157
local decoder = getDecoder(mode)
125158
return decoder(data)
126159
end
127160

128-
local mt = getmetatable(_M) or {}
161+
local mt = {}
129162
mt.__call = function(self, ...)
130163
return decode(...)
131164
end
132-
setmetatable(_M, mt)
165+
166+
json_decode.getDecoder = getDecoder
167+
json_decode.decode = decode
168+
json_decode.util = util
169+
setmetatable(json_decode, mt)
170+
171+
return json_decode

0 commit comments

Comments
 (0)