blob: 18e0c0377dd8179c615c5c5e8516b7324affc099 [file] [log] [blame]
alisdair sullivancb3f3f32014-07-14 21:50:43 -07001%% 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
alisdair sullivancb3f3f32014-07-14 21:50:43 -070025-record(config, {strict_utf8 = false :: boolean()}).
26
alisdair sullivancb3f3f32014-07-14 21:50:43 -070027parser() -> fun(JSON) -> start(JSON, {?MODULE, []}, [], #config{}) end.
28
alisdair sullivancb3f3f32014-07-14 21:50:43 -070029handle_event(Event, {Handler, State}, _Config) -> {Handler, Handler:handle_event(Event, State)}.
30
31handle_event(end_json, State) -> lists:reverse([end_json] ++ State);
32handle_event(Event, State) -> [Event] ++ State.
33
alisdair sullivancb3f3f32014-07-14 21:50:43 -070034%% whitespace
35-define(space, 16#20).
36-define(tab, 16#09).
37-define(cr, 16#0D).
38-define(newline, 16#0A).
39
40%% object delimiters
41-define(start_object, 16#7B).
42-define(end_object, 16#7D).
43
44%% array delimiters
45-define(start_array, 16#5B).
46-define(end_array, 16#5D).
47
48%% kv seperator
49-define(comma, 16#2C).
50-define(doublequote, 16#22).
51-define(singlequote, 16#27).
52-define(colon, 16#3A).
53
54%% string escape sequences
55-define(rsolidus, 16#5C).
56-define(solidus, 16#2F).
57
58%% math
59-define(zero, 16#30).
60-define(decimalpoint, 16#2E).
61-define(negative, 16#2D).
62-define(positive, 16#2B).
63
64%% comments
65-define(star, 16#2A).
66
alisdair sullivancb3f3f32014-07-14 21:50:43 -070067%% some useful guards
68-define(is_hex(Symbol),
69 (Symbol >= $a andalso Symbol =< $f) orelse
Sergei Elin45764092022-09-23 23:21:31 +030070 (Symbol >= $A andalso Symbol =< $F) orelse
71 (Symbol >= $0 andalso Symbol =< $9)
alisdair sullivancb3f3f32014-07-14 21:50:43 -070072).
73
74-define(is_nonzero(Symbol),
75 Symbol >= $1 andalso Symbol =< $9
76).
77
78-define(is_whitespace(Symbol),
79 Symbol =:= ?space; Symbol =:= ?tab; Symbol =:= ?cr; Symbol =:= ?newline
80).
81
alisdair sullivancb3f3f32014-07-14 21:50:43 -070082%% lists are benchmarked to be faster (tho higher in memory usage) than binaries
83new_seq() -> [].
84new_seq(C) -> [C].
85
86acc_seq(Seq, C) when is_list(C) -> lists:reverse(C) ++ Seq;
87acc_seq(Seq, C) -> [C] ++ Seq.
88
89end_seq(Seq) -> unicode:characters_to_binary(lists:reverse(Seq)).
90
91end_seq(Seq, _) -> end_seq(Seq).
92
alisdair sullivancb3f3f32014-07-14 21:50:43 -070093start(<<16#ef, 16#bb, 16#bf, Rest/binary>>, Handler, Stack, Config) ->
94 value(Rest, Handler, Stack, Config);
95start(Bin, Handler, Stack, Config) ->
96 value(Bin, Handler, Stack, Config).
97
alisdair sullivancb3f3f32014-07-14 21:50:43 -070098value(<<?doublequote, Rest/binary>>, Handler, Stack, Config) ->
99 string(Rest, Handler, new_seq(), Stack, Config);
100value(<<$t, Rest/binary>>, Handler, Stack, Config) ->
101 true(Rest, Handler, Stack, Config);
102value(<<$f, Rest/binary>>, Handler, Stack, Config) ->
103 false(Rest, Handler, Stack, Config);
104value(<<$n, Rest/binary>>, Handler, Stack, Config) ->
105 null(Rest, Handler, Stack, Config);
106value(<<?negative, Rest/binary>>, Handler, Stack, Config) ->
107 negative(Rest, Handler, new_seq($-), Stack, Config);
108value(<<?zero, Rest/binary>>, Handler, Stack, Config) ->
109 zero(Rest, Handler, new_seq($0), Stack, Config);
110value(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_nonzero(S) ->
111 integer(Rest, Handler, new_seq(S), Stack, Config);
112value(<<?start_object, Rest/binary>>, Handler, Stack, Config) ->
Sergei Elin45764092022-09-23 23:21:31 +0300113 object(Rest, handle_event(start_object, Handler, Config), [key | Stack], Config);
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700114value(<<?start_array, Rest/binary>>, Handler, Stack, Config) ->
Sergei Elin45764092022-09-23 23:21:31 +0300115 array(Rest, handle_event(start_array, Handler, Config), [array | Stack], Config);
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700116value(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
117 value(Rest, Handler, Stack, Config);
118value(_Bin, _Handler, _Stack, _Config) ->
119 erlang:error(badarg).
120
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700121object(<<?doublequote, Rest/binary>>, Handler, Stack, Config) ->
122 string(Rest, Handler, new_seq(), Stack, Config);
Sergei Elin45764092022-09-23 23:21:31 +0300123object(<<?end_object, Rest/binary>>, Handler, [key | Stack], Config) ->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700124 maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config);
125object(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
126 object(Rest, Handler, Stack, Config);
127object(_Bin, _Handler, _Stack, _Config) ->
128 erlang:error(badarg).
129
Sergei Elin45764092022-09-23 23:21:31 +0300130array(<<?end_array, Rest/binary>>, Handler, [array | Stack], Config) ->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700131 maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config);
132array(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
133 array(Rest, Handler, Stack, Config);
134array(Bin, Handler, Stack, Config) ->
135 value(Bin, Handler, Stack, Config).
136
Sergei Elin45764092022-09-23 23:21:31 +0300137colon(<<?colon, Rest/binary>>, Handler, [key | Stack], Config) ->
138 value(Rest, Handler, [object | Stack], Config);
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700139colon(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
140 colon(Rest, Handler, Stack, Config);
141colon(_Bin, _Handler, _Stack, _Config) ->
142 erlang:error(badarg).
143
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700144key(<<?doublequote, Rest/binary>>, Handler, Stack, Config) ->
145 string(Rest, Handler, new_seq(), Stack, Config);
146key(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
147 key(Rest, Handler, Stack, Config);
148key(_Bin, _Handler, _Stack, _Config) ->
149 erlang:error(badarg).
150
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700151%% note that if you encounter an error from string and you can't find the clause that
152%% caused it here, it might be in unescape below
153string(<<?doublequote, Rest/binary>>, Handler, Acc, Stack, Config) ->
154 doublequote(Rest, Handler, Acc, Stack, Config);
155string(<<?solidus, Rest/binary>>, Handler, Acc, Stack, Config) ->
156 string(Rest, Handler, acc_seq(Acc, ?solidus), Stack, Config);
157string(<<?rsolidus/utf8, Rest/binary>>, Handler, Acc, Stack, Config) ->
158 unescape(Rest, Handler, Acc, Stack, Config);
159string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#20, X < 16#2028 ->
160 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
161string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X == 16#2028; X == 16#2029 ->
162 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
163string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X > 16#2029, X < 16#d800 ->
164 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
165string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X > 16#dfff, X < 16#fdd0 ->
166 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
167string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X > 16#fdef, X < 16#fffe ->
168 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
169string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#10000, X < 16#1fffe ->
170 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
171string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#20000, X < 16#2fffe ->
172 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
173string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#30000, X < 16#3fffe ->
174 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
175string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#40000, X < 16#4fffe ->
176 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
177string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#50000, X < 16#5fffe ->
178 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
179string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#60000, X < 16#6fffe ->
180 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
181string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#70000, X < 16#7fffe ->
182 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
183string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#80000, X < 16#8fffe ->
184 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
185string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#90000, X < 16#9fffe ->
186 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
187string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#a0000, X < 16#afffe ->
188 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
189string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#b0000, X < 16#bfffe ->
190 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
191string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#c0000, X < 16#cfffe ->
192 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
193string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#d0000, X < 16#dfffe ->
194 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
195string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#e0000, X < 16#efffe ->
196 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
197string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#f0000, X < 16#ffffe ->
198 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
199string(<<X/utf8, Rest/binary>>, Handler, Acc, Stack, Config) when X >= 16#100000, X < 16#10fffe ->
200 string(Rest, Handler, acc_seq(Acc, X), Stack, Config);
201%% surrogates
Sergei Elin45764092022-09-23 23:21:31 +0300202string(<<237, X, _, Rest/binary>>, Handler, Acc, Stack, Config = #config{strict_utf8 = false}) when
203 X >= 160
204->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700205 string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config);
206%% u+xfffe, u+xffff, control codes and other noncharacters
Sergei Elin45764092022-09-23 23:21:31 +0300207string(<<_/utf8, Rest/binary>>, Handler, Acc, Stack, Config = #config{strict_utf8 = false}) ->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700208 string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config);
209%% u+fffe and u+ffff for R14BXX (subsequent runtimes will happily match the
Konrad Grochowski3b5dacb2014-11-24 10:55:31 +0100210%% preceding clause
Sergei Elin45764092022-09-23 23:21:31 +0300211string(
212 <<239, 191, X, Rest/binary>>, Handler, Acc, Stack, Config = #config{strict_utf8 = false}
213) when
214 X == 190; X == 191
215->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700216 string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config);
217%% overlong encodings and missing continuations of a 2 byte sequence
Sergei Elin45764092022-09-23 23:21:31 +0300218string(<<X, Rest/binary>>, Handler, Acc, Stack, Config = #config{strict_utf8 = false}) when
219 X >= 192, X =< 223
220->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700221 strip_continuations(Rest, Handler, Acc, Stack, Config, 1);
222%% overlong encodings and missing continuations of a 3 byte sequence
Sergei Elin45764092022-09-23 23:21:31 +0300223string(<<X, Rest/binary>>, Handler, Acc, Stack, Config = #config{strict_utf8 = false}) when
224 X >= 224, X =< 239
225->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700226 strip_continuations(Rest, Handler, Acc, Stack, Config, 2);
227%% overlong encodings and missing continuations of a 4 byte sequence
Sergei Elin45764092022-09-23 23:21:31 +0300228string(<<X, Rest/binary>>, Handler, Acc, Stack, Config = #config{strict_utf8 = false}) when
229 X >= 240, X =< 247
230->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700231 strip_continuations(Rest, Handler, Acc, Stack, Config, 3);
232%% incompletes and unexpected bytes, including orphan continuations
Sergei Elin45764092022-09-23 23:21:31 +0300233string(<<_, Rest/binary>>, Handler, Acc, Stack, Config = #config{strict_utf8 = false}) ->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700234 string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config);
235string(_Bin, _Handler, _Acc, _Stack, _Config) ->
Sergei Elin45764092022-09-23 23:21:31 +0300236 erlang:error(badarg).
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700237
Sergei Elin45764092022-09-23 23:21:31 +0300238doublequote(Rest, Handler, Acc, [key | _] = Stack, Config) ->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700239 colon(Rest, handle_event({key, end_seq(Acc, Config)}, Handler, Config), Stack, Config);
240doublequote(Rest, Handler, Acc, Stack, Config) ->
241 maybe_done(Rest, handle_event({string, end_seq(Acc, Config)}, Handler, Config), Stack, Config).
242
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700243%% strips continuation bytes after bad utf bytes, guards against both too short
244%% and overlong sequences. N is the maximum number of bytes to strip
245strip_continuations(<<Rest/binary>>, Handler, Acc, Stack, Config, 0) ->
246 string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config);
247strip_continuations(<<X, Rest/binary>>, Handler, Acc, Stack, Config, N) when X >= 128, X =< 191 ->
248 strip_continuations(Rest, Handler, Acc, Stack, Config, N - 1);
249%% not a continuation byte, insert a replacement character for sequence thus
250%% far and dispatch back to string
251strip_continuations(<<Rest/binary>>, Handler, Acc, Stack, Config, _) ->
252 string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config).
253
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700254%% this all gets really gross and should probably eventually be folded into
255%% but for now it fakes being part of string on incompletes and errors
256unescape(<<$b, Rest/binary>>, Handler, Acc, Stack, Config) ->
257 string(Rest, Handler, acc_seq(Acc, $\b), Stack, Config);
258unescape(<<$f, Rest/binary>>, Handler, Acc, Stack, Config) ->
259 string(Rest, Handler, acc_seq(Acc, $\f), Stack, Config);
260unescape(<<$n, Rest/binary>>, Handler, Acc, Stack, Config) ->
261 string(Rest, Handler, acc_seq(Acc, $\n), Stack, Config);
262unescape(<<$r, Rest/binary>>, Handler, Acc, Stack, Config) ->
263 string(Rest, Handler, acc_seq(Acc, $\r), Stack, Config);
264unescape(<<$t, Rest/binary>>, Handler, Acc, Stack, Config) ->
265 string(Rest, Handler, acc_seq(Acc, $\t), Stack, Config);
266unescape(<<?doublequote, Rest/binary>>, Handler, Acc, Stack, Config) ->
267 string(Rest, Handler, acc_seq(Acc, $\"), Stack, Config);
268unescape(<<?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config) ->
269 string(Rest, Handler, acc_seq(Acc, $\\), Stack, Config);
270unescape(<<?solidus, Rest/binary>>, Handler, Acc, Stack, Config) ->
271 string(Rest, Handler, acc_seq(Acc, $/), Stack, Config);
Sergei Elin45764092022-09-23 23:21:31 +0300272unescape(
273 <<$u, $d, A, B, C, ?rsolidus, $u, $d, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config
274) when
275 (A == $8 orelse A == $9 orelse A == $a orelse A == $b),
276 (X == $c orelse X == $d orelse X == $e orelse X == $f),
277 ?is_hex(B),
278 ?is_hex(C),
279 ?is_hex(Y),
280 ?is_hex(Z)
281->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700282 High = erlang:list_to_integer([$d, A, B, C], 16),
283 Low = erlang:list_to_integer([$d, X, Y, Z], 16),
284 Codepoint = (High - 16#d800) * 16#400 + (Low - 16#dc00) + 16#10000,
285 string(Rest, Handler, acc_seq(Acc, Codepoint), Stack, Config);
Sergei Elin45764092022-09-23 23:21:31 +0300286unescape(
287 <<$u, $d, A, B, C, ?rsolidus, $u, W, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config
288) when
289 (A == $8 orelse A == $9 orelse A == $a orelse A == $b),
290 ?is_hex(B),
291 ?is_hex(C),
292 ?is_hex(W),
293 ?is_hex(X),
294 ?is_hex(Y),
295 ?is_hex(Z)
296->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700297 string(Rest, Handler, acc_seq(Acc, [16#fffd, 16#fffd]), Stack, Config);
Sergei Elin45764092022-09-23 23:21:31 +0300298unescape(<<$u, A, B, C, D, Rest/binary>>, Handler, Acc, Stack, Config) when
299 ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D)
300->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700301 case erlang:list_to_integer([A, B, C, D], 16) of
302 Codepoint when Codepoint < 16#d800; Codepoint > 16#dfff ->
303 string(Rest, Handler, acc_seq(Acc, Codepoint), Stack, Config);
304 _ ->
305 string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config)
306 end;
307unescape(_Bin, _Handler, _Acc, _Stack, _Config) ->
308 erlang:error(badarg).
309
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700310%% like in strings, there's some pseudo states in here that will never
311%% show up in errors or incompletes. some show up in value, some show
312%% up in integer, decimal or exp
313negative(<<$0, Rest/binary>>, Handler, Acc, Stack, Config) ->
314 zero(Rest, Handler, acc_seq(Acc, $0), Stack, Config);
315negative(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when ?is_nonzero(S) ->
316 integer(Rest, Handler, acc_seq(Acc, S), Stack, Config);
317negative(_Bin, _Handler, _Acc, _Stack, _Config) ->
318 erlang:error(badarg).
319
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700320zero(<<?decimalpoint, Rest/binary>>, Handler, Acc, Stack, Config) ->
321 decimal(Rest, Handler, acc_seq(Acc, ?decimalpoint), Stack, Config);
322zero(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E ->
323 e(Rest, Handler, acc_seq(Acc, ".0e"), Stack, Config);
324zero(Bin, Handler, Acc, Stack, Config) ->
325 finish_number(Bin, Handler, {zero, Acc}, Stack, Config).
326
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700327integer(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) ->
328 integer(Rest, Handler, acc_seq(Acc, S), Stack, Config);
329integer(<<?decimalpoint, Rest/binary>>, Handler, Acc, Stack, Config) ->
330 initialdecimal(Rest, Handler, acc_seq(Acc, ?decimalpoint), Stack, Config);
331integer(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E ->
332 e(Rest, Handler, acc_seq(Acc, ".0e"), Stack, Config);
333integer(Bin, Handler, Acc, Stack, Config) ->
334 finish_number(Bin, Handler, {integer, Acc}, Stack, Config).
335
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700336initialdecimal(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) ->
337 decimal(Rest, Handler, acc_seq(Acc, S), Stack, Config);
338initialdecimal(_Bin, _Handler, _Acc, _Stack, _Config) ->
339 erlang:error(badarg).
340
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700341decimal(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) ->
342 decimal(Rest, Handler, acc_seq(Acc, S), Stack, Config);
343decimal(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E ->
344 e(Rest, Handler, acc_seq(Acc, $e), Stack, Config);
345decimal(Bin, Handler, Acc, Stack, Config) ->
346 finish_number(Bin, Handler, {decimal, Acc}, Stack, Config).
347
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700348e(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) ->
349 exp(Rest, Handler, acc_seq(Acc, S), Stack, Config);
350e(<<Sign, Rest/binary>>, Handler, Acc, Stack, Config) when Sign =:= ?positive; Sign =:= ?negative ->
351 ex(Rest, Handler, acc_seq(Acc, Sign), Stack, Config);
352e(_Bin, _Handler, _Acc, _Stack, _Config) ->
353 erlang:error(badarg).
354
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700355ex(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) ->
356 exp(Rest, Handler, acc_seq(Acc, S), Stack, Config);
357ex(_Bin, _Handler, _Acc, _Stack, _Config) ->
358 erlang:error(badarg).
359
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700360exp(<<S, Rest/binary>>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) ->
361 exp(Rest, Handler, acc_seq(Acc, S), Stack, Config);
362exp(Bin, Handler, Acc, Stack, Config) ->
363 finish_number(Bin, Handler, {exp, Acc}, Stack, Config).
364
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700365finish_number(Rest, Handler, Acc, [], Config) ->
366 maybe_done(Rest, handle_event(format_number(Acc), Handler, Config), [], Config);
367finish_number(Rest, Handler, Acc, Stack, Config) ->
368 maybe_done(Rest, handle_event(format_number(Acc), Handler, Config), Stack, Config).
369
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700370format_number({zero, Acc}) -> {integer, list_to_integer(lists:reverse(Acc))};
371format_number({integer, Acc}) -> {integer, list_to_integer(lists:reverse(Acc))};
372format_number({decimal, Acc}) -> {float, list_to_float(lists:reverse(Acc))};
373format_number({exp, Acc}) -> {float, list_to_float(lists:reverse(Acc))}.
374
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700375true(<<$r, $u, $e, Rest/binary>>, Handler, Stack, Config) ->
376 maybe_done(Rest, handle_event({literal, true}, Handler, Config), Stack, Config);
377true(_Bin, _Handler, _Stack, _Config) ->
378 erlang:error(badarg).
379
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700380false(<<$a, $l, $s, $e, Rest/binary>>, Handler, Stack, Config) ->
381 maybe_done(Rest, handle_event({literal, false}, Handler, Config), Stack, Config);
382false(_Bin, _Handler, _Stack, _Config) ->
383 erlang:error(badarg).
384
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700385null(<<$u, $l, $l, Rest/binary>>, Handler, Stack, Config) ->
386 maybe_done(Rest, handle_event({literal, null}, Handler, Config), Stack, Config);
387null(_Bin, _Handler, _Stack, _Config) ->
388 erlang:error(badarg).
389
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700390maybe_done(<<Rest/binary>>, Handler, [], Config) ->
391 done(Rest, handle_event(end_json, Handler, Config), [], Config);
Sergei Elin45764092022-09-23 23:21:31 +0300392maybe_done(<<?end_object, Rest/binary>>, Handler, [object | Stack], Config) ->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700393 maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config);
Sergei Elin45764092022-09-23 23:21:31 +0300394maybe_done(<<?end_array, Rest/binary>>, Handler, [array | Stack], Config) ->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700395 maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config);
Sergei Elin45764092022-09-23 23:21:31 +0300396maybe_done(<<?comma, Rest/binary>>, Handler, [object | Stack], Config) ->
397 key(Rest, Handler, [key | Stack], Config);
398maybe_done(<<?comma, Rest/binary>>, Handler, [array | _] = Stack, Config) ->
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700399 value(Rest, Handler, Stack, Config);
400maybe_done(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
401 maybe_done(Rest, Handler, Stack, Config);
402maybe_done(_Bin, _Handler, _Stack, _Config) ->
403 erlang:error(badarg).
404
alisdair sullivancb3f3f32014-07-14 21:50:43 -0700405done(<<S, Rest/binary>>, Handler, [], Config) when ?is_whitespace(S) ->
406 done(Rest, Handler, [], Config);
Sergei Elin45764092022-09-23 23:21:31 +0300407done(<<>>, {_Handler, State}, [], _Config) ->
408 State;
409done(_Bin, _Handler, _Stack, _Config) ->
410 erlang:error(badarg).