This is an automated email from the ASF dual-hosted git repository. nickva pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/couchdb-jiffy.git
commit 34d4b1ef518d8eb55880b02399daf3af996cb997 Author: Nick Vatamaniuc <[email protected]> AuthorDate: Sat Apr 11 21:25:45 2026 -0400 100% compliance with RFC 8259 Previously Jiffy was a tiny bit more linient and accepted numbers like 0.3e+ and that's not a valid JSON number, it turns out. --- c_src/decoder.c | 27 +++++++++++++++++++++++++++ test/jiffy_03_number_tests.erl | 16 +++++++++++++++- test/jiffy_22_json_test_suite_tests.erl | 25 +++++-------------------- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/c_src/decoder.c b/c_src/decoder.c index 861f32b..d934100 100644 --- a/c_src/decoder.c +++ b/c_src/decoder.c @@ -33,6 +33,7 @@ enum { nst_frac1, nst_frac, nst_esign, + nst_echeck, nst_edigit } JsonNumState; @@ -549,6 +550,9 @@ dec_number(Decoder* d, ERL_NIF_TERM* value) switch(p[idx]) { case '-': case '+': + state = nst_echeck; + idx++; + break; case '0': case '1': case '2': @@ -567,6 +571,28 @@ dec_number(Decoder* d, ERL_NIF_TERM* value) } break; + case nst_echeck: + switch(p[idx]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + state = nst_edigit; + while(idx < len && p[idx] >= '0' && p[idx] <= '9') { + idx++; + } + break; + default: + goto parse; + } + break; + case nst_edigit: switch(p[idx]) { case '0': @@ -601,6 +627,7 @@ parse: case nst_sign: case nst_frac1: case nst_esign: + case nst_echeck: return 0; default: break; diff --git a/test/jiffy_03_number_tests.erl b/test/jiffy_03_number_tests.erl index 56759ff..2a8fdbb 100644 --- a/test/jiffy_03_number_tests.erl +++ b/test/jiffy_03_number_tests.erl @@ -91,7 +91,11 @@ cases(ok) -> {<<"-10000000000">>, -10000000000}, %% Number parsing edge cases {<<"-0.0E1">>, -0.0, <<"0.0">>}, - {<<"1E-1">>, 1.0e-1, <<"0.1">>} + {<<"1E-1">>, 1.0e-1, <<"0.1">>}, + {<<"1e0">>, 1.0, <<"1.0">>}, + {<<"1e01">>, 10.0, <<"10.0">>}, + {<<"1e00001">>, 10.0, <<"10.0">>}, + {<<"1E001">>, 10.0, <<"10.0">>} ]; cases(error) -> @@ -106,6 +110,16 @@ cases(error) -> <<"1E">>, <<"1-E2">>, <<"2E +3">>, + <<"2e+">>, + <<"2e-">>, + <<"3E+">>, + <<"3E-">>, + <<"0.1e-">>, + <<"0.1e+">>, + <<"0.1E-">>, + <<"0.1E+">>, + <<"1e-e">>, + <<"1e+e">>, <<"1E3000">>, <<"0.1E30000">>, <<"1EA">> diff --git a/test/jiffy_22_json_test_suite_tests.erl b/test/jiffy_22_json_test_suite_tests.erl index 8a71ab1..d3d52d6 100644 --- a/test/jiffy_22_json_test_suite_tests.erl +++ b/test/jiffy_22_json_test_suite_tests.erl @@ -60,32 +60,17 @@ gen_whatever({Name, Json}) -> end}. -% Jiffy is linient here and we deviate from strict RFC 8259: -% - accept truncated exponents e.g. 0.3e+ is 0.3 for us so -% add an exception for it -% -known_deviations() -> - [ - "n_number_0.3e+", - "n_number_0_capital_E+", - "n_number_0e+", - "n_number_1.0e+", - "n_number_1.0e-" - ]. - - classify(Files) -> classify(Files, [], [], []). classify([], Y, N, I) -> {lists:reverse(Y), lists:reverse(N), lists:reverse(I)}; classify([{Name, _Json} = F | Rest], Y, N, I) -> - case {Name, lists:member(Name, known_deviations())} of - {_, true} -> classify(Rest, Y, N, [F | I]); - {"y_" ++ _, _} -> classify(Rest, [F | Y], N, I); - {"n_" ++ _, _} -> classify(Rest, Y, [F | N], I); - {"i_" ++ _, _} -> classify(Rest, Y, N, [F | I]); - _ -> classify(Rest, Y, N, I) + case Name of + "y_" ++ _ -> classify(Rest, [F | Y], N, I); + "n_" ++ _ -> classify(Rest, Y, [F | N], I); + "i_" ++ _ -> classify(Rest, Y, N, [F | I]); + _ -> classify(Rest, Y, N, I) end.
