2 Licensed according to the included 'LICENSE' document
3 Author: Thomas Harning Jr <harningt@gmail.com>
6 local setmetatable
= setmetatable
7 local jsonutil
= require("json.util")
11 local unpack
= require("table").unpack
or unpack
20 function state_ops
.pop(self
)
21 self
.previous_set
= true
22 self
.previous
= self
.active
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
]
29 self
.state_stack
[i
] = nil
30 self
.key_stack
[i
] = nil
35 function state_ops
.push(self
)
39 self
.stack
[i
] = self
.active
40 self
.state_stack
[i
] = self
.active_state
41 self
.key_stack
[i
] = self
.active_key
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
51 assert(self
.active_key
, "Missing key value")
52 object_options
.setObjectKey(self
.active
, self
.active_key
, self
:grab_value(object_options
.allowEmptyElement
))
56 function state_ops
.put_array_value(self
, trailing
)
57 local array_options
= self
.options
.array
59 if trailing
and not self
.previous_set
and array_options
.trailingComma
then
62 local new_index
= self
.active_state
+ 1
63 self
.active_state
= new_index
64 self
.active
[new_index
] = self
:grab_value(array_options
.allowEmptyElement
)
67 function state_ops
.put_call_value(self
, trailing
)
68 local call_options
= self
.options
.calls
70 if trailing
and not self
.previous_set
and call_options
.trailingComma
then
73 local new_index
= self
.active_state
+ 1
74 self
.active_state
= new_index
75 self
.active
[new_index
] = self
:grab_value(call_options
.allowEmptyElement
)
78 function state_ops
.put_value(self
, trailing
)
79 if self
.active_state
== 'object' then
80 self
:put_object_value(trailing
)
81 elseif self
.active
.func
then
82 self
:put_call_value(trailing
)
84 self
:put_array_value(trailing
)
88 function state_ops
.new_array(self
)
90 if jsonutil
.InitArray
then
91 new_array
= jsonutil
.InitArray(new_array
) or new_array
93 self
.active
= new_array
99 function state_ops
.end_array(self
)
100 if self
.previous_set
or self
.active_state
~= 0 then
101 -- Not an empty array
104 if self
.active_state
~= #self
.active
then
105 -- Store the length in
106 self
.active
.n
= self
.active_state
110 function state_ops
.new_object(self
)
111 local new_object
= {}
112 self
.active
= new_object
113 self
.active_state
= 'object'
114 self
.active_key
= nil
118 function state_ops
.end_object(self
)
119 if self
.active_key
or self
.previous_set
or next(self
.active
) then
120 -- Not an empty object
125 function state_ops
.new_call(self
, name
, func
)
126 -- TODO setup properly
130 self
.active
= new_call
131 self
.active_state
= 0
132 self
.active_key
= nil
136 function state_ops
.end_call(self
)
137 if self
.previous_set
or self
.active_state
~= 0 then
138 -- Not an empty array
141 if self
.active_state
~= #self
.active
then
142 -- Store the length in
143 self
.active
.n
= self
.active_state
145 local func
= self
.active
.func
147 func
= jsonutil
.buildCall
149 self
.active
= func(self
.active
.name
, unpack(self
.active
, 1, self
.active
.n
or #self
.active
))
153 function state_ops
.unset_value(self
)
154 self
.previous_set
= false
158 function state_ops
.grab_value(self
, allowEmptyValue
)
159 if not self
.previous_set
and allowEmptyValue
then
160 -- Calculate an appropriate empty-value
161 return self
.emptyValue
163 assert(self
.previous_set
, "Previous value not set")
164 self
.previous_set
= false
168 function state_ops
.set_value(self
, value
)
169 assert(not self
.previous_set
, "Value set when one already in slot")
170 self
.previous_set
= true
171 self
.previous
= value
174 function state_ops
.set_key(self
)
175 assert(self
.active_state
== 'object', "Cannot set key on array")
176 local value
= self
:grab_value()
177 local value_type
= type(value
)
178 if self
.options
.object
.number then
179 assert(value_type
== 'string' or value_type
== 'number', "As configured, a key must be a number or string")
181 assert(value_type
== 'string', "As configured, a key must be a string")
183 self
.active_key
= value
187 local function create(options
)
189 -- Calculate an empty value up front
190 if options
.others
.allowUndefined
then
191 emptyValue
= options
.others
.undefined
or nil
193 emptyValue
= options
.others
.null
or nil
205 emptyValue
= emptyValue
207 return setmetatable(ret
, state_mt
)