Add std/json quirk_allow_final_comma
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index fe922b0..b615ecc 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -21320,9 +21320,17 @@
(((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
(((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
if (0 == (v_expect & 256)) {
- v_expect = 4098;
+ if (self->private_impl.f_quirk_enabled_allow_final_comma) {
+ v_expect = 4162;
+ } else {
+ v_expect = 4098;
+ }
} else {
- v_expect = 7858;
+ if (self->private_impl.f_quirk_enabled_allow_final_comma) {
+ v_expect = 8114;
+ } else {
+ v_expect = 7858;
+ }
}
goto label__outer__continue;
} else if (v_class == 3) {
diff --git a/std/json/decode_json.wuffs b/std/json/decode_json.wuffs
index 176fd09..566811d 100644
--- a/std/json/decode_json.wuffs
+++ b/std/json/decode_json.wuffs
@@ -832,9 +832,17 @@
// What's valid after a comma depends on whether or not we're
// in an array or an object.
if 0 == (expect & 0x0100) { // 0x0100 is (1 << CLASS_CLOSE_SQUARE_BRACKET).
- expect = 0x1002 // 0x1002 is EXPECT_STRING.
+ if this.quirk_enabled_allow_final_comma {
+ expect = 0x1042 // 0x1042 is EXPECT_STRING | EXPECT_CLOSE_CURLY_BRACE.
+ } else {
+ expect = 0x1002 // 0x1002 is EXPECT_STRING.
+ }
} else {
- expect = 0x1EB2 // 0x0EB2 is EXPECT_VALUE.
+ if this.quirk_enabled_allow_final_comma {
+ expect = 0x1FB2 // 0x0FB2 is EXPECT_VALUE | EXPECT_CLOSE_SQUARE_BRACKET.
+ } else {
+ expect = 0x1EB2 // 0x0EB2 is EXPECT_VALUE.
+ }
}
continue.outer
diff --git a/test/c/std/json.c b/test/c/std/json.c
index e345344..f1bfc1a 100644
--- a/test/c/std/json.c
+++ b/test/c/std/json.c
@@ -1330,6 +1330,74 @@
}
const char* //
+test_wuffs_json_decode_quirk_allow_final_comma() {
+ CHECK_FOCUS(__func__);
+
+ struct {
+ // want has 2 bytes, one for each possible q:
+ // - q&1 sets WUFFS_JSON__QUIRK_ALLOW_FINAL_COMMA.
+ // An 'X', '+' or '-' means that decoding should succeed (and consume the
+ // entire input), succeed (without consuming the entire input) or fail.
+ const char* want;
+ const char* str;
+ } test_cases[] = {
+ {.want = "-X", .str = "[0,]"},
+ {.want = "-X", .str = "[[], {},{\"k\":\"v\",\n}\n,\n]"},
+ {.want = "--", .str = "[,]"},
+ {.want = "--", .str = "{,}"},
+ };
+
+ int tc;
+ for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+ int q;
+ for (q = 0; q < 2; q++) {
+ wuffs_json__decoder dec;
+ CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+ &dec, sizeof dec, WUFFS_VERSION,
+ WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+ wuffs_json__decoder__set_quirk_enabled(
+ &dec, WUFFS_JSON__QUIRK_ALLOW_FINAL_COMMA, q & 1);
+
+ wuffs_base__token_buffer tok =
+ wuffs_base__make_token_buffer_writer(global_have_token_slice);
+ wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+ wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+ strlen(test_cases[tc].str)),
+ true);
+ const char* have =
+ wuffs_json__decoder__decode_tokens(&dec, &tok, &src).repr;
+ const char* want =
+ (test_cases[tc].want[q] != '-') ? NULL : wuffs_json__error__bad_input;
+ if (have != want) {
+ RETURN_FAIL("tc=%d, q=%d: decode_tokens: have \"%s\", want \"%s\"", tc,
+ q, have, want);
+ }
+
+ size_t total_length = 0;
+ while (tok.meta.ri < tok.meta.wi) {
+ total_length += wuffs_base__token__length(&tok.data.ptr[tok.meta.ri++]);
+ }
+ if (total_length != src.meta.ri) {
+ RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+ total_length, src.meta.ri);
+ }
+ if (test_cases[tc].want[q] == 'X') {
+ if (total_length != src.data.len) {
+ RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+ total_length, src.data.len);
+ }
+ } else if (test_cases[tc].want[q] == '+') {
+ if (total_length >= src.data.len) {
+ RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want < %zu", tc, q,
+ total_length, src.data.len);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+const char* //
test_wuffs_json_decode_quirk_allow_comment_etc() {
CHECK_FOCUS(__func__);
@@ -2046,6 +2114,7 @@
test_wuffs_json_decode_quirk_allow_backslash_etc,
test_wuffs_json_decode_quirk_allow_backslash_x,
test_wuffs_json_decode_quirk_allow_comment_etc,
+ test_wuffs_json_decode_quirk_allow_final_comma,
test_wuffs_json_decode_quirk_allow_leading_etc,
test_wuffs_json_decode_quirk_allow_trailing_etc,
test_wuffs_json_decode_quirk_replace_invalid_utf_8,