1%% The MIT License 2 3%% Copyright (c) 2010-2013 alisdair sullivan <alisdairsullivan@yahoo.ca> 4 5%% Permission is hereby granted, free of charge, to any person obtaining a copy 6%% of this software and associated documentation files (the "Software"), to deal 7%% in the Software without restriction, including without limitation the rights 8%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9%% copies of the Software, and to permit persons to whom the Software is 10%% furnished to do so, subject to the following conditions: 11 12%% The above copyright notice and this permission notice shall be included in 13%% all copies or substantial portions of the Software. 14 15%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21%% THE SOFTWARE. 22 23 24-module(jsx_decoder). 25 26%% inline handle_event, format_number and maybe_replace 27-compile({inline, [handle_event/3]}). 28-compile({inline, [format_number/1]}). 29-compile({inline, [maybe_replace/2]}). 30-compile({inline, [doublequote/5, singlequote/5]}). 31 32-export([decoder/3, resume/6]). 33 34 35-spec decoder(Handler::module(), State::any(), Config::list()) -> jsx:decoder(). 36 37decoder(Handler, State, Config) -> 38 fun(JSON) -> start(JSON, {Handler, Handler:init(State)}, [], jsx_config:parse_config(Config)) end. 39 40 41%% resume allows continuation from interrupted decoding without having to explicitly export 42%% all states 43-spec resume( 44 Rest::binary(), 45 State::atom(), 46 Handler::{atom(), any()}, 47 Acc::any(), 48 Stack::list(atom()), 49 Config::jsx:config() 50 ) -> jsx:decoder() | {incomplete, jsx:decoder()}. 51 52resume(Rest, State, Handler, Acc, Stack, Config) -> 53 case State of 54 start -> start(Rest, Handler, Stack, Config); 55 value -> value(Rest, Handler, Stack, Config); 56 object -> object(Rest, Handler, Stack, Config); 57 array -> array(Rest, Handler, Stack, Config); 58 colon -> colon(Rest, Handler, Stack, Config); 59 key -> key(Rest, Handler, Stack, Config); 60 string -> string(Rest, Handler, Acc, Stack, Config); 61 number -> number(Rest, Handler, Acc, Stack, Config); 62 true -> true(Rest, Handler, Stack, Config); 63 false -> false(Rest, Handler, Stack, Config); 64 null -> null(Rest, Handler, Stack, Config); 65 comment -> comment(Rest, Handler, Acc, Stack, Config); 66 maybe_done -> maybe_done(Rest, Handler, Stack, Config); 67 done -> done(Rest, Handler, Stack, Config) 68 end. 69 70 71-include("jsx_config.hrl"). 72 73 74%% whitespace 75-define(space, 16#20). 76-define(tab, 16#09). 77-define(cr, 16#0D). 78-define(newline, 16#0A). 79 80%% object delimiters 81-define(start_object, 16#7B). 82-define(end_object, 16#7D). 83 84%% array delimiters 85-define(start_array, 16#5B). 86-define(end_array, 16#5D). 87 88%% kv seperator 89-define(comma, 16#2C). 90-define(doublequote, 16#22). 91-define(singlequote, 16#27). 92-define(colon, 16#3A). 93 94%% string escape sequences 95-define(rsolidus, 16#5C). 96-define(solidus, 16#2F). 97 98%% math 99-define(zero, 16#30). 100-define(decimalpoint, 16#2E). 101-define(negative, 16#2D). 102-define(positive, 16#2B). 103 104%% comments 105-define(star, 16#2A). 106 107 108%% some useful guards 109-define(is_hex(Symbol), 110 (Symbol >= $a andalso Symbol =< $f) orelse 111 (Symbol >= $A andalso Symbol =< $F) orelse 112 (Symbol >= $0 andalso Symbol =< $9) 113). 114 115-define(is_nonzero(Symbol), 116 Symbol >= $1 andalso Symbol =< $9 117). 118 119 120%% error is a macro so the stack trace shows the error site when possible 121-ifndef(error). 122-define(error(State, Bin, Handler, Acc, Stack, Config), 123 case Config#config.error_handler of 124 false -> erlang:error(badarg); 125 F -> F(Bin, {decoder, State, Handler, Acc, Stack}, jsx_config:config_to_list(Config)) 126 end 127). 128-define(error(State, Bin, Handler, Stack, Config), 129 ?error(State, Bin, Handler, null, Stack, Config) 130). 131-endif. 132 133 134incomplete(State, Rest, Handler, Stack, Config = #config{stream=false}) -> 135 ?error(State, Rest, Handler, Stack, Config); 136incomplete(State, Rest, Handler, Stack, Config) -> 137 incomplete(State, Rest, Handler, unused, Stack, Config). 138 139 140incomplete(State, Rest, Handler, Acc, Stack, Config = #config{stream=false}) -> 141 ?error(State, Rest, Handler, Acc, Stack, Config); 142incomplete(State, Rest, Handler, Acc, Stack, Config = #config{incomplete_handler=false}) -> 143 {incomplete, fun(Stream) when is_binary(Stream) -> 144 resume(<<Rest/binary, Stream/binary>>, State, Handler, Acc, Stack, Config); 145 (End) when End == end_stream; End == end_json -> 146 case resume(<<Rest/binary, ?space/utf8>>, State, Handler, Acc, Stack, Config#config{stream=false}) of 147 {incomplete, _} -> ?error(State, Rest, Handler, Acc, Stack, Config); 148 Else -> Else 149 end 150 end 151 }; 152incomplete(State, Rest, Handler, Acc, Stack, Config = #config{incomplete_handler=F}) -> 153 F(Rest, {decoder, State, Handler, Acc, Stack}, jsx_config:config_to_list(Config)). 154 155 156handle_event(Event, {Handler, State}, _Config) -> {Handler, Handler:handle_event(Event, State)}. 157 158 159start(<<16#ef, 16#bb, 16#bf, Rest/binary>>, Handler, Stack, Config) -> 160 value(Rest, Handler, Stack, Config); 161start(<<16#ef, 16#bb>>, Handler, Stack, Config) -> 162 incomplete(start, <<16#ef, 16#bb>>, Handler, Stack, Config); 163start(<<16#ef>>, Handler, Stack, Config) -> 164 incomplete(start, <<16#ef>>, Handler, Stack, Config); 165start(<<>>, Handler, Stack, Config) -> 166 incomplete(start, <<>>, Handler, Stack, Config); 167start(Bin, Handler, Stack, Config) -> 168 value(Bin, Handler, Stack, Config). 169 170 171value(<<?doublequote, Rest/binary>>, Handler, Stack, Config) -> 172 string(Rest, Handler, Stack, Config); 173value(<<?space, Rest/binary>>, Handler, Stack, Config) -> 174 value(Rest, Handler, Stack, Config); 175value(<<?start_object, Rest/binary>>, Handler, Stack, Config) -> 176 object(Rest, handle_event(start_object, Handler, Config), [key|Stack], Config); 177value(<<?start_array, Rest/binary>>, Handler, Stack, Config) -> 178 array(Rest, handle_event(start_array, Handler, Config), [array|Stack], Config); 179value(<<$t, $r, $u, $e, Rest/binary>>, Handler, Stack, Config) -> 180 maybe_done(Rest, handle_event({literal, true}, Handler, Config), Stack, Config); 181value(<<$f, $a, $l, $s, $e, Rest/binary>>, Handler, Stack, Config) -> 182 maybe_done(Rest, handle_event({literal, false}, Handler, Config), Stack, Config); 183value(<<$n, $u, $l, $l, Rest/binary>>, Handler, Stack, Config) -> 184 maybe_done(Rest, handle_event({literal, null}, Handler, Config), Stack, Config); 185value(<<?zero, Rest/binary>>, Handler, Stack, Config) -> 186 number(Rest, Handler, [?zero], [zero|Stack], Config); 187value(<<$1, Rest/binary>>, Handler, Stack, Config) -> 188 number(Rest, Handler, [$1], [integer|Stack], Config); 189value(<<$2, Rest/binary>>, Handler, Stack, Config) -> 190 number(Rest, Handler, [$2], [integer|Stack], Config); 191value(<<$3, Rest/binary>>, Handler, Stack, Config) -> 192 number(Rest, Handler, [$3], [integer|Stack], Config); 193value(<<$4, Rest/binary>>, Handler, Stack, Config) -> 194 number(Rest, Handler, [$4], [integer|Stack], Config); 195value(<<$5, Rest/binary>>, Handler, Stack, Config) -> 196 number(Rest, Handler, [$5], [integer|Stack], Config); 197value(<<$6, Rest/binary>>, Handler, Stack, Config) -> 198 number(Rest, Handler, [$6], [integer|Stack], Config); 199value(<<$7, Rest/binary>>, Handler, Stack, Config) -> 200 number(Rest, Handler, [$7], [integer|Stack], Config); 201value(<<$8, Rest/binary>>, Handler, Stack, Config) -> 202 number(Rest, Handler, [$8], [integer|Stack], Config); 203value(<<$9, Rest/binary>>, Handler, Stack, Config) -> 204 number(Rest, Handler, [$9], [integer|Stack], Config); 205value(<<?negative, Rest/binary>>, Handler, Stack, Config) -> 206 number(Rest, Handler, [$-], [negative|Stack], Config); 207value(<<?newline, Rest/binary>>, Handler, Stack, Config) -> 208 value(Rest, Handler, Stack, Config); 209value(<<$t, Rest/binary>>, Handler, Stack, Config) -> 210 true(Rest, Handler, Stack, Config); 211value(<<$f, Rest/binary>>, Handler, Stack, Config) -> 212 false(Rest, Handler, Stack, Config); 213value(<<$n, Rest/binary>>, Handler, Stack, Config) -> 214 null(Rest, Handler, Stack, Config); 215value(<<?tab, Rest/binary>>, Handler, Stack, Config) -> 216 value(Rest, Handler, Stack, Config); 217value(<<?cr, Rest/binary>>, Handler, Stack, Config) -> 218 value(Rest, Handler, Stack, Config); 219value(<<?singlequote, Rest/binary>>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> 220 string(Rest, Handler, [singlequote|Stack], Config); 221value(<<?end_array, _/binary>> = Rest, Handler, Stack, Config=#config{strict_commas=false}) -> 222 maybe_done(Rest, Handler, Stack, Config); 223value(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) -> 224 ?error(value, <<?solidus, Rest/binary>>, Handler, Stack, Config); 225value(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) -> 226 comment(Rest, Handler, value, [comment|Stack], Config); 227value(<<?solidus, ?star, Rest/binary>>, Handler, Stack, Config) -> 228 comment(Rest, Handler, value, [multicomment|Stack], Config); 229value(<<?solidus>>, Handler, Stack, Config) -> 230 incomplete(value, <<?solidus>>, Handler, Stack, Config); 231value(<<>>, Handler, Stack, Config) -> 232 incomplete(value, <<>>, Handler, Stack, Config); 233value(Bin, Handler, Stack, Config) -> 234 ?error(value, Bin, Handler, Stack, Config). 235 236 237object(<<?doublequote, Rest/binary>>, Handler, Stack, Config) -> 238 string(Rest, Handler, Stack, Config); 239object(<<?space, Rest/binary>>, Handler, Stack, Config) -> 240 object(Rest, Handler, Stack, Config); 241object(<<?end_object, Rest/binary>>, Handler, [key|Stack], Config) -> 242 maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config); 243object(<<?newline, Rest/binary>>, Handler, Stack, Config) -> 244 object(Rest, Handler, Stack, Config); 245object(<<?tab, Rest/binary>>, Handler, Stack, Config) -> 246 object(Rest, Handler, Stack, Config); 247object(<<?cr, Rest/binary>>, Handler, Stack, Config) -> 248 object(Rest, Handler, Stack, Config); 249object(<<?singlequote, Rest/binary>>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> 250 string(Rest, Handler, [singlequote|Stack], Config); 251object(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) -> 252 ?error(object, <<?solidus, Rest/binary>>, Handler, Stack, Config); 253object(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) -> 254 comment(Rest, Handler, object, [comment|Stack], Config); 255object(<<?solidus, ?star, Rest/binary>>, Handler, Stack, Config) -> 256 comment(Rest, Handler, object, [multicomment|Stack], Config); 257object(<<?solidus>>, Handler, Stack, Config) -> 258 incomplete(object, <<?solidus>>, Handler, Stack, Config); 259object(<<>>, Handler, Stack, Config) -> 260 incomplete(object, <<>>, Handler, Stack, Config); 261object(Bin, Handler, Stack, Config) -> 262 ?error(object, Bin, Handler, Stack, Config). 263 264 265array(<<?end_array, Rest/binary>>, Handler, [array|Stack], Config) -> 266 maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config); 267array(<<?space, Rest/binary>>, Handler, Stack, Config) -> 268 array(Rest, Handler, Stack, Config); 269array(<<?newline, Rest/binary>>, Handler, Stack, Config) -> 270 array(Rest, Handler, Stack, Config); 271array(<<?tab, Rest/binary>>, Handler, Stack, Config) -> 272 array(Rest, Handler, Stack, Config); 273array(<<?cr, Rest/binary>>, Handler, Stack, Config) -> 274 array(Rest, Handler, Stack, Config); 275array(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) -> 276 value(<<?solidus, Rest/binary>>, Handler, Stack, Config); 277array(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) -> 278 comment(Rest, Handler, array, [comment|Stack], Config); 279array(<<?solidus, ?star, Rest/binary>>, Handler, Stack, Config) -> 280 comment(Rest, Handler, array, [multicomment|Stack], Config); 281array(<<?solidus>>, Handler, Stack, Config) -> 282 incomplete(array, <<?solidus>>, Handler, Stack, Config); 283array(<<>>, Handler, Stack, Config) -> 284 incomplete(array, <<>>, Handler, Stack, Config); 285array(Bin, Handler, Stack, Config) -> 286 value(Bin, Handler, Stack, Config). 287 288 289colon(<<?colon, Rest/binary>>, Handler, [key|Stack], Config) -> 290 value(Rest, Handler, [object|Stack], Config); 291colon(<<?space, Rest/binary>>, Handler, Stack, Config) -> 292 colon(Rest, Handler, Stack, Config); 293colon(<<?newline, Rest/binary>>, Handler, Stack, Config) -> 294 colon(Rest, Handler, Stack, Config); 295colon(<<?tab, Rest/binary>>, Handler, Stack, Config) -> 296 colon(Rest, Handler, Stack, Config); 297colon(<<?cr, Rest/binary>>, Handler, Stack, Config) -> 298 colon(Rest, Handler, Stack, Config); 299colon(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) -> 300 ?error(colon, <<?solidus, Rest/binary>>, Handler, Stack, Config); 301colon(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) -> 302 comment(Rest, Handler, colon, [comment|Stack], Config); 303colon(<<?solidus, ?star, Rest/binary>>, Handler, Stack, Config) -> 304 comment(Rest, Handler, colon, [multicomment|Stack], Config); 305colon(<<?solidus>>, Handler, Stack, Config) -> 306 incomplete(colon, <<?solidus>>, Handler, Stack, Config); 307colon(<<>>, Handler, Stack, Config) -> 308 incomplete(colon, <<>>, Handler, Stack, Config); 309colon(Bin, Handler, Stack, Config) -> 310 ?error(colon, Bin, Handler, Stack, Config). 311 312 313key(<<?doublequote, Rest/binary>>, Handler, Stack, Config) -> 314 string(Rest, Handler, Stack, Config); 315key(<<?space, Rest/binary>>, Handler, Stack, Config) -> 316 key(Rest, Handler, Stack, Config); 317key(<<?end_object, Rest/binary>>, Handler, [key|Stack], Config=#config{strict_commas=false}) -> 318 maybe_done(<<?end_object, Rest/binary>>, Handler, [object|Stack], Config); 319key(<<?newline, Rest/binary>>, Handler, Stack, Config) -> 320 key(Rest, Handler, Stack, Config); 321key(<<?tab, Rest/binary>>, Handler, Stack, Config) -> 322 key(Rest, Handler, Stack, Config); 323key(<<?cr, Rest/binary>>, Handler, Stack, Config) -> 324 key(Rest, Handler, Stack, Config); 325key(<<?singlequote, Rest/binary>>, Handler, Stack, Config=#config{strict_single_quotes=false}) -> 326 string(Rest, Handler, [singlequote|Stack], Config); 327key(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) -> 328 ?error(key, <<?solidus, Rest/binary>>, Handler, Stack, Config); 329key(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) -> 330 comment(Rest, Handler, key, [comment|Stack], Config); 331key(<<?solidus, ?star, Rest/binary>>, Handler, Stack, Config) -> 332 comment(Rest, Handler, key, [multicomment|Stack], Config); 333key(<<?solidus>>, Handler, Stack, Config) -> 334 incomplete(key, <<?solidus>>, Handler, Stack, Config); 335key(<<>>, Handler, Stack, Config) -> 336 incomplete(key, <<>>, Handler, Stack, Config); 337key(Bin, Handler, Stack, Config) -> 338 ?error(key, Bin, Handler, Stack, Config). 339 340 341%% note that if you encounter an error from string and you can't find the clause that 342%% caused it here, it might be in unescape below 343string(Bin, Handler, Stack, Config) -> 344 string(Bin, Handler, [], Stack, Config). 345 346 347string(<<?doublequote, Rest/binary>>, Handler, Acc, Stack, Config) -> 348 doublequote(Rest, Handler, Acc, Stack, Config); 349string(<<?singlequote, Rest/binary>>, Handler, Acc, Stack, Config) -> 350 singlequote(Rest, Handler, Acc, Stack, Config); 351string(<<?solidus, Rest/binary>>, Handler, Acc, Stack, Config) -> 352 string(Rest, Handler, [Acc, maybe_replace(?solidus, Config)], Stack, Config); 353string(<<?rsolidus/utf8, Rest/binary>>, Handler, Acc, Stack, Config) -> 354 unescape(Rest, Handler, Acc, Stack, Config); 355%% TODO this is pretty gross and i don't like it 356string(<<X/utf8, Rest/binary>> = Bin, Handler, Acc, Stack, Config=#config{uescape=true}) -> 357 case X of 358 X when X < 16#80 -> count(Bin, Handler, Acc, Stack, Config); 359 X -> string(Rest, Handler, [Acc, json_escape_sequence(X)], Stack, Config) 360 end; 361%% u+2028 362string(<<226, 128, 168, Rest/binary>>, Handler, Acc, Stack, Config) -> 363 string(Rest, Handler, [Acc, maybe_replace(16#2028, Config)], Stack, Config); 364%% u+2029 365string(<<226, 128, 169, Rest/binary>>, Handler, Acc, Stack, Config) -> 366 string(Rest, Handler, [Acc, maybe_replace(16#2029, Config)], Stack, Config); 367string(<<X/utf8, _/binary>> = Bin, Handler, Acc, Stack, Config=#config{strict_control_codes=true}) when X > 16#1f -> 368 count(Bin, Handler, Acc, Stack, Config); 369string(<<_/utf8, _/binary>> = Bin, Handler, Acc, Stack, Config=#config{strict_control_codes=false}) -> 370 count(Bin, Handler, Acc, Stack, Config); 371%% necessary for bytes that are badly formed utf8 that won't match in `count` 372string(<<X, Rest/binary>>, Handler, Acc, Stack, Config=#config{dirty_strings=true}) -> 373 string(Rest, Handler, [Acc, X], Stack, Config); 374%% u+fffe and u+ffff for R14BXX (subsequent runtimes will happily match with /utf8 375string(<<239, 191, 190, Rest/binary>>, Handler, Acc, Stack, Config) -> 376 string(Rest, Handler, [Acc, <<16#fffe/utf8>>], Stack, Config); 377string(<<239, 191, 191, Rest/binary>>, Handler, Acc, Stack, Config) -> 378 string(Rest, Handler, [Acc, <<16#ffff/utf8>>], Stack, Config); 379string(<<>>, Handler, Acc, Stack, Config) -> 380 incomplete(string, <<>>, Handler, Acc, Stack, Config); 381string(<<X>>, Handler, Acc, Stack, Config) when X >= 2#11000000 -> 382 incomplete(string, <<X>>, Handler, Acc, Stack, Config); 383string(<<X, Y>>, Handler, Acc, Stack, Config) when X >= 2#11100000, Y >= 2#10000000 -> 384 incomplete(string, <<X, Y>>, Handler, Acc, Stack, Config); 385string(<<X, Y, Z>>, Handler, Acc, Stack, Config) 386 when X >= 2#11100000, Y >= 2#10000000, Z >= 2#10000000 -> 387 incomplete(string, <<X, Y, Z>>, Handler, Acc, Stack, Config); 388%% surrogates 389string(<<237, X, _, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) 390 when X >= 160 -> 391 string(Rest, Handler, [Acc, <<16#fffd/utf8>>], Stack, Config); 392%% overlong encodings and missing continuations of a 2 byte sequence 393string(<<X, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) 394 when X >= 192, X =< 223 -> 395 strip_continuations(Rest, Handler, Acc, Stack, Config, 1); 396%% overlong encodings and missing continuations of a 3 byte sequence 397string(<<X, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) 398 when X >= 224, X =< 239 -> 399 strip_continuations(Rest, Handler, Acc, Stack, Config, 2); 400%% overlong encodings and missing continuations of a 4 byte sequence 401string(<<X, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) 402 when X >= 240, X =< 247 -> 403 strip_continuations(Rest, Handler, Acc, Stack, Config, 3); 404%% incompletes and unexpected bytes, including orphan continuations 405string(<<_, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) -> 406 string(Rest, Handler, [Acc, <<16#fffd/utf8>>], Stack, Config); 407string(Bin, Handler, Acc, Stack, Config) -> ?error(string, Bin, Handler, Acc, Stack, Config). 408 409 410count(Bin, Handler, Acc, Stack, Config) -> 411 Size = count(Bin, 0, Config), 412 <<Clean:Size/binary, Rest/binary>> = Bin, 413 string(Rest, Handler, [Acc, Clean], Stack, Config). 414 415 416%% explicitly whitelist ascii set for faster parsing. really? really. someone should 417%% submit a patch that unrolls simple guards 418count(<<32, Rest/binary>>, N, Config) -> 419 count(Rest, N + 1, Config); 420count(<<33, Rest/binary>>, N, Config) -> 421 count(Rest, N + 1, Config); 422count(<<?doublequote, _/binary>>, N, _) -> N; 423count(<<35, Rest/binary>>, N, Config) -> 424 count(Rest, N + 1, Config); 425count(<<36, Rest/binary>>, N, Config) -> 426 count(Rest, N + 1, Config); 427count(<<37, Rest/binary>>, N, Config) -> 428 count(Rest, N + 1, Config); 429count(<<38, Rest/binary>>, N, Config) -> 430 count(Rest, N + 1, Config); 431count(<<?singlequote, _/binary>>, N, _) -> N; 432count(<<40, Rest/binary>>, N, Config) -> 433 count(Rest, N + 1, Config); 434count(<<41, Rest/binary>>, N, Config) -> 435 count(Rest, N + 1, Config); 436count(<<42, Rest/binary>>, N, Config) -> 437 count(Rest, N + 1, Config); 438count(<<43, Rest/binary>>, N, Config) -> 439 count(Rest, N + 1, Config); 440count(<<44, Rest/binary>>, N, Config) -> 441 count(Rest, N + 1, Config); 442count(<<45, Rest/binary>>, N, Config) -> 443 count(Rest, N + 1, Config); 444count(<<46, Rest/binary>>, N, Config) -> 445 count(Rest, N + 1, Config); 446count(<<?solidus, _/binary>>, N, _) -> N; 447count(<<48, Rest/binary>>, N, Config) -> 448 count(Rest, N + 1, Config); 449count(<<49, Rest/binary>>, N, Config) -> 450 count(Rest, N + 1, Config); 451count(<<50, Rest/binary>>, N, Config) -> 452 count(Rest, N + 1, Config); 453count(<<51, Rest/binary>>, N, Config) -> 454 count(Rest, N + 1, Config); 455count(<<52, Rest/binary>>, N, Config) -> 456 count(Rest, N + 1, Config); 457count(<<53, Rest/binary>>, N, Config) -> 458 count(Rest, N + 1, Config); 459count(<<54, Rest/binary>>, N, Config) -> 460 count(Rest, N + 1, Config); 461count(<<55, Rest/binary>>, N, Config) -> 462 count(Rest, N + 1, Config); 463count(<<56, Rest/binary>>, N, Config) -> 464 count(Rest, N + 1, Config); 465count(<<57, Rest/binary>>, N, Config) -> 466 count(Rest, N + 1, Config); 467count(<<58, Rest/binary>>, N, Config) -> 468 count(Rest, N + 1, Config); 469count(<<59, Rest/binary>>, N, Config) -> 470 count(Rest, N + 1, Config); 471count(<<60, Rest/binary>>, N, Config) -> 472 count(Rest, N + 1, Config); 473count(<<61, Rest/binary>>, N, Config) -> 474 count(Rest, N + 1, Config); 475count(<<62, Rest/binary>>, N, Config) -> 476 count(Rest, N + 1, Config); 477count(<<63, Rest/binary>>, N, Config) -> 478 count(Rest, N + 1, Config); 479count(<<64, Rest/binary>>, N, Config) -> 480 count(Rest, N + 1, Config); 481count(<<65, Rest/binary>>, N, Config) -> 482 count(Rest, N + 1, Config); 483count(<<66, Rest/binary>>, N, Config) -> 484 count(Rest, N + 1, Config); 485count(<<67, Rest/binary>>, N, Config) -> 486 count(Rest, N + 1, Config); 487count(<<68, Rest/binary>>, N, Config) -> 488 count(Rest, N + 1, Config); 489count(<<69, Rest/binary>>, N, Config) -> 490 count(Rest, N + 1, Config); 491count(<<70, Rest/binary>>, N, Config) -> 492 count(Rest, N + 1, Config); 493count(<<71, Rest/binary>>, N, Config) -> 494 count(Rest, N + 1, Config); 495count(<<72, Rest/binary>>, N, Config) -> 496 count(Rest, N + 1, Config); 497count(<<73, Rest/binary>>, N, Config) -> 498 count(Rest, N + 1, Config); 499count(<<74, Rest/binary>>, N, Config) -> 500 count(Rest, N + 1, Config); 501count(<<75, Rest/binary>>, N, Config) -> 502 count(Rest, N + 1, Config); 503count(<<76, Rest/binary>>, N, Config) -> 504 count(Rest, N + 1, Config); 505count(<<77, Rest/binary>>, N, Config) -> 506 count(Rest, N + 1, Config); 507count(<<78, Rest/binary>>, N, Config) -> 508 count(Rest, N + 1, Config); 509count(<<79, Rest/binary>>, N, Config) -> 510 count(Rest, N + 1, Config); 511count(<<80, Rest/binary>>, N, Config) -> 512 count(Rest, N + 1, Config); 513count(<<81, Rest/binary>>, N, Config) -> 514 count(Rest, N + 1, Config); 515count(<<82, Rest/binary>>, N, Config) -> 516 count(Rest, N + 1, Config); 517count(<<83, Rest/binary>>, N, Config) -> 518 count(Rest, N + 1, Config); 519count(<<84, Rest/binary>>, N, Config) -> 520 count(Rest, N + 1, Config); 521count(<<85, Rest/binary>>, N, Config) -> 522 count(Rest, N + 1, Config); 523count(<<86, Rest/binary>>, N, Config) -> 524 count(Rest, N + 1, Config); 525count(<<87, Rest/binary>>, N, Config) -> 526 count(Rest, N + 1, Config); 527count(<<88, Rest/binary>>, N, Config) -> 528 count(Rest, N + 1, Config); 529count(<<89, Rest/binary>>, N, Config) -> 530 count(Rest, N + 1, Config); 531count(<<90, Rest/binary>>, N, Config) -> 532 count(Rest, N + 1, Config); 533count(<<91, Rest/binary>>, N, Config) -> 534 count(Rest, N + 1, Config); 535count(<<?rsolidus, _/binary>>, N, _) -> N; 536count(<<93, Rest/binary>>, N, Config) -> 537 count(Rest, N + 1, Config); 538count(<<94, Rest/binary>>, N, Config) -> 539 count(Rest, N + 1, Config); 540count(<<95, Rest/binary>>, N, Config) -> 541 count(Rest, N + 1, Config); 542count(<<96, Rest/binary>>, N, Config) -> 543 count(Rest, N + 1, Config); 544count(<<97, Rest/binary>>, N, Config) -> 545 count(Rest, N + 1, Config); 546count(<<98, Rest/binary>>, N, Config) -> 547 count(Rest, N + 1, Config); 548count(<<99, Rest/binary>>, N, Config) -> 549 count(Rest, N + 1, Config); 550count(<<100, Rest/binary>>, N, Config) -> 551 count(Rest, N + 1, Config); 552count(<<101, Rest/binary>>, N, Config) -> 553 count(Rest, N + 1, Config); 554count(<<102, Rest/binary>>, N, Config) -> 555 count(Rest, N + 1, Config); 556count(<<103, Rest/binary>>, N, Config) -> 557 count(Rest, N + 1, Config); 558count(<<104, Rest/binary>>, N, Config) -> 559 count(Rest, N + 1, Config); 560count(<<105, Rest/binary>>, N, Config) -> 561 count(Rest, N + 1, Config); 562count(<<106, Rest/binary>>, N, Config) -> 563 count(Rest, N + 1, Config); 564count(<<107, Rest/binary>>, N, Config) -> 565 count(Rest, N + 1, Config); 566count(<<108, Rest/binary>>, N, Config) -> 567 count(Rest, N + 1, Config); 568count(<<109, Rest/binary>>, N, Config) -> 569 count(Rest, N + 1, Config); 570count(<<110, Rest/binary>>, N, Config) -> 571 count(Rest, N + 1, Config); 572count(<<111, Rest/binary>>, N, Config) -> 573 count(Rest, N + 1, Config); 574count(<<112, Rest/binary>>, N, Config) -> 575 count(Rest, N + 1, Config); 576count(<<113, Rest/binary>>, N, Config) -> 577 count(Rest, N + 1, Config); 578count(<<114, Rest/binary>>, N, Config) -> 579 count(Rest, N + 1, Config); 580count(<<115, Rest/binary>>, N, Config) -> 581 count(Rest, N + 1, Config); 582count(<<116, Rest/binary>>, N, Config) -> 583 count(Rest, N + 1, Config); 584count(<<117, Rest/binary>>, N, Config) -> 585 count(Rest, N + 1, Config); 586count(<<118, Rest/binary>>, N, Config) -> 587 count(Rest, N + 1, Config); 588count(<<119, Rest/binary>>, N, Config) -> 589 count(Rest, N + 1, Config); 590count(<<120, Rest/binary>>, N, Config) -> 591 count(Rest, N + 1, Config); 592count(<<121, Rest/binary>>, N, Config) -> 593 count(Rest, N + 1, Config); 594count(<<122, Rest/binary>>, N, Config) -> 595 count(Rest, N + 1, Config); 596count(<<123, Rest/binary>>, N, Config) -> 597 count(Rest, N + 1, Config); 598count(<<124, Rest/binary>>, N, Config) -> 599 count(Rest, N + 1, Config); 600count(<<125, Rest/binary>>, N, Config) -> 601 count(Rest, N + 1, Config); 602count(<<126, Rest/binary>>, N, Config) -> 603 count(Rest, N + 1, Config); 604count(<<127, Rest/binary>>, N, Config) -> 605 count(Rest, N + 1, Config); 606count(<<_, Rest/binary>>, N, Config=#config{dirty_strings=true}) -> 607 count(Rest, N + 1, Config); 608count(<<_/utf8, _/binary>>, N, #config{uescape=true}) -> N; 609count(<<X/utf8, Rest/binary>>, N, Config=#config{strict_control_codes=false}) when X < 32 -> 610 count(Rest, N + 1, Config); 611count(<<X/utf8, _/binary>>, N, #config{strict_control_codes=true}) when X < 32 -> N; 612count(<<X/utf8, Rest/binary>>, N, Config) -> 613 case X of 614 X when X < 16#800 -> count(Rest, N + 2, Config); 615 %% jsonp escaping 616 16#2028 -> N; 617 16#2029 -> N; 618 X when X < 16#10000 -> count(Rest, N + 3, Config); 619 _ -> count(Rest, N + 4, Config) 620 end; 621count(_, N, _) -> N. 622 623 624doublequote(Rest, Handler, Acc, [key|_] = Stack, Config) -> 625 colon(Rest, handle_event({key, iolist_to_binary(Acc)}, Handler, Config), Stack, Config); 626doublequote(Rest, Handler, Acc, [singlequote|_] = Stack, Config) -> 627 string(Rest, Handler, [Acc, maybe_replace(?doublequote, Config)], Stack, Config); 628doublequote(<<>>, Handler, Acc, [singlequote|_] = Stack, Config) -> 629 incomplete(string, <<?doublequote>>, Handler, Acc, Stack, Config); 630doublequote(Rest, Handler, Acc, Stack, Config) -> 631 maybe_done(Rest, handle_event({string, iolist_to_binary(Acc)}, Handler, Config), Stack, Config). 632 633 634singlequote(Rest, Handler, Acc, [singlequote, key|Stack], Config) -> 635 colon(Rest, handle_event({key, iolist_to_binary(Acc)}, Handler, Config), [key|Stack], Config); 636singlequote(Rest, Handler, Acc, [singlequote|Stack], Config) -> 637 maybe_done(Rest, handle_event({string, iolist_to_binary(Acc)}, Handler, Config), Stack, Config); 638singlequote(Rest, Handler, Acc, Stack, Config) -> 639 string(Rest, Handler, [Acc, ?singlequote], Stack, Config). 640 641 642%% strips continuation bytes after bad utf bytes, guards against both too short 643%% and overlong sequences. N is the maximum number of bytes to strip 644strip_continuations(<<Rest/binary>>, Handler, Acc, Stack, Config, 0) -> 645 string(Rest, Handler, [Acc, <<16#fffd/utf8>>], Stack, Config); 646strip_continuations(<<X, Rest/binary>>, Handler, Acc, Stack, Config, N) when X >= 128, X =< 191 -> 647 strip_continuations(Rest, Handler, Acc, Stack, Config, N - 1); 648%% if end of input is reached before stripping the max number of continuations 649%% possible magic numbers are reinserted into the stream that get us back to 650%% the same state without complicated machinery 651strip_continuations(<<>>, Handler, Acc, Stack, Config, N) -> 652 case N of 653 1 -> incomplete(string, <<192>>, Handler, Acc, Stack, Config); 654 2 -> incomplete(string, <<224>>, Handler, Acc, Stack, Config); 655 3 -> incomplete(string, <<240>>, Handler, Acc, Stack, Config) 656 end; 657%% not a continuation byte, insert a replacement character for sequence thus 658%% far and dispatch back to string 659strip_continuations(<<Rest/binary>>, Handler, Acc, Stack, Config, _) -> 660 string(Rest, Handler, [Acc, <<16#fffd/utf8>>], Stack, Config). 661 662 663%% this all gets really gross and should probably eventually be folded into 664%% but for now it fakes being part of string on incompletes and errors 665unescape(<<?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config=#config{dirty_strings=true}) -> 666 string(<<?rsolidus, Rest/binary>>, Handler, [Acc, <<?rsolidus>>], Stack, Config); 667unescape(<<C, Rest/binary>>, Handler, Acc, Stack, Config=#config{dirty_strings=true}) -> 668 string(Rest, Handler, [Acc, <<?rsolidus, C>>], Stack, Config); 669unescape(<<$b, Rest/binary>>, Handler, Acc, Stack, Config) -> 670 string(Rest, Handler, [Acc, maybe_replace($\b, Config)], Stack, Config); 671unescape(<<$f, Rest/binary>>, Handler, Acc, Stack, Config) -> 672 string(Rest, Handler, [Acc, maybe_replace($\f, Config)], Stack, Config); 673unescape(<<$n, Rest/binary>>, Handler, Acc, Stack, Config) -> 674 string(Rest, Handler, [Acc, maybe_replace($\n, Config)], Stack, Config); 675unescape(<<$r, Rest/binary>>, Handler, Acc, Stack, Config) -> 676 string(Rest, Handler, [Acc, maybe_replace($\r, Config)], Stack, Config); 677unescape(<<$t, Rest/binary>>, Handler, Acc, Stack, Config) -> 678 string(Rest, Handler, [Acc, maybe_replace($\t, Config)], Stack, Config); 679unescape(<<?doublequote, Rest/binary>>, Handler, Acc, Stack, Config) -> 680 string(Rest, Handler, [Acc, maybe_replace($\", Config)], Stack, Config); 681unescape(<<?singlequote, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_single_quotes=false}) -> 682 string(Rest, Handler, [Acc, <<?singlequote>>], Stack, Config); 683unescape(<<?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config) -> 684 string(Rest, Handler, [Acc, maybe_replace($\\, Config)], Stack, Config); 685unescape(<<?solidus, Rest/binary>>, Handler, Acc, Stack, Config) -> 686 string(Rest, Handler, [Acc, maybe_replace($/, Config)], Stack, Config); 687unescape(<<$u, F, A, B, C, ?rsolidus, $u, G, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config) 688 when (A == $8 orelse A == $9 orelse A == $a orelse A == $b orelse A == $A orelse A == $B), 689 (X == $c orelse X == $d orelse X == $e orelse X == $f orelse X == $C orelse X == $D orelse X == $E orelse X == $F), 690 (F == $d orelse F == $D), 691 (G == $d orelse G == $D), 692 ?is_hex(B), ?is_hex(C), ?is_hex(Y), ?is_hex(Z) 693 -> 694 High = erlang:list_to_integer([$d, A, B, C], 16), 695 Low = erlang:list_to_integer([$d, X, Y, Z], 16), 696 Codepoint = (High - 16#d800) * 16#400 + (Low - 16#dc00) + 16#10000, 697 string(Rest, Handler, [Acc, <<Codepoint/utf8>>], Stack, Config); 698unescape(<<$u, F, A, B, C, ?rsolidus, $u, W, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config) 699 when (A == $8 orelse A == $9 orelse A == $a orelse A == $b orelse A == $A orelse A == $B), 700 (F == $d orelse F == $D), 701 ?is_hex(B), ?is_hex(C), ?is_hex(W), ?is_hex(X), ?is_hex(Y), ?is_hex(Z) 702 -> 703 case Config#config.strict_utf8 of 704 true -> ?error(<<$u, $d, A, B, C, ?rsolidus, $u, W, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config); 705 false -> string(Rest, Handler, [Acc, <<16#fffd/utf8>>, <<16#fffd/utf8>>], Stack, Config) 706 end; 707unescape(<<$u, F, A, B, C, ?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config) 708 when (A == $8 orelse A == $9 orelse A == $a orelse A == $b orelse A == $A orelse A == $B), 709 (F == $d orelse F == $D), 710 ?is_hex(B), ?is_hex(C) 711 -> 712 incomplete(string, <<?rsolidus, $u, $d, A, B, C, ?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config); 713unescape(<<$u, F, A, B, C>>, Handler, Acc, Stack, Config) 714 when (A == $8 orelse A == $9 orelse A == $a orelse A == $b orelse A == $A orelse A == $B), 715 (F == $d orelse F == $D), 716 ?is_hex(B), ?is_hex(C) 717 -> 718 incomplete(string, <<?rsolidus, $u, $d, A, B, C>>, Handler, Acc, Stack, Config); 719unescape(<<$u, A, B, C, D, Rest/binary>>, Handler, Acc, Stack, Config) 720 when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D) -> 721 case erlang:list_to_integer([A, B, C, D], 16) of 722 Codepoint when Codepoint < 16#d800; Codepoint > 16#dfff -> 723 string(Rest, Handler, [Acc, maybe_replace(Codepoint, Config)], Stack, Config); 724 _ when Config#config.strict_utf8 -> 725 ?error(string, <<?rsolidus, $u, A, B, C, D, Rest/binary>>, Handler, Acc, Stack, Config); 726 _ -> string(Rest, Handler, [Acc, <<16#fffd/utf8>>], Stack, Config) 727 end; 728unescape(Bin, Handler, Acc, Stack, Config) -> 729 case is_partial_escape(Bin) of 730 true -> incomplete(string, <<?rsolidus/utf8, Bin/binary>>, Handler, Acc, Stack, Config); 731 false -> case Config#config.strict_escapes of 732 true -> ?error(string, <<?rsolidus, Bin/binary>>, Handler, Acc, Stack, Config); 733 false -> string(Bin, Handler, [Acc, <<?rsolidus>>], Stack, Config) 734 end 735 end. 736 737 738is_partial_escape(<<$u, A, B, C>>) when ?is_hex(A), ?is_hex(B), ?is_hex(C) -> true; 739is_partial_escape(<<$u, A, B>>) when ?is_hex(A), ?is_hex(B) -> true; 740is_partial_escape(<<$u, A>>) when ?is_hex(A) -> true; 741is_partial_escape(<<$u>>) -> true; 742is_partial_escape(<<>>) -> true; 743is_partial_escape(_) -> false. 744 745 746maybe_replace(C, #config{dirty_strings=true}) -> <<C>>; 747maybe_replace($\b, #config{escaped_strings=true}) -> <<$\\, $b>>; 748maybe_replace($\t, #config{escaped_strings=true}) -> <<$\\, $t>>; 749maybe_replace($\n, #config{escaped_strings=true}) -> <<$\\, $n>>; 750maybe_replace($\f, #config{escaped_strings=true}) -> <<$\\, $f>>; 751maybe_replace($\r, #config{escaped_strings=true}) -> <<$\\, $r>>; 752maybe_replace($\", #config{escaped_strings=true}) -> <<$\\, $\">>; 753maybe_replace($/, Config=#config{escaped_strings=true}) -> 754 case Config#config.escaped_forward_slashes of 755 true -> <<$\\, $/>> 756 ; false -> <<$/>> 757 end; 758maybe_replace($\\, #config{escaped_strings=true}) -> <<$\\, $\\>>; 759maybe_replace(X, Config=#config{escaped_strings=true}) when X == 16#2028; X == 16#2029 -> 760 case Config#config.unescaped_jsonp of 761 true -> <<X/utf8>> 762 ; false -> json_escape_sequence(X) 763 end; 764maybe_replace(X, #config{escaped_strings=true}) when X < 32 -> 765 json_escape_sequence(X); 766maybe_replace(X, _Config) -> <<X/utf8>>. 767 768 769%% convert a codepoint to it's \uXXXX equiv. 770json_escape_sequence(X) when X < 65536 -> 771 <<A:4, B:4, C:4, D:4>> = <<X:16>>, 772 <<$\\, $u, (to_hex(A)), (to_hex(B)), (to_hex(C)), (to_hex(D))>>; 773json_escape_sequence(X) -> 774 Adjusted = X - 16#10000, 775 <<A:10, B:10>> = <<Adjusted:20>>, 776 [json_escape_sequence(A + 16#d800), json_escape_sequence(B + 16#dc00)]. 777 778 779%% ascii "1" is [49], "2" is [50], etc... 780to_hex(10) -> $a; 781to_hex(11) -> $b; 782to_hex(12) -> $c; 783to_hex(13) -> $d; 784to_hex(14) -> $e; 785to_hex(15) -> $f; 786to_hex(X) -> X + 48. 787 788 789number(<<$e, Rest/binary>>, Handler, Acc, [integer|Stack], Config) -> 790 number(Rest, Handler, [Acc, $., $0, $e], [e|Stack], Config); 791number(<<$E, Rest/binary>>, Handler, Acc, [integer|Stack], Config) -> 792 number(Rest, Handler, [Acc, $., $0, $e], [e|Stack], Config); 793number(<<$e, Rest/binary>>, Handler, Acc, [zero|Stack], Config) -> 794 number(Rest, Handler, [Acc, $., $0, $e], [e|Stack], Config); 795number(<<$E, Rest/binary>>, Handler, Acc, [zero|Stack], Config) -> 796 number(Rest, Handler, [Acc, $., $0, $e], [e|Stack], Config); 797number(<<>>, Handler, Acc, [State|Stack], Config=#config{stream=false}) -> 798 NumType = case State of 799 zero -> integer; 800 integer -> integer; 801 decimal -> float; 802 exp -> float 803 end, 804 finish_number(<<>>, Handler, {NumType, iolist_to_binary(Acc)}, Stack, Config); 805number(<<>>, Handler, Acc, Stack, Config) -> 806 incomplete(number, <<>>, Handler, Acc, Stack, Config); 807number(Bin, Handler, Acc, [State|Stack], Config) -> 808 Counted = case State of 809 zero -> zero(Bin, 0); 810 integer -> integer(Bin, 0); 811 negative -> negative(Bin, 0); 812 initialdecimal -> initialdecimal(Bin, 0); 813 decimal -> decimal(Bin, 0); 814 e -> e(Bin, 0); 815 ex -> ex(Bin, 0); 816 exp -> exp(Bin, 0) 817 end, 818 case Counted of 819 {finish_integer, Size} -> 820 <<Clean:Size/binary, Rest/binary>> = Bin, 821 finish_number(Rest, Handler, {integer, iolist_to_binary([Acc, Clean])}, Stack, Config); 822 {finish_float, Size} -> 823 <<Clean:Size/binary, Rest/binary>> = Bin, 824 finish_number(Rest, Handler, {float, iolist_to_binary([Acc, Clean])}, Stack, Config); 825 {error, Size} -> 826 <<Clean:Size/binary, Rest/binary>> = Bin, 827 ?error(number, Rest, Handler, [Acc, Clean], Stack, Config); 828 {NewState, Size} -> 829 <<Clean:Size/binary, Rest/binary>> = Bin, 830 number(Rest, Handler, [Acc, Clean], [NewState|Stack], Config) 831 end. 832 833 834zero(<<?decimalpoint, Rest/binary>>, N) -> initialdecimal(Rest, N + 1); 835zero(<<$e, _/binary>>, N) -> {integer, N}; 836zero(<<$E, _/binary>>, N) -> {integer, N}; 837zero(<<>>, N) -> {zero, N}; 838zero(_, N) -> {finish_integer, N}. 839 840 841integer(<<$0, Rest/binary>>, N) -> integer(Rest, N + 1); 842integer(<<$1, Rest/binary>>, N) -> integer(Rest, N + 1); 843integer(<<$2, Rest/binary>>, N) -> integer(Rest, N + 1); 844integer(<<$3, Rest/binary>>, N) -> integer(Rest, N + 1); 845integer(<<$4, Rest/binary>>, N) -> integer(Rest, N + 1); 846integer(<<$5, Rest/binary>>, N) -> integer(Rest, N + 1); 847integer(<<$6, Rest/binary>>, N) -> integer(Rest, N + 1); 848integer(<<$7, Rest/binary>>, N) -> integer(Rest, N + 1); 849integer(<<$8, Rest/binary>>, N) -> integer(Rest, N + 1); 850integer(<<$9, Rest/binary>>, N) -> integer(Rest, N + 1); 851integer(<<?decimalpoint, Rest/binary>>, N) -> initialdecimal(Rest, N + 1); 852integer(<<$e, _/binary>>, N) -> {integer, N}; 853integer(<<$E, _/binary>>, N) -> {integer, N}; 854integer(<<>>, N) -> {integer, N}; 855integer(_, N) -> {finish_integer, N}. 856 857 858negative(<<$0, Rest/binary>>, N) -> zero(Rest, N + 1); 859negative(<<$1, Rest/binary>>, N) -> integer(Rest, N + 1); 860negative(<<$2, Rest/binary>>, N) -> integer(Rest, N + 1); 861negative(<<$3, Rest/binary>>, N) -> integer(Rest, N + 1); 862negative(<<$4, Rest/binary>>, N) -> integer(Rest, N + 1); 863negative(<<$5, Rest/binary>>, N) -> integer(Rest, N + 1); 864negative(<<$6, Rest/binary>>, N) -> integer(Rest, N + 1); 865negative(<<$7, Rest/binary>>, N) -> integer(Rest, N + 1); 866negative(<<$8, Rest/binary>>, N) -> integer(Rest, N + 1); 867negative(<<$9, Rest/binary>>, N) -> integer(Rest, N + 1); 868negative(<<>>, N) -> {negative, N}; 869negative(_, N) -> {error, N}. 870 871 872initialdecimal(<<$0, Rest/binary>>, N) -> decimal(Rest, N + 1); 873initialdecimal(<<$1, Rest/binary>>, N) -> decimal(Rest, N + 1); 874initialdecimal(<<$2, Rest/binary>>, N) -> decimal(Rest, N + 1); 875initialdecimal(<<$3, Rest/binary>>, N) -> decimal(Rest, N + 1); 876initialdecimal(<<$4, Rest/binary>>, N) -> decimal(Rest, N + 1); 877initialdecimal(<<$5, Rest/binary>>, N) -> decimal(Rest, N + 1); 878initialdecimal(<<$6, Rest/binary>>, N) -> decimal(Rest, N + 1); 879initialdecimal(<<$7, Rest/binary>>, N) -> decimal(Rest, N + 1); 880initialdecimal(<<$8, Rest/binary>>, N) -> decimal(Rest, N + 1); 881initialdecimal(<<$9, Rest/binary>>, N) -> decimal(Rest, N + 1); 882initialdecimal(<<>>, N) -> {initialdecimal, N}; 883initialdecimal(_, N) -> {error, N}. 884 885 886decimal(<<$0, Rest/binary>>, N) -> decimal(Rest, N + 1); 887decimal(<<$1, Rest/binary>>, N) -> decimal(Rest, N + 1); 888decimal(<<$2, Rest/binary>>, N) -> decimal(Rest, N + 1); 889decimal(<<$3, Rest/binary>>, N) -> decimal(Rest, N + 1); 890decimal(<<$4, Rest/binary>>, N) -> decimal(Rest, N + 1); 891decimal(<<$5, Rest/binary>>, N) -> decimal(Rest, N + 1); 892decimal(<<$6, Rest/binary>>, N) -> decimal(Rest, N + 1); 893decimal(<<$7, Rest/binary>>, N) -> decimal(Rest, N + 1); 894decimal(<<$8, Rest/binary>>, N) -> decimal(Rest, N + 1); 895decimal(<<$9, Rest/binary>>, N) -> decimal(Rest, N + 1); 896decimal(<<$e, Rest/binary>>, N) -> e(Rest, N + 1); 897decimal(<<$E, Rest/binary>>, N) -> e(Rest, N + 1); 898decimal(<<>>, N) -> {decimal, N}; 899decimal(_, N) -> {finish_float, N}. 900 901 902e(<<$0, Rest/binary>>, N) -> exp(Rest, N + 1); 903e(<<$1, Rest/binary>>, N) -> exp(Rest, N + 1); 904e(<<$2, Rest/binary>>, N) -> exp(Rest, N + 1); 905e(<<$3, Rest/binary>>, N) -> exp(Rest, N + 1); 906e(<<$4, Rest/binary>>, N) -> exp(Rest, N + 1); 907e(<<$5, Rest/binary>>, N) -> exp(Rest, N + 1); 908e(<<$6, Rest/binary>>, N) -> exp(Rest, N + 1); 909e(<<$7, Rest/binary>>, N) -> exp(Rest, N + 1); 910e(<<$8, Rest/binary>>, N) -> exp(Rest, N + 1); 911e(<<$9, Rest/binary>>, N) -> exp(Rest, N + 1); 912e(<<?positive, Rest/binary>>, N) -> ex(Rest, N + 1); 913e(<<?negative, Rest/binary>>, N) -> ex(Rest, N + 1); 914e(<<>>, N) -> {e, N}; 915e(_, N) -> {error, N}. 916 917 918ex(<<$0, Rest/binary>>, N) -> exp(Rest, N + 1); 919ex(<<$1, Rest/binary>>, N) -> exp(Rest, N + 1); 920ex(<<$2, Rest/binary>>, N) -> exp(Rest, N + 1); 921ex(<<$3, Rest/binary>>, N) -> exp(Rest, N + 1); 922ex(<<$4, Rest/binary>>, N) -> exp(Rest, N + 1); 923ex(<<$5, Rest/binary>>, N) -> exp(Rest, N + 1); 924ex(<<$6, Rest/binary>>, N) -> exp(Rest, N + 1); 925ex(<<$7, Rest/binary>>, N) -> exp(Rest, N + 1); 926ex(<<$8, Rest/binary>>, N) -> exp(Rest, N + 1); 927ex(<<$9, Rest/binary>>, N) -> exp(Rest, N + 1); 928ex(<<>>, N) -> {ex, N}; 929ex(_, N) -> {error, N}. 930 931 932exp(<<$0, Rest/binary>>, N) -> exp(Rest, N + 1); 933exp(<<$1, Rest/binary>>, N) -> exp(Rest, N + 1); 934exp(<<$2, Rest/binary>>, N) -> exp(Rest, N + 1); 935exp(<<$3, Rest/binary>>, N) -> exp(Rest, N + 1); 936exp(<<$4, Rest/binary>>, N) -> exp(Rest, N + 1); 937exp(<<$5, Rest/binary>>, N) -> exp(Rest, N + 1); 938exp(<<$6, Rest/binary>>, N) -> exp(Rest, N + 1); 939exp(<<$7, Rest/binary>>, N) -> exp(Rest, N + 1); 940exp(<<$8, Rest/binary>>, N) -> exp(Rest, N + 1); 941exp(<<$9, Rest/binary>>, N) -> exp(Rest, N + 1); 942exp(<<>>, N) -> {exp, N}; 943exp(_, N) -> {finish_float, N}. 944 945 946finish_number(Rest, Handler, Acc, Stack, Config) -> 947 maybe_done(Rest, handle_event(format_number(Acc), Handler, Config), Stack, Config). 948 949 950-ifndef(no_binary_to_whatever). 951format_number({integer, Acc}) -> {integer, binary_to_integer(Acc)}; 952format_number({float, Acc}) -> {float, binary_to_float(Acc)}. 953-else. 954format_number({integer, Acc}) -> {integer, list_to_integer(unicode:characters_to_list(Acc))}; 955format_number({float, Acc}) -> {float, list_to_float(unicode:characters_to_list(Acc))}. 956-endif. 957 958 959true(<<$r, $u, $e, Rest/binary>>, Handler, Stack, Config) -> 960 maybe_done(Rest, handle_event({literal, true}, Handler, Config), Stack, Config); 961true(<<$r, $u>>, Handler, Stack, Config) -> 962 incomplete(true, <<$r, $u>>, Handler, Stack, Config); 963true(<<$r>>, Handler, Stack, Config) -> 964 incomplete(true, <<$r>>, Handler, Stack, Config); 965true(<<>>, Handler, Stack, Config) -> 966 incomplete(true, <<>>, Handler, Stack, Config); 967true(Bin, Handler, Stack, Config) -> 968 ?error(true, Bin, Handler, Stack, Config). 969 970 971false(<<$a, $l, $s, $e, Rest/binary>>, Handler, Stack, Config) -> 972 maybe_done(Rest, handle_event({literal, false}, Handler, Config), Stack, Config); 973false(<<$a, $l, $s>>, Handler, Stack, Config) -> 974 incomplete(false, <<$a, $l, $s>>, Handler, Stack, Config); 975false(<<$a, $l>>, Handler, Stack, Config) -> 976 incomplete(false, <<$a, $l>>, Handler, Stack, Config); 977false(<<$a>>, Handler, Stack, Config) -> 978 incomplete(false, <<$a>>, Handler, Stack, Config); 979false(<<>>, Handler, Stack, Config) -> 980 incomplete(false, <<>>, Handler, Stack, Config); 981false(Bin, Handler, Stack, Config) -> 982 ?error(false, Bin, Handler, Stack, Config). 983 984 985null(<<$u, $l, $l, Rest/binary>>, Handler, Stack, Config) -> 986 maybe_done(Rest, handle_event({literal, null}, Handler, Config), Stack, Config); 987null(<<$u, $l>>, Handler, Stack, Config) -> 988 incomplete(null, <<$u, $l>>, Handler, Stack, Config); 989null(<<$u>>, Handler, Stack, Config) -> 990 incomplete(null, <<$u>>, Handler, Stack, Config); 991null(<<>>, Handler, Stack, Config) -> 992 incomplete(null, <<>>, Handler, Stack, Config); 993null(Bin, Handler, Stack, Config) -> 994 ?error(null, Bin, Handler, Stack, Config). 995 996 997comment(<<?newline, Rest/binary>>, Handler, Resume, [comment|Stack], Config) -> 998 resume(Rest, Resume, Handler, unused, Stack, Config); 999comment(<<?solidus, ?star, Rest/binary>>, Handler, Resume, Stack, Config) -> 1000 comment(Rest, Handler, Resume, [multicomment|Stack], Config); 1001comment(<<?solidus>>, Handler, Resume, [multicomment|_] = Stack, Config) -> 1002 incomplete(comment, <<?solidus>>, Handler, Resume, Stack, Config); 1003comment(<<?star, ?solidus, Rest/binary>>, Handler, Resume, [multicomment|Stack], Config) -> 1004 case Stack of 1005 [multicomment|_] -> comment(Rest, Handler, Resume, Stack, Config); 1006 _ -> resume(Rest, Resume, Handler, unused, Stack, Config) 1007 end; 1008comment(<<?star>>, Handler, Resume, [multicomment|_] = Stack, Config) -> 1009 incomplete(comment, <<?star>>, Handler, Resume, Stack, Config); 1010comment(<<_/utf8, Rest/binary>>, Handler, Resume, Stack, Config) -> 1011 comment(Rest, Handler, Resume, Stack, Config); 1012comment(<<_, Rest/binary>>, Handler, Resume, Stack, Config=#config{strict_utf8=false}) -> 1013 comment(Rest, Handler, Resume, Stack, Config); 1014comment(<<>>, Handler, done, [Comment], Config=#config{stream=false}) 1015 when Comment == comment; Comment == multicomment -> 1016 resume(<<>>, done, Handler, unused, [], Config); 1017comment(<<>>, Handler, Resume, Stack, Config) -> 1018 incomplete(comment, <<>>, Handler, Resume, Stack, Config); 1019comment(Bin, Handler, Resume, Stack, Config) -> 1020 ?error(comment, Bin, Handler, Resume, Stack, Config). 1021 1022 1023maybe_done(<<Rest/binary>>, Handler, [], Config) -> 1024 done(Rest, handle_event(end_json, Handler, Config), [], Config); 1025maybe_done(<<?space, Rest/binary>>, Handler, Stack, Config) -> 1026 maybe_done(Rest, Handler, Stack, Config); 1027maybe_done(<<?end_object, Rest/binary>>, Handler, [object|Stack], Config) -> 1028 maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config); 1029maybe_done(<<?end_array, Rest/binary>>, Handler, [array|Stack], Config) -> 1030 maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config); 1031maybe_done(<<?comma, Rest/binary>>, Handler, [object|Stack], Config) -> 1032 key(Rest, Handler, [key|Stack], Config); 1033maybe_done(<<?comma, Rest/binary>>, Handler, [array|_] = Stack, Config) -> 1034 value(Rest, Handler, Stack, Config); 1035maybe_done(<<?newline, Rest/binary>>, Handler, Stack, Config) -> 1036 maybe_done(Rest, Handler, Stack, Config); 1037maybe_done(<<?tab, Rest/binary>>, Handler, Stack, Config) -> 1038 maybe_done(Rest, Handler, Stack, Config); 1039maybe_done(<<?cr, Rest/binary>>, Handler, Stack, Config) -> 1040 maybe_done(Rest, Handler, Stack, Config); 1041maybe_done(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) -> 1042 ?error(maybe_done, <<?solidus, Rest/binary>>, Handler, Stack, Config); 1043maybe_done(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) -> 1044 comment(Rest, Handler, maybe_done, [comment|Stack], Config); 1045maybe_done(<<?solidus, ?star, Rest/binary>>, Handler, Stack, Config) -> 1046 comment(Rest, Handler, maybe_done, [multicomment|Stack], Config); 1047maybe_done(<<?solidus>>, Handler, Stack, Config) -> 1048 incomplete(maybe_done, <<?solidus>>, Handler, Stack, Config); 1049maybe_done(<<>>, Handler, Stack, Config) when length(Stack) > 0 -> 1050 incomplete(maybe_done, <<>>, Handler, Stack, Config); 1051maybe_done(Bin, Handler, Stack, Config) -> 1052 ?error(maybe_done, Bin, Handler, Stack, Config). 1053 1054 1055done(<<?space, Rest/binary>>, Handler, [], Config) -> 1056 done(Rest, Handler, [], Config); 1057done(<<?newline, Rest/binary>>, Handler, [], Config) -> 1058 done(Rest, Handler, [], Config); 1059done(<<?tab, Rest/binary>>, Handler, [], Config) -> 1060 done(Rest, Handler, [], Config); 1061done(<<?cr, Rest/binary>>, Handler, [], Config) -> 1062 done(Rest, Handler, [], Config); 1063done(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) -> 1064 ?error(done, <<?solidus, Rest/binary>>, Handler, Stack, Config); 1065done(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) -> 1066 comment(Rest, Handler, done, [comment|Stack], Config); 1067done(<<?solidus, ?star, Rest/binary>>, Handler, Stack, Config) -> 1068 comment(Rest, Handler, done, [multicomment|Stack], Config); 1069done(<<?solidus>>, Handler, Stack, Config) -> 1070 incomplete(done, <<?solidus>>, Handler, Stack, Config); 1071done(Bin, {_Handler, State}, _Stack, #config{return_tail=true}) -> 1072 {with_tail,State, Bin}; 1073done(<<>>, {Handler, State}, [], Config=#config{stream=true}) -> 1074 incomplete(done, <<>>, {Handler, State}, [], Config); 1075done(<<>>, {_Handler, State}, [], _Config) -> State; 1076done(Bin, {Handler, State}, _Stack, Config=#config{multi_term=true}) -> 1077 value(Bin, {Handler, Handler:reset(State)}, [], Config); 1078done(Bin, Handler, Stack, Config) -> ?error(done, Bin, Handler, Stack, Config). 1079 1080 1081 1082-ifdef(TEST). 1083-include_lib("eunit/include/eunit.hrl"). 1084 1085 1086json_to_bytes(JSON) -> json_to_bytes(JSON, []). 1087 1088json_to_bytes(<<>>, Acc) -> [<<>>] ++ lists:reverse(Acc); 1089json_to_bytes(<<X, Rest/binary>>, Acc) -> json_to_bytes(Rest, [<<X>>] ++ Acc). 1090 1091 1092decode(JSON) -> decode(JSON, []). 1093decode(JSON, Config) -> (decoder(jsx, [], Config))(JSON). 1094 1095 1096incremental_decode(JSON) -> incremental_decode(JSON, []). 1097incremental_decode(JSON, Config) -> 1098 Final = lists:foldl( 1099 fun(Byte, Decoder) -> {incomplete, F} = Decoder(Byte), F end, 1100 decoder(jsx, [], [stream] ++ Config), 1101 json_to_bytes(JSON) 1102 ), 1103 Final(end_stream). 1104 1105 1106%% all these numbers have different representation in erlang than in javascript and 1107%% do not roundtrip like most integers/floats 1108special_number_test_() -> 1109 Cases = [ 1110 % {title, test form, json, opt flags} 1111 {"-0", [{integer, 0}, end_json], <<"-0">>}, 1112 {"-0.0", [{float, 0.0}, end_json], <<"-0.0">>}, 1113 {"0e0", [{float, 0.0}, end_json], <<"0e0">>}, 1114 {"0e4", [{float, 0.0}, end_json], <<"0e4">>}, 1115 {"1e0", [{float, 1.0}, end_json], <<"1e0">>}, 1116 {"-1e0", [{float, -1.0}, end_json], <<"-1e0">>}, 1117 {"-0e0", [{float, -0.0}, end_json], <<"-0e0">>}, 1118 {"1e4", [{float, 1.0e4}, end_json], <<"1e4">>}, 1119 {"number terminated by whitespace", 1120 [start_array, {integer, 1}, end_array, end_json], 1121 <<"[ 1 ]">> 1122 }, 1123 {"number terminated by comma", 1124 [start_array, {integer, 1}, {integer, 1}, end_array, end_json], 1125 <<"[ 1, 1 ]">> 1126 }, 1127 {"number terminated by comma in object", 1128 [start_object, {key, <<"x">>}, {integer, 1}, {key, <<"y">>}, {integer, 1}, end_object, end_json], 1129 <<"{\"x\": 1, \"y\": 1}">> 1130 } 1131 ], 1132 [{Title, ?_assertEqual(Events, decode(JSON))} 1133 || {Title, Events, JSON} <- Cases 1134 ] ++ 1135 [{Title ++ " (incremental)", ?_assertEqual(Events, incremental_decode(JSON))} 1136 || {Title, Events, JSON} <- Cases 1137 ]. 1138 1139 1140comments_test_() -> 1141 Cases = [ 1142 % {title, test form, json, opt flags} 1143 {"preceeding // comment", 1144 [start_array, end_array, end_json], 1145 <<"// comment ", ?newline, "[]">> 1146 }, 1147 {"preceeding /**/ comment", 1148 [start_array, end_array, end_json], 1149 <<"/* comment */[]">> 1150 }, 1151 {"trailing // comment", 1152 [start_array, end_array, end_json], 1153 <<"[]// comment", ?newline>> 1154 }, 1155 {"trailing // comment (no newline)", 1156 [start_array, end_array, end_json], 1157 <<"[]// comment">> 1158 }, 1159 {"trailing /**/ comment", 1160 [start_array, end_array, end_json], 1161 <<"[] /* comment */">> 1162 }, 1163 {"// comment inside array", 1164 [start_array, end_array, end_json], 1165 <<"[ // comment", ?newline, "]">> 1166 }, 1167 {"/**/ comment inside array", 1168 [start_array, end_array, end_json], 1169 <<"[ /* comment */ ]">> 1170 }, 1171 {"// comment at beginning of array", 1172 [start_array, {literal, true}, end_array, end_json], 1173 <<"[ // comment", ?newline, "true", ?newline, "]">> 1174 }, 1175 {"/**/ comment at beginning of array", 1176 [start_array, {literal, true}, end_array, end_json], 1177 <<"[ /* comment */ true ]">> 1178 }, 1179 {"// comment at end of array", 1180 [start_array, {literal, true}, end_array, end_json], 1181 <<"[ true // comment", ?newline, "]">> 1182 }, 1183 {"/**/ comment at end of array", 1184 [start_array, {literal, true}, end_array, end_json], 1185 <<"[ true /* comment */ ]">> 1186 }, 1187 {"// comment midarray (post comma)", 1188 [start_array, {literal, true}, {literal, false}, end_array, end_json], 1189 <<"[ true, // comment", ?newline, "false ]">> 1190 }, 1191 {"/**/ comment midarray (post comma)", 1192 [start_array, {literal, true}, {literal, false}, end_array, end_json], 1193 <<"[ true, /* comment */ false ]">> 1194 }, 1195 {"// comment midarray (pre comma)", 1196 [start_array, {literal, true}, {literal, false}, end_array, end_json], 1197 <<"[ true// comment", ?newline, ", false ]">> 1198 }, 1199 {"/**/ comment midarray (pre comma)", 1200 [start_array, {literal, true}, {literal, false}, end_array, end_json], 1201 <<"[ true/* comment */, false ]">> 1202 }, 1203 {"// comment inside object", 1204 [start_object, end_object, end_json], 1205 <<"{ // comment", ?newline, "}">> 1206 }, 1207 {"/**/ comment inside object", 1208 [start_object, end_object, end_json], 1209 <<"{ /* comment */ }">> 1210 }, 1211 {"// comment at beginning of object", 1212 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1213 <<"{ // comment", ?newline, " \"key\": true", ?newline, "}">> 1214 }, 1215 {"/**/ comment at beginning of object", 1216 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1217 <<"{ /* comment */ \"key\": true }">> 1218 }, 1219 {"// comment at end of object", 1220 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1221 <<"{ \"key\": true // comment", ?newline, "}">> 1222 }, 1223 {"/**/ comment at end of object", 1224 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1225 <<"{ \"key\": true /* comment */ }">> 1226 }, 1227 {"// comment midobject (post comma)", 1228 [ 1229 start_object, 1230 {key, <<"x">>}, 1231 {literal, true}, 1232 {key, <<"y">>}, 1233 {literal, false}, 1234 end_object, 1235 end_json 1236 ], 1237 <<"{ \"x\": true, // comment", ?newline, "\"y\": false }">> 1238 }, 1239 {"/**/ comment midobject (post comma)", 1240 [ 1241 start_object, 1242 {key, <<"x">>}, 1243 {literal, true}, 1244 {key, <<"y">>}, 1245 {literal, false}, 1246 end_object, 1247 end_json 1248 ], 1249 <<"{ \"x\": true, /* comment */", ?newline, "\"y\": false }">> 1250 }, 1251 {"// comment midobject (pre comma)", 1252 [ 1253 start_object, 1254 {key, <<"x">>}, 1255 {literal, true}, 1256 {key, <<"y">>}, 1257 {literal, false}, 1258 end_object, 1259 end_json 1260 ], 1261 <<"{ \"x\": true// comment", ?newline, ", \"y\": false }">> 1262 }, 1263 {"/**/ comment midobject (pre comma)", 1264 [ 1265 start_object, 1266 {key, <<"x">>}, 1267 {literal, true}, 1268 {key, <<"y">>}, 1269 {literal, false}, 1270 end_object, 1271 end_json 1272 ], 1273 <<"{ \"x\": true/* comment */", ?newline, ", \"y\": false }">> 1274 }, 1275 {"// comment precolon", 1276 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1277 <<"{ \"key\" // comment", ?newline, ": true }">> 1278 }, 1279 {"/**/ comment precolon", 1280 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1281 <<"{ \"key\"/* comment */: true }">> 1282 }, 1283 {"// comment postcolon", 1284 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1285 <<"{ \"key\": // comment", ?newline, " true }">> 1286 }, 1287 {"/**/ comment postcolon", 1288 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1289 <<"{ \"key\":/* comment */ true }">> 1290 }, 1291 {"// comment terminating zero", 1292 [start_array, {integer, 0}, end_array, end_json], 1293 <<"[ 0// comment", ?newline, "]">> 1294 }, 1295 {"// comment terminating integer", 1296 [start_array, {integer, 1}, end_array, end_json], 1297 <<"[ 1// comment", ?newline, "]">> 1298 }, 1299 {"// comment terminating float", 1300 [start_array, {float, 1.0}, end_array, end_json], 1301 <<"[ 1.0// comment", ?newline, "]">> 1302 }, 1303 {"// comment terminating exp", 1304 [start_array, {float, 1.0e1}, end_array, end_json], 1305 <<"[ 1e1// comment", ?newline, "]">> 1306 }, 1307 {"/**/ comment terminating zero", 1308 [start_array, {integer, 0}, end_array, end_json], 1309 <<"[ 0/* comment */ ]">> 1310 }, 1311 {"/**/ comment terminating integer", 1312 [start_array, {integer, 1}, end_array, end_json], 1313 <<"[ 1/* comment */ ]">> 1314 }, 1315 {"/**/ comment terminating float", 1316 [start_array, {float, 1.0}, end_array, end_json], 1317 <<"[ 1.0/* comment */ ]">> 1318 }, 1319 {"/**/ comment terminating exp", 1320 [start_array, {float, 1.0e1}, end_array, end_json], 1321 <<"[ 1e1/* comment */ ]">> 1322 }, 1323 {"/**/ comment following /**/ comment", 1324 [start_array, {literal, true}, end_array, end_json], 1325 <<"[/* comment *//* comment */true]">> 1326 }, 1327 {"/**/ comment following // comment", 1328 [start_array, {literal, true}, end_array, end_json], 1329 <<"[// comment", ?newline, "/* comment */true]">> 1330 }, 1331 {"// comment following /**/ comment", 1332 [start_array, {literal, true}, end_array, end_json], 1333 <<"[/* comment */// comment", ?newline, "true]">> 1334 }, 1335 {"// comment following // comment", 1336 [start_array, {literal, true}, end_array, end_json], 1337 <<"[// comment", ?newline, "// comment", ?newline, "true]">> 1338 }, 1339 {"/**/ comment inside /**/ comment", 1340 [start_array, {literal, true}, end_array, end_json], 1341 <<"[ /* /* comment */ */ true ]">> 1342 }, 1343 {"/**/ comment with /", 1344 [start_array, {literal, true}, end_array, end_json], 1345 <<"[ /* / */ true ]">> 1346 }, 1347 {"/**/ comment with *", 1348 [start_array, {literal, true}, end_array, end_json], 1349 <<"[ /* * */ true ]">> 1350 }, 1351 {"// comment with badutf", 1352 [start_array, {literal, true}, end_array, end_json], 1353 <<"[ // comment ", 16#00c0, " ", ?newline, "true]">> 1354 }, 1355 {"/**/ comment with badutf", 1356 [start_array, {literal, true}, end_array, end_json], 1357 <<"[ /* comment ", 16#00c0, " */ true]">> 1358 }, 1359 {"/**/ comment with badutf preceeded by /", 1360 [start_array, {literal, true}, end_array, end_json], 1361 <<"[ /* comment /", 16#00c0, " */ true]">> 1362 } 1363 ], 1364 [{Title, ?_assertEqual(Events, decode(JSON))} 1365 || {Title, Events, JSON} <- Cases 1366 ] ++ 1367 [{Title ++ " (incremental)", ?_assertEqual(Events, incremental_decode(JSON))} 1368 || {Title, Events, JSON} <- Cases 1369 ] ++ 1370 % error when `{strict, [comments]}` is present 1371 [{Title, ?_assertError(badarg, decode(JSON, [{strict, [comments]}]))} 1372 || {Title, _Events, JSON} <- Cases 1373 ] ++ 1374 [{Title ++ " (incremental)", ?_assertError( 1375 badarg, 1376 incremental_decode(JSON, [{strict, [comments]}]) 1377 )} || {Title, _Events, JSON} <- Cases 1378 ]. 1379 1380 1381no_comments_test_() -> 1382 Cases = [ 1383 {"// comment with badutf", 1384 badarg, 1385 <<"[ // comment ", 16#00c0, " ", ?newline, "true]">>, 1386 [{strict, [utf8]}] 1387 }, 1388 {"/**/ comment with badutf", 1389 badarg, 1390 <<"[ /* comment ", 16#00c0, " */ true]">>, 1391 [{strict, [utf8]}] 1392 }, 1393 {"/**/ comment with badutf preceeded by /", 1394 badarg, 1395 <<"[ /* comment /", 16#00c0, " */ true]">>, 1396 [{strict, [utf8]}] 1397 } 1398 ], 1399 [{Title, ?_assertError(Error, decode(JSON, Config))} 1400 || {Title, Error, JSON, Config} <- Cases 1401 ] ++ 1402 [{Title ++ " (incremental)", ?_assertError(Error, incremental_decode(JSON, Config))} 1403 || {Title, Error, JSON, Config} <- Cases 1404 ]. 1405 1406 1407% doing the full unicode range takes foreverrrrrrr so just do boundaries 1408% excludes characters that may need escaping 1409codepoints() -> 1410 lists:seq(0, 32) ++ 1411 [32, 33] ++ 1412 lists:seq(35, 46) ++ 1413 lists:seq(48, 91) ++ 1414 lists:seq(93, 127) ++ 1415 [16#2027, 16#202a, 16#d7ff, 16#e000] ++ 1416 lists:seq(16#fdd0, 16#ffff) ++ 1417 [16#10000, 16#20000, 16#30000, 16#40000, 16#50000] ++ 1418 [16#60000, 16#70000, 16#80000, 16#90000, 16#a0000, 16#b0000] ++ 1419 [16#c0000, 16#d0000, 16#e0000, 16#f0000, 16#100000]. 1420 1421 1422surrogates() -> lists:seq(16#d800, 16#dfff). 1423 1424 1425%% erlang refuses to decode certain codepoints, so fake them all 1426to_fake_utf8(N) when N < 16#0080 -> <<34/utf8, N:8, 34/utf8>>; 1427to_fake_utf8(N) when N < 16#0800 -> 1428 <<0:5, Y:5, X:6>> = <<N:16>>, 1429 <<34/utf8, 2#110:3, Y:5, 2#10:2, X:6, 34/utf8>>; 1430to_fake_utf8(N) when N < 16#10000 -> 1431 <<Z:4, Y:6, X:6>> = <<N:16>>, 1432 <<34/utf8, 2#1110:4, Z:4, 2#10:2, Y:6, 2#10:2, X:6, 34/utf8>>; 1433to_fake_utf8(N) -> 1434 <<0:3, W:3, Z:6, Y:6, X:6>> = <<N:24>>, 1435 <<34/utf8, 2#11110:5, W:3, 2#10:2, Z:6, 2#10:2, Y:6, 2#10:2, X:6, 34/utf8>>. 1436 1437 1438clean_string_test_() -> 1439 Clean = codepoints(), 1440 Dirty = surrogates(), 1441 % clean codepoints 1442 [{"clean u+" ++ integer_to_list(Codepoint, 16), ?_assertEqual( 1443 [{string, <<Codepoint/utf8>>}, end_json], 1444 decode(<<34/utf8, Codepoint/utf8, 34/utf8>>) 1445 )} || Codepoint <- Clean 1446 ] ++ 1447 % bad codepoints replaced by u+FFFD 1448 [{"clean u+" ++ integer_to_list(Codepoint, 16), ?_assertEqual( 1449 [{string, <<16#fffd/utf8>>}, end_json], 1450 decode(to_fake_utf8(Codepoint)) 1451 )} || Codepoint <- Dirty 1452 ] ++ 1453 % bad codepoints that cause errors 1454 [{"dirty u+" ++ integer_to_list(Codepoint, 16), ?_assertError( 1455 badarg, 1456 decode(to_fake_utf8(Codepoint), [{strict, [utf8]}]) 1457 )} || Codepoint <- Dirty 1458 ]. 1459 1460 1461dirty_string_test_() -> 1462 Cases = [ 1463 {"dirty \\n", 1464 [start_array, {string, <<"\\n">>}, end_array, end_json], 1465 <<"[\"\\n\"]">>, 1466 [dirty_strings] 1467 }, 1468 {"dirty \\uwxyz", 1469 [start_array, {string, <<"\\uwxyz">>}, end_array, end_json], 1470 <<"[\"\\uwxyz\"]">>, 1471 [dirty_strings] 1472 }, 1473 {"dirty \\x23", 1474 [start_array, {string, <<"\\x23">>}, end_array, end_json], 1475 <<"[\"\\x23\"]">>, 1476 [dirty_strings] 1477 }, 1478 {"dirty 0", 1479 [start_array, {string, <<0>>}, end_array, end_json], 1480 <<"[\"", 0, "\"]">>, 1481 [dirty_strings] 1482 }, 1483 {"dirty 0\\\"0", 1484 [start_array, {string, <<0, ?rsolidus, ?doublequote, 0>>}, end_array, end_json], 1485 <<"[\"", 0, ?rsolidus, ?doublequote, 0, "\"]">>, 1486 [dirty_strings] 1487 }, 1488 {"dirty 0\\\\\"0", 1489 [start_array, {string, <<0, ?rsolidus, ?rsolidus, ?doublequote, 0>>}, end_array, end_json], 1490 <<"[\"", 0, ?rsolidus, ?rsolidus, ?doublequote, 0, "\"]">>, 1491 [dirty_strings] 1492 }, 1493 {"dirty 16#d800", 1494 [start_array, {string, <<237, 160, 128>>}, end_array, end_json], 1495 <<"[\"", 237, 160, 128, "\"]">>, 1496 [dirty_strings] 1497 }, 1498 {"dirty /", 1499 [start_array, {string, <<$/>>}, end_array, end_json], 1500 <<"[\"", $/, "\"]">>, 1501 [dirty_strings, escaped_forward_slashes] 1502 }, 1503 {"dirty <<194, 129>>", 1504 [start_array, {string, <<194, 129>>}, end_array, end_json], 1505 <<"[\"", 194, 129, "\"]">>, 1506 [dirty_strings] 1507 } 1508 ], 1509 [{Title, ?_assertEqual(Events, decode(JSON, Config))} 1510 || {Title, Events, JSON, Config} <- Cases 1511 ] ++ 1512 % ensure `dirty_strings` and `strict` interact properly 1513 [{Title, ?_assertEqual(Events, decode(JSON, Config ++ [strict]))} 1514 || {Title, Events, JSON, Config} <- Cases 1515 ] ++ 1516 [{Title ++ " (incremental)", ?_assertEqual(Events, incremental_decode(JSON, Config))} 1517 || {Title, Events, JSON, Config} <- Cases 1518 ]. 1519 1520 1521bad_utf8_test_() -> 1522 Cases = [ 1523 {"orphan continuation byte u+0080", <<16#fffd/utf8>>, <<16#0080>>}, 1524 {"orphan continuation byte u+00bf", <<16#fffd/utf8>>, <<16#00bf>>}, 1525 {"2 continuation bytes", 1526 binary:copy(<<16#fffd/utf8>>, 2), 1527 <<(binary:copy(<<16#0080>>, 2))/binary>> 1528 }, 1529 {"3 continuation bytes", 1530 binary:copy(<<16#fffd/utf8>>, 3), 1531 <<(binary:copy(<<16#0080>>, 3))/binary>> 1532 }, 1533 {"4 continuation bytes", 1534 binary:copy(<<16#fffd/utf8>>, 4), 1535 <<(binary:copy(<<16#0080>>, 4))/binary>> 1536 }, 1537 {"5 continuation bytes", 1538 binary:copy(<<16#fffd/utf8>>, 5), 1539 <<(binary:copy(<<16#0080>>, 5))/binary>> 1540 }, 1541 {"6 continuation bytes", 1542 binary:copy(<<16#fffd/utf8>>, 6), 1543 <<(binary:copy(<<16#0080>>, 6))/binary>> 1544 }, 1545 {"all continuation bytes", 1546 binary:copy(<<16#fffd/utf8>>, length(lists:seq(16#0080, 16#00bf))), 1547 <<(list_to_binary(lists:seq(16#0080, 16#00bf)))/binary>> 1548 }, 1549 {"lonely start byte", <<16#fffd/utf8>>, <<16#00c0>>}, 1550 {"lonely start bytes (2 byte)", 1551 <<16#fffd/utf8, 32, 16#fffd/utf8>>, 1552 <<16#00c0, 32, 16#00df>> 1553 }, 1554 {"lonely start bytes (3 byte)", 1555 <<16#fffd/utf8, 32, 16#fffd/utf8>>, 1556 <<16#00e0, 32, 16#00ef>> 1557 }, 1558 {"lonely start bytes (4 byte)", 1559 <<16#fffd/utf8, 32, 16#fffd/utf8>>, 1560 <<16#00f0, 32, 16#00f7>> 1561 }, 1562 {"missing continuation byte (3 byte)", <<16#fffd/utf8, 32>>, <<224, 160, 32>>}, 1563 {"missing continuation byte (4 byte missing one)", 1564 <<16#fffd/utf8, 32>>, 1565 <<240, 144, 128, 32>> 1566 }, 1567 {"missing continuation byte (4 byte missing two)", 1568 <<16#fffd/utf8, 32>>, 1569 <<240, 144, 32>> 1570 }, 1571 {"overlong encoding of u+002f (2 byte)", 1572 <<16#fffd/utf8, 32>>, 1573 <<16#c0, 16#af, 32>> 1574 }, 1575 {"overlong encoding of u+002f (3 byte)", 1576 <<16#fffd/utf8, 32>>, 1577 <<16#e0, 16#80, 16#af, 32>> 1578 }, 1579 {"overlong encoding of u+002f (4 byte)", 1580 <<16#fffd/utf8, 32>>, 1581 <<16#f0, 16#80, 16#80, 16#af, 32>> 1582 }, 1583 {"highest overlong 2 byte sequence", 1584 <<16#fffd/utf8, 32>>, 1585 <<16#c1, 16#bf, 32>> 1586 }, 1587 {"highest overlong 3 byte sequence", 1588 <<16#fffd/utf8, 32>>, 1589 <<16#e0, 16#9f, 16#bf, 32>> 1590 }, 1591 {"highest overlong 4 byte sequence", 1592 <<16#fffd/utf8, 32>>, 1593 <<16#f0, 16#8f, 16#bf, 16#bf, 32>> 1594 } 1595 ], 1596 [{Title, ?_assertError( 1597 badarg, 1598 decode(<<34, JSON/binary, 34>>, [{strict, [utf8]}]) 1599 )} || {Title, _, JSON} <- Cases 1600 ] ++ 1601 [{Title ++ " (incremental)", ?_assertError( 1602 badarg, 1603 incremental_decode(<<34, JSON/binary, 34>>, [{strict, [utf8]}]) 1604 )} || {Title, _, JSON} <- Cases 1605 ] ++ 1606 [{Title ++ " replaced", ?_assertEqual( 1607 [{string, Replacement}, end_json], 1608 decode(<<34, JSON/binary, 34>>) 1609 )} || {Title, Replacement, JSON} <- Cases 1610 ] ++ 1611 [{Title ++ " replaced (incremental)", ?_assertEqual( 1612 [{string, Replacement}, end_json], 1613 incremental_decode(<<34, JSON/binary, 34>>) 1614 )} || {Title, Replacement, JSON} <- Cases 1615 ]. 1616 1617 1618unescape_test_() -> 1619 Cases = [ 1620 {"unescape backspace", <<"\b">>, <<"\\b"/utf8>>}, 1621 {"unescape tab", <<"\t">>, <<"\\t"/utf8>>}, 1622 {"unescape newline", <<"\n">>, <<"\\n"/utf8>>}, 1623 {"unescape formfeed", <<"\f">>, <<"\\f"/utf8>>}, 1624 {"unescape carriage return", <<"\r">>, <<"\\r"/utf8>>}, 1625 {"unescape quote", <<"\"">>, <<"\\\""/utf8>>}, 1626 {"unescape solidus", <<"/">>, <<"\\/"/utf8>>}, 1627 {"unescape reverse solidus", <<"\\">>, <<"\\\\"/utf8>>}, 1628 {"unescape control", <<0>>, <<"\\u0000"/utf8>>}, 1629 {"unescape surrogate pair", <<16#10000/utf8>>, <<"\\ud800\\udc00"/utf8>>}, 1630 {"unescape surrogate pair", <<16#10000/utf8>>, <<"\\uD800\\uDC00"/utf8>>}, 1631 {"replace bad high surrogate", <<16#fffd/utf8>>, <<"\\udc00"/utf8>>}, 1632 {"replace bad high surrogate", <<16#fffd/utf8>>, <<"\\uDC00"/utf8>>}, 1633 {"replace naked high surrogate", 1634 <<16#fffd/utf8, "hello world">>, 1635 <<"\\ud800hello world"/utf8>> 1636 }, 1637 {"replace naked high surrogate", 1638 <<16#fffd/utf8, "hello world">>, 1639 <<"\\uD800hello world"/utf8>> 1640 }, 1641 {"replace naked low surrogate", 1642 <<16#fffd/utf8, "hello world">>, 1643 <<"\\udc00hello world"/utf8>> 1644 }, 1645 {"replace naked low surrogate", 1646 <<16#fffd/utf8, "hello world">>, 1647 <<"\\uDC00hello world"/utf8>> 1648 }, 1649 {"replace bad surrogate pair", <<16#fffd/utf8, 16#fffd/utf8>>, <<"\\ud800\\u0000">>}, 1650 {"replace bad surrogate pair", <<16#fffd/utf8, 16#fffd/utf8>>, <<"\\uD800\\u0000">>} 1651 ], 1652 [{Title, ?_assertEqual([{string, Escaped}, end_json], decode(<<34, JSON/binary, 34>>))} 1653 || {Title, Escaped, JSON} <- Cases 1654 ] ++ 1655 [{Title ++ " (incremental)", ?_assertEqual( 1656 [{string, Escaped}, end_json], 1657 incremental_decode(<<34, JSON/binary, 34>>) 1658 )} || {Title, Escaped, JSON} <- Cases 1659 ]. 1660 1661 1662bad_escaped_surrogate_test_() -> 1663 Cases = [ 1664 {"do not unescape bad high surrogate", <<"\\udc00">>}, 1665 {"do not unescape naked high surrogate", <<"\\ud800hello world">>}, 1666 {"do not unescape naked low surrogate", <<"\\udc00hello world">>}, 1667 {"do not unescape bad surrogate pair", <<"\\ud800\\u0000">>} 1668 ], 1669 [{Title, ?_assertError(badarg, decode(<<34, JSON/binary, 34>>, [{strict, [utf8]}]))} 1670 || {Title, JSON} <- Cases 1671 ]. 1672 1673 1674escape_test_() -> 1675 Cases = [ 1676 {"backspace", <<"\b">>, <<"\\b">>}, 1677 {"tab", <<"\t">>, <<"\\t">>}, 1678 {"newline", <<"\n">>, <<"\\n">>}, 1679 {"formfeed", <<"\f">>, <<"\\f">>}, 1680 {"carriage return", <<"\r">>, <<"\\r">>}, 1681 {"quote", <<"\"">>, <<"\\\"">>}, 1682 {"backslash", <<"\\">>, <<"\\\\">>}, 1683 {"control", <<0>>, <<"\\u0000">>} 1684 ], 1685 [{"escape " ++ Title, ?_assertEqual( 1686 [{string, Escaped}, end_json], 1687 decode(<<34, Escaped/binary, 34>>, [escaped_strings]) 1688 )} || {Title, _Unescaped, Escaped} <- Cases 1689 ] ++ 1690 [{"do not escape " ++ Title, ?_assertEqual( 1691 [{string, Unescaped}, end_json], 1692 decode(<<34, Escaped/binary, 34>>) 1693 )} || {Title, Unescaped, Escaped} <- Cases 1694 ]. 1695 1696 1697special_escape_test_() -> 1698 Cases = [ 1699 {"escape forward slash", <<"\\/">>, <<"/"/utf8>>, [escaped_forward_slashes]}, 1700 {"do not escape forward slash", <<"/">>, <<"/"/utf8>>, []}, 1701 {"escape jsonp", <<"\\u2028">>, <<16#2028/utf8>>, []}, 1702 {"do not escape jsonp", <<16#2028/utf8>>, <<16#2028/utf8>>, [unescaped_jsonp]} 1703 ], 1704 [{Title, ?_assertEqual( 1705 [{string, Expect}, end_json], 1706 decode(<<34, Raw/binary, 34>>, [escaped_strings] ++ Config) 1707 )} || {Title, Expect, Raw, Config} <- Cases 1708 ]. 1709 1710 1711uescape_test_() -> 1712 [ 1713 {"\"\\u0080\"", ?_assertEqual( 1714 [{string, <<"\\u0080">>}, end_json], 1715 decode(<<34, 128/utf8, 34>>, [uescape]) 1716 )}, 1717 {"\"\\u8ca8\\u5481\\u3002\\u0091\\u0091\"", ?_assertEqual( 1718 [{string, <<"\\u8ca8\\u5481\\u3002\\u0091\\u0091">>}, end_json], 1719 decode( 1720 <<34,232,178,168,229,146,129,227,128,130,194,145,194,145,34>>, 1721 [uescape] 1722 ) 1723 )}, 1724 {"\"\\ud834\\udd1e\"", ?_assertEqual( 1725 [{string, <<"\\ud834\\udd1e">>}, end_json], 1726 decode(<<34, 240, 157, 132, 158, 34>>, [uescape]) 1727 )}, 1728 {"\"\\ud83d\\ude0a\"", ?_assertEqual( 1729 [{string, <<"\\ud83d\\ude0a">>}, end_json], 1730 decode(<<34, 240, 159, 152, 138, 34>>, [uescape]) 1731 )} 1732 ]. 1733 1734 1735single_quoted_string_test_() -> 1736 Cases = [ 1737 {"single quoted string", [{string, <<"hello world">>}, end_json], <<39, "hello world", 39>>}, 1738 {"single quoted string with embedded double quotes", 1739 [{string, <<"quoth the raven, \"nevermore\"">>}, end_json], 1740 <<39, "quoth the raven, \"nevermore\"", 39>> 1741 }, 1742 {"escaped single quote", 1743 [{string, <<"quoth the raven, 'nevermore'">>}, end_json], 1744 <<39, "quoth the raven, \\'nevermore\\'", 39>> 1745 }, 1746 {"single quoted key", 1747 [start_object, 1748 {key, <<"key">>}, {string, <<"value">>}, 1749 {key, <<"another key">>}, {string, <<"another value">>}, 1750 end_object, end_json], 1751 <<"{'key':'value','another key':'another value'}">> 1752 } 1753 ], 1754 [{Title, ?_assertEqual(Expect, decode(Raw, []))} || {Title, Expect, Raw} <- Cases] ++ 1755 [{Title, ?_assertError( 1756 badarg, 1757 decode(Raw, [{strict, [single_quotes]}]) 1758 )} || {Title, _Expect, Raw} <- Cases 1759 ]. 1760 1761 1762embedded_single_quoted_string_test_() -> 1763 [ 1764 {"string with embedded single quotes", ?_assertEqual( 1765 [{string, <<"quoth the raven, 'nevermore'">>}, end_json], 1766 decode(<<34, "quoth the raven, 'nevermore'", 34>>, []) 1767 )}, 1768 {"string with embedded single quotes", ?_assertEqual( 1769 [{string, <<"quoth the raven, 'nevermore'">>}, end_json], 1770 decode(<<34, "quoth the raven, 'nevermore'", 34>>, [{strict, [single_quotes]}]) 1771 )} 1772 ]. 1773 1774 1775ignored_bad_escapes_test_() -> 1776 [ 1777 {"ignore unrecognized escape sequence", ?_assertEqual( 1778 [{string, <<"\\x25">>}, end_json], 1779 decode(<<"\"\\x25\"">>, []) 1780 )} 1781 ]. 1782 1783 1784bom_test_() -> 1785 [ 1786 {"bom", ?_assertEqual( 1787 [start_array, end_array, end_json], 1788 decode(<<16#ef, 16#bb, 16#bf, "[]"/utf8>>, []) 1789 )} 1790 ]. 1791 1792 1793trailing_comma_test_() -> 1794 [ 1795 {"trailing comma in object", ?_assertEqual( 1796 [start_object, {key, <<"key">>}, {literal, true}, end_object, end_json], 1797 decode(<<"{\"key\": true,}">>, []) 1798 )}, 1799 {"strict trailing comma in object", ?_assertError( 1800 badarg, 1801 decode(<<"{\"key\": true,}">>, [{strict, [trailing_commas]}]) 1802 )}, 1803 {"two trailing commas in object", ?_assertError( 1804 badarg, 1805 decode(<<"{\"key\": true,,}">>, []) 1806 )}, 1807 {"comma in empty object", ?_assertError( 1808 badarg, 1809 decode(<<"{,}">>, []) 1810 )}, 1811 {"trailing comma in list", ?_assertEqual( 1812 [start_array, {literal, true}, end_array, end_json], 1813 decode(<<"[true,]">>, []) 1814 )}, 1815 {"strict trailing comma in list", ?_assertError( 1816 badarg, 1817 decode(<<"[true,]">>, [{strict, [trailing_commas]}]) 1818 )}, 1819 {"two trailing commas in list", ?_assertError( 1820 badarg, 1821 decode(<<"[true,,]">>, []) 1822 )}, 1823 {"comma in empty list", ?_assertError( 1824 badarg, 1825 decode(<<"[,]">>, []) 1826 )} 1827 ]. 1828 1829 1830incomplete_test_() -> 1831 [ 1832 {"stream false", ?_assertError( 1833 badarg, 1834 decode(<<"{">>) 1835 )}, 1836 {"stream true", ?_assertMatch( 1837 {incomplete, _}, 1838 decode(<<"{">>, [stream]) 1839 )}, 1840 {"complete input", ?_assertMatch( 1841 {incomplete, _}, 1842 decode(<<"{}">>, [stream]) 1843 )} 1844 ]. 1845 1846 1847error_test_() -> 1848 Cases = [ 1849 {"maybe_bom error", <<16#ef, 0>>}, 1850 {"definitely_bom error", <<16#ef, 16#bb, 0>>}, 1851 {"object error", <<"{"/utf8, 0>>}, 1852 {"colon error", <<"{\"\""/utf8, 0>>}, 1853 {"key error", <<"{\"\":1,"/utf8, 0>>}, 1854 {"value error", <<0>>}, 1855 {"negative error", <<"-"/utf8, 0>>}, 1856 {"zero error", <<"0"/utf8, 0>>}, 1857 {"integer error", <<"1"/utf8, 0>>}, 1858 {"decimal error", <<"1.0"/utf8, 0>>}, 1859 {"e error", <<"1e"/utf8, 0>>}, 1860 {"ex error", <<"1e+"/utf8, 0>>}, 1861 {"exp error", <<"1e1"/utf8, 0>>}, 1862 {"exp error", <<"1.0e1"/utf8, 0>>}, 1863 {"exp error", <<"1.e"/utf8>>}, 1864 {"true error", <<"tru"/utf8, 0>>}, 1865 {"false error", <<"fals"/utf8, 0>>}, 1866 {"null error", <<"nul"/utf8, 0>>}, 1867 {"maybe_done error", <<"[[]"/utf8, 0>>}, 1868 {"done error", <<"[]"/utf8, 0>>} 1869 ], 1870 [{Title, ?_assertError(badarg, decode(State))} || {Title, State} <- Cases]. 1871 1872 1873custom_incomplete_handler_test_() -> 1874 [ 1875 {"custom incomplete handler", ?_assertError( 1876 incomplete, 1877 decode(<<>>, [{incomplete_handler, fun(_, _, _) -> erlang:error(incomplete) end}, stream]) 1878 )} 1879 ]. 1880 1881 1882return_tail_test_() -> 1883 [ 1884 {"return_tail with tail", ?_assertEqual( 1885 {with_tail,[{}],<<"3">>}, 1886 jsx:decode(<<"{} 3">>, [return_tail]) 1887 )}, 1888 {"return_tail without tail", ?_assertEqual( 1889 {with_tail,[{}],<<"">>}, 1890 jsx:decode(<<"{}">>, [return_tail]) 1891 )}, 1892 {"return_tail with trimmed whitespace", ?_assertEqual( 1893 {with_tail,[{}],<<"">>}, 1894 jsx:decode(<<"{} ">>, [return_tail]) 1895 )}, 1896 {"return_tail and streaming", ?_assertEqual( 1897 {with_tail,[{}],<<"3">>}, 1898 begin 1899 {incomplete, F} = jsx:decode(<<"{">>, [return_tail, stream]), 1900 F(<<"} 3">>) 1901 end 1902 )}, 1903 {"return_tail and streaming", ?_assertEqual( 1904 {with_tail,[{}],<<"">>}, 1905 begin 1906 %% In case of infinite stream of objects a user does not know 1907 %% when to call F(end_stream). 1908 %% So, return_tail overwrites conservative stream end. 1909 %% This means that we don't need to call end_stream explicitly. 1910 {incomplete, F} = jsx:decode(<<"{">>, [return_tail, stream]), 1911 F(<<"}">>) 1912 end 1913 )} 1914 ]. 1915 1916-endif. 1917