decoder: fixes 5.2-strict mode state object
[luajson.git] / lua / json / decode / state.lua
blob8a2f8facde8a0348d4a55a183fed4b8e05b56d93
1 --[[
2 Licensed according to the included 'LICENSE' document
3 Author: Thomas Harning Jr <harningt@gmail.com>
4 ]]
6 local setmetatable = setmetatable
7 local jsonutil = require("json.util")
8 local assert = assert
9 local type = type
10 local next = next
11 local unpack = unpack
13 _ENV = nil
15 local state_ops = {}
16 local state_mt = {
17 __index = state_ops
20 function state_ops.pop(self)
21 self.previous_set = true
22 self.previous = self.active
23 local i = self.i
24 -- Load in this array into the active item
25 self.active = self.stack[i]
26 self.active_state = self.state_stack[i]
27 self.active_key = self.key_stack[i]
28 self.stack[i] = nil
29 self.state_stack[i] = nil
30 self.key_stack[i] = nil
32 self.i = i - 1
33 end
35 function state_ops.push(self)
36 local i = self.i + 1
37 self.i = i
39 self.stack[i] = self.active
40 self.state_stack[i] = self.active_state
41 self.key_stack[i] = self.active_key
42 end
44 function state_ops.put_object_value(self, trailing)
45 local object_options = self.options.object
46 if trailing and object_options.trailingComma then
47 if not self.active_key then
48 return
49 end
50 end
51 assert(self.active_key, "Missing key value")
52 object_options.setObjectKey(self.active, self.active_key, self:grab_value())
53 self.active_key = nil
54 end
56 function state_ops.put_array_value(self, trailing)
57 -- Safety check
58 if trailing and not self.previous_set and self.options.array.trailingComma then
59 return
60 end
61 local new_index = self.active_state + 1
62 self.active_state = new_index
63 self.active[new_index] = self:grab_value()
64 end
66 function state_ops.put_value(self, trailing)
67 if self.active_state == 'object' then
68 self:put_object_value(trailing)
69 else
70 self:put_array_value(trailing)
71 end
72 end
74 function state_ops.new_array(self)
75 local new_array = {}
76 if jsonutil.InitArray then
77 new_array = jsonutil.InitArray(new_array) or new_array
78 end
79 self.active = new_array
80 self.active_state = 0
81 self.active_key = nil
82 self:unset_value()
83 end
85 function state_ops.end_array(self)
86 if self.previous_set or self.active_state ~= 0 then
87 -- Not an empty array
88 self:put_value(true)
89 end
90 if self.active_state ~= #self.active then
91 -- Store the length in
92 self.active.n = self.active_state
93 end
94 end
96 function state_ops.new_object(self)
97 local new_object = {}
98 self.active = new_object
99 self.active_state = 'object'
100 self.active_key = nil
101 self:unset_value()
104 function state_ops.end_object(self)
105 if self.previous_set or next(self.active) then
106 -- Not an empty object
107 self:put_value(true)
111 function state_ops.new_call(self, name, func)
112 -- TODO setup properly
113 local new_call = {}
114 new_call.name = name
115 new_call.func = func
116 self.active = new_call
117 self.active_state = 0
118 self.active_key = nil
119 self:unset_value()
122 function state_ops.end_call(self)
123 if self.previous_set or self.active_state ~= 0 then
124 -- Not an empty array
125 self:put_value(true)
127 if self.active_state ~= #self.active then
128 -- Store the length in
129 self.active.n = self.active_state
131 local func = self.active.func
132 if func == true then
133 func = jsonutil.buildCall
135 self.active = func(self.active.name, unpack(self.active, 1, self.active.n or #self.active))
139 function state_ops.unset_value(self)
140 self.previous_set = false
141 self.previous = nil
144 function state_ops.grab_value(self)
145 assert(self.previous_set, "Previous value not set")
146 self.previous_set = false
147 return self.previous
150 function state_ops.set_value(self, value)
151 assert(not self.previous_set, "Value set when one already in slot")
152 self.previous_set = true
153 self.previous = value
156 function state_ops.set_key(self)
157 assert(self.active_state == 'object', "Cannot set key on array")
158 local value = self:grab_value()
159 local value_type = type(value)
160 if self.options.object.number then
161 assert(value_type == 'string' or value_type == 'number', "As configured, a key must be a number or string")
162 else
163 assert(value_type == 'string', "As configured, a key must be a string")
165 self.active_key = value
169 local function create(options)
170 local ret = {
171 options = options,
172 stack = {},
173 state_stack = {},
174 key_stack = {},
175 i = 0,
176 active = nil,
177 active_key = nil,
178 previous = nil,
179 active_state = nil
182 return setmetatable(ret, state_mt)
185 local state = {
186 create = create
189 return state