]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | %% Licensed to the Apache Software Foundation (ASF) under one |
2 | %% or more contributor license agreements. See the NOTICE file | |
3 | %% distributed with this work for additional information | |
4 | %% regarding copyright ownership. The ASF licenses this file | |
5 | %% to you under the Apache License, Version 2.0 (the | |
6 | %% "License"); you may not use this file except in compliance | |
7 | %% with the License. You may obtain a copy of the License at | |
8 | %% | |
9 | %% http://www.apache.org/licenses/LICENSE-2.0 | |
10 | %% | |
11 | %% Unless required by applicable law or agreed to in writing, | |
12 | %% software distributed under the License is distributed on an | |
13 | %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | %% KIND, either express or implied. See the License for the | |
15 | %% specific language governing permissions and limitations | |
16 | %% under the License. | |
17 | %% | |
18 | %% The json parser implementation was created by | |
19 | %% alisdair sullivan <alisdair@hartbrake.com> based on | |
20 | %% the jsx json library | |
21 | ||
22 | -module(thrift_json_parser). | |
23 | -export([parser/0, handle_event/2]). | |
24 | ||
25 | ||
26 | -record(config, {strict_utf8 = false :: boolean()}). | |
27 | ||
28 | ||
29 | parser() -> fun(JSON) -> start(JSON, {?MODULE, []}, [], #config{}) end. | |
30 | ||
31 | ||
32 | handle_event(Event, {Handler, State}, _Config) -> {Handler, Handler:handle_event(Event, State)}. | |
33 | ||
34 | handle_event(end_json, State) -> lists:reverse([end_json] ++ State); | |
35 | handle_event(Event, State) -> [Event] ++ State. | |
36 | ||
37 | ||
38 | %% whitespace | |
39 | -define(space, 16#20). | |
40 | -define(tab, 16#09). | |
41 | -define(cr, 16#0D). | |
42 | -define(newline, 16#0A). | |
43 | ||
44 | %% object delimiters | |
45 | -define(start_object, 16#7B). | |
46 | -define(end_object, 16#7D). | |
47 | ||
48 | %% array delimiters | |
49 | -define(start_array, 16#5B). | |
50 | -define(end_array, 16#5D). | |
51 | ||
52 | %% kv seperator | |
53 | -define(comma, 16#2C). | |
54 | -define(doublequote, 16#22). | |
55 | -define(singlequote, 16#27). | |
56 | -define(colon, 16#3A). | |
57 | ||
58 | %% string escape sequences | |
59 | -define(rsolidus, 16#5C). | |
60 | -define(solidus, 16#2F). | |
61 | ||
62 | %% math | |
63 | -define(zero, 16#30). | |
64 | -define(decimalpoint, 16#2E). | |
65 | -define(negative, 16#2D). | |
66 | -define(positive, 16#2B). | |
67 | ||
68 | %% comments | |
69 | -define(star, 16#2A). | |
70 | ||
71 | ||
72 | %% some useful guards | |
73 | -define(is_hex(Symbol), | |
74 | (Symbol >= $a andalso Symbol =< $f) orelse | |
75 | (Symbol >= $A andalso Symbol =< $F) orelse | |
76 | (Symbol >= $0 andalso Symbol =< $9) | |
77 | ). | |
78 | ||
79 | -define(is_nonzero(Symbol), | |
80 | Symbol >= $1 andalso Symbol =< $9 | |
81 | ). | |
82 | ||
83 | -define(is_whitespace(Symbol), | |
84 | Symbol =:= ?space; Symbol =:= ?tab; Symbol =:= ?cr; Symbol =:= ?newline | |
85 | ). | |
86 | ||
87 | ||
88 | %% lists are benchmarked to be faster (tho higher in memory usage) than binaries | |
89 | new_seq() -> []. | |
90 | new_seq(C) -> [C]. | |
91 | ||
92 | acc_seq(Seq, C) when is_list(C) -> lists:reverse(C) ++ Seq; | |
93 | acc_seq(Seq, C) -> [C] ++ Seq. | |
94 | ||
95 | end_seq(Seq) -> unicode:characters_to_binary(lists:reverse(Seq)). | |
96 | ||
97 | end_seq(Seq, _) -> end_seq(Seq). | |
98 | ||
99 | ||
100 | start(<<16#ef, 16#bb, 16#bf, Rest/binary>>, Handler, Stack, Config) -> | |
101 | value(Rest, Handler, Stack, Config); | |
102 | start(Bin, Handler, Stack, Config) -> | |
103 | value(Bin, Handler, Stack, Config). | |
104 | ||
105 | ||
106 | value(<<?doublequote, Rest/binary>>, Handler, Stack, Config) -> | |
107 | string(Rest, Handler, new_seq(), Stack, Config); | |
108 | value(<<$t, Rest/binary>>, Handler, Stack, Config) -> | |
109 | true(Rest, Handler, Stack, Config); | |
110 | value(<<$f, Rest/binary>>, Handler, Stack, Config) -> | |
111 | false(Rest, Handler, Stack, Config); | |
112 | value(<<$n, Rest/binary>>, Handler, Stack, Config) -> | |
113 | null(Rest, Handler, Stack, Config); | |
114 | value(<<?negative, Rest/binary>>, Handler, Stack, Config) -> | |
115 | negative(Rest, Handler, new_seq($-), Stack, Config); | |
116 | value(<<?zero, Rest/binary>>, Handler, Stack, Config) -> | |
117 | zero(Rest, Handler, new_seq($0), Stack, Config); | |
118 | value(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_nonzero(S) -> | |
119 | integer(Rest, Handler, new_seq(S), Stack, Config); | |
120 | value(<<?start_object, Rest/binary>>, Handler, Stack, Config) -> | |
121 | object(Rest, handle_event(start_object, Handler, Config), [key|Stack], Config); | |
122 | value(<<?start_array, Rest/binary>>, Handler, Stack, Config) -> | |
123 | array(Rest, handle_event(start_array, Handler, Config), [array|Stack], Config); | |
124 | value(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) -> | |
125 | value(Rest, Handler, Stack, Config); | |
126 | value(_Bin, _Handler, _Stack, _Config) -> | |
127 | erlang:error(badarg). | |
128 | ||
129 | ||
130 | object(<<?doublequote, Rest/binary>>, Handler, Stack, Config) -> | |
131 | string(Rest, Handler, new_seq(), Stack, Config); | |
132 | object(<<?end_object, Rest/binary>>, Handler, [key|Stack], Config) -> | |
133 | maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config); | |
134 | object(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) -> | |
135 | object(Rest, Handler, Stack, Config); | |
136 | object(_Bin, _Handler, _Stack, _Config) -> | |
137 | erlang:error(badarg). | |
138 | ||
139 | ||
140 | array(<<?end_array, Rest/binary>>, Handler, [array|Stack], Config) -> | |
141 | maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config); | |
142 | array(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) -> | |
143 | array(Rest, Handler, Stack, Config); | |
144 | array(Bin, Handler, Stack, Config) -> | |
145 | value(Bin, Handler, Stack, Config). | |
146 | ||
147 | ||
148 | colon(<<?colon, Rest/binary>>, Handler, [key|Stack], Config) -> | |
149 | value(Rest, Handler, [object|Stack], Config); | |
150 | colon(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) -> | |
151 | colon(Rest, Handler, Stack, Config); | |
152 | colon(_Bin, _Handler, _Stack, _Config) -> | |
153 | erlang:error(badarg). | |
154 | ||
155 | ||
156 | key(<<?doublequote, Rest/binary>>, Handler, Stack, Config) -> | |
157 | string(Rest, Handler, new_seq(), Stack, Config); | |
158 | key(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) -> | |
159 | key(Rest, Handler, Stack, Config); | |
160 | key(_Bin, _Handler, _Stack, _Config) -> | |
161 | erlang:error(badarg). | |
162 | ||
163 | ||
164 | %% note that if you encounter an error from string and you can't find the clause that | |
165 | %% caused it here, it might be in unescape below | |
166 | string(<<?doublequote, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
167 | doublequote(Rest, Handler, Acc, Stack, Config); | |
168 | string(<<?solidus, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
169 | string(Rest, Handler, acc_seq(Acc, ?solidus), Stack, Config); | |
170 | string(<<?rsolidus/utf8, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
171 | unescape(Rest, Handler, Acc, Stack, Config); | |
172 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#20, X < 16#2028 -> | |
173 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
174 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X == 16#2028; X == 16#2029 -> | |
175 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
176 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X > 16#2029, X < 16#d800 -> | |
177 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
178 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X > 16#dfff, X < 16#fdd0 -> | |
179 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
180 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X > 16#fdef, X < 16#fffe -> | |
181 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
182 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#10000, X < 16#1fffe -> | |
183 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
184 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#20000, X < 16#2fffe -> | |
185 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
186 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#30000, X < 16#3fffe -> | |
187 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
188 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#40000, X < 16#4fffe -> | |
189 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
190 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#50000, X < 16#5fffe -> | |
191 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
192 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#60000, X < 16#6fffe -> | |
193 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
194 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#70000, X < 16#7fffe -> | |
195 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
196 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#80000, X < 16#8fffe -> | |
197 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
198 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#90000, X < 16#9fffe -> | |
199 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
200 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#a0000, X < 16#afffe -> | |
201 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
202 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#b0000, X < 16#bfffe -> | |
203 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
204 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#c0000, X < 16#cfffe -> | |
205 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
206 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#d0000, X < 16#dfffe -> | |
207 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
208 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#e0000, X < 16#efffe -> | |
209 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
210 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#f0000, X < 16#ffffe -> | |
211 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
212 | string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#100000, X < 16#10fffe -> | |
213 | string(Rest, Handler, acc_seq(Acc, X), Stack, Config); | |
214 | %% surrogates | |
215 | string(<<237, X, _, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) | |
216 | when X >= 160 -> | |
217 | string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); | |
218 | %% u+xfffe, u+xffff, control codes and other noncharacters | |
219 | string(<<_/utf8, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) -> | |
220 | string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); | |
221 | %% u+fffe and u+ffff for R14BXX (subsequent runtimes will happily match the | |
222 | %% preceding clause | |
223 | string(<<239, 191, X, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) | |
224 | when X == 190; X == 191 -> | |
225 | string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); | |
226 | %% overlong encodings and missing continuations of a 2 byte sequence | |
227 | string(<<X, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) | |
228 | when X >= 192, X =< 223 -> | |
229 | strip_continuations(Rest, Handler, Acc, Stack, Config, 1); | |
230 | %% overlong encodings and missing continuations of a 3 byte sequence | |
231 | string(<<X, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) | |
232 | when X >= 224, X =< 239 -> | |
233 | strip_continuations(Rest, Handler, Acc, Stack, Config, 2); | |
234 | %% overlong encodings and missing continuations of a 4 byte sequence | |
235 | string(<<X, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) | |
236 | when X >= 240, X =< 247 -> | |
237 | strip_continuations(Rest, Handler, Acc, Stack, Config, 3); | |
238 | %% incompletes and unexpected bytes, including orphan continuations | |
239 | string(<<_, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) -> | |
240 | string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); | |
241 | string(_Bin, _Handler, _Acc, _Stack, _Config) -> | |
242 | erlang:error(badarg). | |
243 | ||
244 | ||
245 | doublequote(Rest, Handler, Acc, [key|_] = Stack, Config) -> | |
246 | colon(Rest, handle_event({key, end_seq(Acc, Config)}, Handler, Config), Stack, Config); | |
247 | doublequote(Rest, Handler, Acc, Stack, Config) -> | |
248 | maybe_done(Rest, handle_event({string, end_seq(Acc, Config)}, Handler, Config), Stack, Config). | |
249 | ||
250 | ||
251 | %% strips continuation bytes after bad utf bytes, guards against both too short | |
252 | %% and overlong sequences. N is the maximum number of bytes to strip | |
253 | strip_continuations(<<Rest/binary>>, Handler, Acc, Stack, Config, 0) -> | |
254 | string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); | |
255 | strip_continuations(<<X, Rest/binary>>, Handler, Acc, Stack, Config, N) when X >= 128, X =< 191 -> | |
256 | strip_continuations(Rest, Handler, Acc, Stack, Config, N - 1); | |
257 | %% not a continuation byte, insert a replacement character for sequence thus | |
258 | %% far and dispatch back to string | |
259 | strip_continuations(<<Rest/binary>>, Handler, Acc, Stack, Config, _) -> | |
260 | string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config). | |
261 | ||
262 | ||
263 | %% this all gets really gross and should probably eventually be folded into | |
264 | %% but for now it fakes being part of string on incompletes and errors | |
265 | unescape(<<$b, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
266 | string(Rest, Handler, acc_seq(Acc, $\b), Stack, Config); | |
267 | unescape(<<$f, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
268 | string(Rest, Handler, acc_seq(Acc, $\f), Stack, Config); | |
269 | unescape(<<$n, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
270 | string(Rest, Handler, acc_seq(Acc, $\n), Stack, Config); | |
271 | unescape(<<$r, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
272 | string(Rest, Handler, acc_seq(Acc, $\r), Stack, Config); | |
273 | unescape(<<$t, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
274 | string(Rest, Handler, acc_seq(Acc, $\t), Stack, Config); | |
275 | unescape(<<?doublequote, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
276 | string(Rest, Handler, acc_seq(Acc, $\"), Stack, Config); | |
277 | unescape(<<?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
278 | string(Rest, Handler, acc_seq(Acc, $\\), Stack, Config); | |
279 | unescape(<<?solidus, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
280 | string(Rest, Handler, acc_seq(Acc, $/), Stack, Config); | |
281 | unescape(<<$u, $d, A, B, C, ?rsolidus, $u, $d, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config) | |
282 | when (A == $8 orelse A == $9 orelse A == $a orelse A == $b), | |
283 | (X == $c orelse X == $d orelse X == $e orelse X == $f), | |
284 | ?is_hex(B), ?is_hex(C), ?is_hex(Y), ?is_hex(Z) | |
285 | -> | |
286 | High = erlang:list_to_integer([$d, A, B, C], 16), | |
287 | Low = erlang:list_to_integer([$d, X, Y, Z], 16), | |
288 | Codepoint = (High - 16#d800) * 16#400 + (Low - 16#dc00) + 16#10000, | |
289 | string(Rest, Handler, acc_seq(Acc, Codepoint), Stack, Config); | |
290 | unescape(<<$u, $d, A, B, C, ?rsolidus, $u, W, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config) | |
291 | when (A == $8 orelse A == $9 orelse A == $a orelse A == $b), | |
292 | ?is_hex(B), ?is_hex(C), ?is_hex(W), ?is_hex(X), ?is_hex(Y), ?is_hex(Z) | |
293 | -> | |
294 | string(Rest, Handler, acc_seq(Acc, [16#fffd, 16#fffd]), Stack, Config); | |
295 | unescape(<<$u, A, B, C, D, Rest/binary>>, Handler, Acc, Stack, Config) | |
296 | when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D) -> | |
297 | case erlang:list_to_integer([A, B, C, D], 16) of | |
298 | Codepoint when Codepoint < 16#d800; Codepoint > 16#dfff -> | |
299 | string(Rest, Handler, acc_seq(Acc, Codepoint), Stack, Config); | |
300 | _ -> | |
301 | string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config) | |
302 | end; | |
303 | unescape(_Bin, _Handler, _Acc, _Stack, _Config) -> | |
304 | erlang:error(badarg). | |
305 | ||
306 | ||
307 | %% like in strings, there's some pseudo states in here that will never | |
308 | %% show up in errors or incompletes. some show up in value, some show | |
309 | %% up in integer, decimal or exp | |
310 | negative(<<$0, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
311 | zero(Rest, Handler, acc_seq(Acc, $0), Stack, Config); | |
312 | negative(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when ?is_nonzero(S) -> | |
313 | integer(Rest, Handler, acc_seq(Acc, S), Stack, Config); | |
314 | negative(_Bin, _Handler, _Acc, _Stack, _Config) -> | |
315 | erlang:error(badarg). | |
316 | ||
317 | ||
318 | zero(<<?decimalpoint, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
319 | decimal(Rest, Handler, acc_seq(Acc, ?decimalpoint), Stack, Config); | |
320 | zero(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E -> | |
321 | e(Rest, Handler, acc_seq(Acc, ".0e"), Stack, Config); | |
322 | zero(Bin, Handler, Acc, Stack, Config) -> | |
323 | finish_number(Bin, Handler, {zero, Acc}, Stack, Config). | |
324 | ||
325 | ||
326 | integer(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> | |
327 | integer(Rest, Handler, acc_seq(Acc, S), Stack, Config); | |
328 | integer(<<?decimalpoint, Rest/binary>>, Handler, Acc, Stack, Config) -> | |
329 | initialdecimal(Rest, Handler, acc_seq(Acc, ?decimalpoint), Stack, Config); | |
330 | integer(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E -> | |
331 | e(Rest, Handler, acc_seq(Acc, ".0e"), Stack, Config); | |
332 | integer(Bin, Handler, Acc, Stack, Config) -> | |
333 | finish_number(Bin, Handler, {integer, Acc}, Stack, Config). | |
334 | ||
335 | ||
336 | initialdecimal(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> | |
337 | decimal(Rest, Handler, acc_seq(Acc, S), Stack, Config); | |
338 | initialdecimal(_Bin, _Handler, _Acc, _Stack, _Config) -> | |
339 | erlang:error(badarg). | |
340 | ||
341 | ||
342 | decimal(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> | |
343 | decimal(Rest, Handler, acc_seq(Acc, S), Stack, Config); | |
344 | decimal(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E -> | |
345 | e(Rest, Handler, acc_seq(Acc, $e), Stack, Config); | |
346 | decimal(Bin, Handler, Acc, Stack, Config) -> | |
347 | finish_number(Bin, Handler, {decimal, Acc}, Stack, Config). | |
348 | ||
349 | ||
350 | e(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> | |
351 | exp(Rest, Handler, acc_seq(Acc, S), Stack, Config); | |
352 | e(<<Sign, Rest/binary>>, Handler, Acc, Stack, Config) when Sign =:= ?positive; Sign =:= ?negative -> | |
353 | ex(Rest, Handler, acc_seq(Acc, Sign), Stack, Config); | |
354 | e(_Bin, _Handler, _Acc, _Stack, _Config) -> | |
355 | erlang:error(badarg). | |
356 | ||
357 | ||
358 | ex(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> | |
359 | exp(Rest, Handler, acc_seq(Acc, S), Stack, Config); | |
360 | ex(_Bin, _Handler, _Acc, _Stack, _Config) -> | |
361 | erlang:error(badarg). | |
362 | ||
363 | ||
364 | exp(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> | |
365 | exp(Rest, Handler, acc_seq(Acc, S), Stack, Config); | |
366 | exp(Bin, Handler, Acc, Stack, Config) -> | |
367 | finish_number(Bin, Handler, {exp, Acc}, Stack, Config). | |
368 | ||
369 | ||
370 | finish_number(Rest, Handler, Acc, [], Config) -> | |
371 | maybe_done(Rest, handle_event(format_number(Acc), Handler, Config), [], Config); | |
372 | finish_number(Rest, Handler, Acc, Stack, Config) -> | |
373 | maybe_done(Rest, handle_event(format_number(Acc), Handler, Config), Stack, Config). | |
374 | ||
375 | ||
376 | format_number({zero, Acc}) -> {integer, list_to_integer(lists:reverse(Acc))}; | |
377 | format_number({integer, Acc}) -> {integer, list_to_integer(lists:reverse(Acc))}; | |
378 | format_number({decimal, Acc}) -> {float, list_to_float(lists:reverse(Acc))}; | |
379 | format_number({exp, Acc}) -> {float, list_to_float(lists:reverse(Acc))}. | |
380 | ||
381 | ||
382 | true(<<$r, $u, $e, Rest/binary>>, Handler, Stack, Config) -> | |
383 | maybe_done(Rest, handle_event({literal, true}, Handler, Config), Stack, Config); | |
384 | true(_Bin, _Handler, _Stack, _Config) -> | |
385 | erlang:error(badarg). | |
386 | ||
387 | ||
388 | false(<<$a, $l, $s, $e, Rest/binary>>, Handler, Stack, Config) -> | |
389 | maybe_done(Rest, handle_event({literal, false}, Handler, Config), Stack, Config); | |
390 | false(_Bin, _Handler, _Stack, _Config) -> | |
391 | erlang:error(badarg). | |
392 | ||
393 | ||
394 | null(<<$u, $l, $l, Rest/binary>>, Handler, Stack, Config) -> | |
395 | maybe_done(Rest, handle_event({literal, null}, Handler, Config), Stack, Config); | |
396 | null(_Bin, _Handler, _Stack, _Config) -> | |
397 | erlang:error(badarg). | |
398 | ||
399 | ||
400 | maybe_done(<<Rest/binary>>, Handler, [], Config) -> | |
401 | done(Rest, handle_event(end_json, Handler, Config), [], Config); | |
402 | maybe_done(<<?end_object, Rest/binary>>, Handler, [object|Stack], Config) -> | |
403 | maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config); | |
404 | maybe_done(<<?end_array, Rest/binary>>, Handler, [array|Stack], Config) -> | |
405 | maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config); | |
406 | maybe_done(<<?comma, Rest/binary>>, Handler, [object|Stack], Config) -> | |
407 | key(Rest, Handler, [key|Stack], Config); | |
408 | maybe_done(<<?comma, Rest/binary>>, Handler, [array|_] = Stack, Config) -> | |
409 | value(Rest, Handler, Stack, Config); | |
410 | maybe_done(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) -> | |
411 | maybe_done(Rest, Handler, Stack, Config); | |
412 | maybe_done(_Bin, _Handler, _Stack, _Config) -> | |
413 | erlang:error(badarg). | |
414 | ||
415 | ||
416 | done(<<S, Rest/binary>>, Handler, [], Config) when ?is_whitespace(S) -> | |
417 | done(Rest, Handler, [], Config); | |
418 | done(<<>>, {_Handler, State}, [], _Config) -> State; | |
419 | done(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). |