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.
 
 

Reply via email to