1
1
--[[
2
2
Licensed according to the included 'LICENSE' document
3
3
Author: Thomas Harning Jr <harningt@gmail.com>
4
- -- ]]
4
+ ]]
5
5
local lpeg = require (" lpeg" )
6
6
7
7
local error = error
8
+ local pcall = pcall
8
9
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
13
12
local util = require (" json.decode.util" )
14
13
14
+ local decode_state = require (" json.decode.state" )
15
+
15
16
local setmetatable , getmetatable = setmetatable , getmetatable
16
17
local assert = assert
17
18
local ipairs , pairs = ipairs , pairs
18
19
local string_char = require (" string" ).char
19
20
21
+ local type = type
22
+
20
23
local require = require
21
- module (" json.decode" )
24
+
25
+ local _ENV = nil
22
26
23
27
local modulesToLoad = {
24
- " array" ,
25
- " object" ,
28
+ " composite" ,
26
29
" strings" ,
27
30
" number" ,
28
- " calls" ,
29
31
" others"
30
32
}
31
33
local loadedModules = {
32
34
}
33
35
34
- default = {
36
+ local json_decode = {}
37
+
38
+ json_decode .default = {
35
39
unicodeWhitespace = true ,
36
- initialObject = false
40
+ initialObject = false ,
41
+ nothrow = false
37
42
}
38
43
39
44
local modes_defined = { " default" , " strict" , " simple" }
40
45
41
- simple = {}
46
+ json_decode . simple = {}
42
47
43
- strict = {
48
+ json_decode . strict = {
44
49
unicodeWhitespace = true ,
45
- initialObject = true
50
+ initialObject = true ,
51
+ nothrow = false
46
52
}
47
53
48
- -- Register generic value type
49
- util .register_type (" VALUE" )
50
54
for _ ,name in ipairs (modulesToLoad ) do
51
55
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 )
55
59
end
56
60
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
62
62
end
63
63
64
64
-- 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
68
106
69
107
local function buildDecoder (mode )
70
108
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
71
114
local ignored = mode .unicodeWhitespace and util .unicode_ignored or util .ascii_ignored
72
115
-- Store 'ignored' in the global options table
73
116
mode .ignored = ignored
74
117
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
93
125
end
126
+ return generateDecoder (lexer , mode )
94
127
end
95
128
96
129
-- Since 'default' is nil, we cannot take map it
97
- local defaultDecoder = buildDecoder (default )
130
+ local defaultDecoder = buildDecoder (json_decode . default )
98
131
local prebuilt_decoders = {}
99
132
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 ])
102
135
end
103
136
end
104
137
@@ -110,23 +143,29 @@ Options:
110
143
object => object decode options
111
144
initialObject => whether or not to require the initial object to be a table/array
112
145
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
116
149
local decoder = mode == nil and defaultDecoder or prebuilt_decoders [mode ]
117
150
if decoder then
118
151
return decoder
119
152
end
120
153
return buildDecoder (mode )
121
154
end
122
155
123
- function decode (data , mode )
156
+ local function decode (data , mode )
124
157
local decoder = getDecoder (mode )
125
158
return decoder (data )
126
159
end
127
160
128
- local mt = getmetatable ( _M ) or {}
161
+ local mt = {}
129
162
mt .__call = function (self , ...)
130
163
return decode (... )
131
164
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