Add std/json quirk_allow_leading_etc
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 247cba6..aa6a9a2 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -5944,6 +5944,11 @@
// ---------------- Public Function Prototypes
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
+wuffs_json__decoder__set_quirk_enabled(wuffs_json__decoder* self,
+ uint32_t a_quirk,
+ bool a_enabled);
+
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_json__decoder__decode_tokens(wuffs_json__decoder* self,
wuffs_base__token_buffer* a_dst,
@@ -5972,9 +5977,28 @@
wuffs_base__vtable vtable_for__wuffs_base__token_decoder;
wuffs_base__vtable null_vtable;
+ bool f_quirk_enabled_allow_backslash_a;
+ bool f_quirk_enabled_allow_backslash_capital_u;
+ bool f_quirk_enabled_allow_backslash_e;
+ bool f_quirk_enabled_allow_backslash_question_mark;
+ bool f_quirk_enabled_allow_backslash_single_quote;
+ bool f_quirk_enabled_allow_backslash_v;
+ bool f_quirk_enabled_allow_backslash_x;
+ bool f_quirk_enabled_allow_backslash_zero;
+ bool f_quirk_enabled_allow_comment_block;
+ bool f_quirk_enabled_allow_comment_line;
+ bool f_quirk_enabled_allow_final_comma;
+ bool f_quirk_enabled_allow_inf_nan_numbers;
+ bool f_quirk_enabled_allow_leading_ascii_record_separator;
+ bool f_quirk_enabled_allow_leading_unicode_byte_order_mark;
+ bool f_quirk_enabled_allow_trailing_new_line;
+ bool f_quirk_enabled_replace_invalid_utf_8;
+ bool f_allow_leading_ars;
+ bool f_allow_leading_ubom;
bool f_end_of_data;
uint32_t p_decode_tokens[1];
+ uint32_t p_decode_leading[1];
} private_impl;
struct {
@@ -6029,6 +6053,11 @@
return (wuffs_base__token_decoder*)this;
}
+ inline wuffs_base__empty_struct //
+ set_quirk_enabled(uint32_t a_quirk, bool a_enabled) {
+ return wuffs_json__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
+ }
+
inline wuffs_base__status //
decode_tokens(wuffs_base__token_buffer* a_dst, wuffs_base__io_buffer* a_src) {
return wuffs_json__decoder__decode_tokens(this, a_dst, a_src);
@@ -20262,6 +20291,11 @@
wuffs_base__io_buffer* a_src,
uint32_t a_n);
+static wuffs_base__status //
+wuffs_json__decoder__decode_leading(wuffs_json__decoder* self,
+ wuffs_base__token_buffer* a_dst,
+ wuffs_base__io_buffer* a_src);
+
// ---------------- VTables
const wuffs_base__token_decoder__func_ptrs
@@ -20329,6 +20363,58 @@
// ---------------- Function Implementations
+// -------- func json.decoder.set_quirk_enabled
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
+wuffs_json__decoder__set_quirk_enabled(wuffs_json__decoder* self,
+ uint32_t a_quirk,
+ bool a_enabled) {
+ if (!self) {
+ return wuffs_base__make_empty_struct();
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_empty_struct();
+ }
+
+ if (a_quirk == 1225364480) {
+ self->private_impl.f_quirk_enabled_allow_backslash_a = a_enabled;
+ } else if (a_quirk == 1225364481) {
+ self->private_impl.f_quirk_enabled_allow_backslash_capital_u = a_enabled;
+ } else if (a_quirk == 1225364482) {
+ self->private_impl.f_quirk_enabled_allow_backslash_e = a_enabled;
+ } else if (a_quirk == 1225364483) {
+ self->private_impl.f_quirk_enabled_allow_backslash_question_mark =
+ a_enabled;
+ } else if (a_quirk == 1225364484) {
+ self->private_impl.f_quirk_enabled_allow_backslash_single_quote = a_enabled;
+ } else if (a_quirk == 1225364485) {
+ self->private_impl.f_quirk_enabled_allow_backslash_v = a_enabled;
+ } else if (a_quirk == 1225364486) {
+ self->private_impl.f_quirk_enabled_allow_backslash_x = a_enabled;
+ } else if (a_quirk == 1225364487) {
+ self->private_impl.f_quirk_enabled_allow_backslash_zero = a_enabled;
+ } else if (a_quirk == 1225364488) {
+ self->private_impl.f_quirk_enabled_allow_comment_block = a_enabled;
+ } else if (a_quirk == 1225364489) {
+ self->private_impl.f_quirk_enabled_allow_comment_line = a_enabled;
+ } else if (a_quirk == 1225364490) {
+ self->private_impl.f_quirk_enabled_allow_final_comma = a_enabled;
+ } else if (a_quirk == 1225364491) {
+ self->private_impl.f_quirk_enabled_allow_inf_nan_numbers = a_enabled;
+ } else if (a_quirk == 1225364492) {
+ self->private_impl.f_quirk_enabled_allow_leading_ascii_record_separator =
+ a_enabled;
+ } else if (a_quirk == 1225364493) {
+ self->private_impl.f_quirk_enabled_allow_leading_unicode_byte_order_mark =
+ a_enabled;
+ } else if (a_quirk == 1225364494) {
+ self->private_impl.f_quirk_enabled_allow_trailing_new_line = a_enabled;
+ } else if (a_quirk == 1225364495) {
+ self->private_impl.f_quirk_enabled_replace_invalid_utf_8 = a_enabled;
+ }
+ return wuffs_base__make_empty_struct();
+}
+
// -------- func json.decoder.decode_tokens
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
@@ -20418,13 +20504,35 @@
status = wuffs_base__make_status(wuffs_base__note__end_of_data);
goto ok;
}
+ if (self->private_impl
+ .f_quirk_enabled_allow_leading_ascii_record_separator ||
+ self->private_impl
+ .f_quirk_enabled_allow_leading_unicode_byte_order_mark) {
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+ }
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
+ status = wuffs_json__decoder__decode_leading(self, a_dst, a_src);
+ if (a_dst) {
+ iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
+ }
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
+ if (status.repr) {
+ goto suspend;
+ }
+ }
v_expect = 3762;
label__outer__continue:;
while (true) {
while (true) {
if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
status = wuffs_base__make_status(wuffs_base__suspension__short_write);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
goto label__outer__continue;
}
v_whitespace_length = 0;
@@ -20445,7 +20553,7 @@
}
status =
wuffs_base__make_status(wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
v_whitespace_length = 0;
goto label__outer__continue;
}
@@ -20490,7 +20598,7 @@
if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
status =
wuffs_base__make_status(wuffs_base__suspension__short_write);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
goto label__string_loop_outer__continue;
}
v_string_length = 0;
@@ -20513,7 +20621,7 @@
}
status =
wuffs_base__make_status(wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
v_string_length = 0;
goto label__string_loop_outer__continue;
}
@@ -20587,7 +20695,7 @@
}
status = wuffs_base__make_status(
wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
v_string_length = 0;
v_char = 0;
goto label__string_loop_outer__continue;
@@ -20613,7 +20721,7 @@
}
status = wuffs_base__make_status(
wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
v_string_length = 0;
v_char = 0;
goto label__string_loop_outer__continue;
@@ -20659,7 +20767,7 @@
}
status = wuffs_base__make_status(
wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
v_string_length = 0;
v_uni4_value = 0;
v_char = 0;
@@ -20745,7 +20853,7 @@
}
status = wuffs_base__make_status(
wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
v_string_length = 0;
v_char = 0;
goto label__string_loop_outer__continue;
@@ -20787,7 +20895,7 @@
}
status = wuffs_base__make_status(
wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
v_string_length = 0;
v_char = 0;
goto label__string_loop_outer__continue;
@@ -20834,7 +20942,7 @@
}
status = wuffs_base__make_status(
wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
v_string_length = 0;
v_char = 0;
goto label__string_loop_outer__continue;
@@ -20892,13 +21000,13 @@
}
status =
wuffs_base__make_status(wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12);
goto label__1__continue;
}
if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
status =
wuffs_base__make_status(wuffs_base__suspension__short_write);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(13);
goto label__1__continue;
}
(iop_a_src += 1, wuffs_base__make_empty_struct());
@@ -20976,11 +21084,11 @@
} else {
status =
wuffs_base__make_status(wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(13);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14);
while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
status = wuffs_base__make_status(
wuffs_base__suspension__short_write);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15);
}
}
}
@@ -21114,7 +21222,7 @@
} else if (v_match == 1) {
status =
wuffs_base__make_status(wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(16);
goto label__outer__continue;
}
} else if (v_class == 10) {
@@ -21135,7 +21243,7 @@
} else if (v_match == 1) {
status =
wuffs_base__make_status(wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(16);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17);
goto label__outer__continue;
}
} else if (v_class == 11) {
@@ -21156,7 +21264,7 @@
} else if (v_match == 1) {
status =
wuffs_base__make_status(wuffs_base__suspension__short_read);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(18);
goto label__outer__continue;
}
}
@@ -21387,6 +21495,122 @@
return v_n;
}
+// -------- func json.decoder.decode_leading
+
+static wuffs_base__status //
+wuffs_json__decoder__decode_leading(wuffs_json__decoder* self,
+ wuffs_base__token_buffer* a_dst,
+ wuffs_base__io_buffer* a_src) {
+ wuffs_base__status status = wuffs_base__make_status(NULL);
+
+ uint8_t v_c = 0;
+ uint32_t v_u = 0;
+
+ wuffs_base__token* iop_a_dst = NULL;
+ wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_dst) {
+ io0_a_dst = a_dst->data.ptr;
+ io1_a_dst = io0_a_dst + a_dst->meta.wi;
+ iop_a_dst = io1_a_dst;
+ io2_a_dst = io0_a_dst + a_dst->data.len;
+ if (a_dst->meta.closed) {
+ io2_a_dst = iop_a_dst;
+ }
+ }
+ uint8_t* iop_a_src = NULL;
+ uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
+ }
+
+ uint32_t coro_susp_point = self->private_impl.p_decode_leading[0];
+ if (coro_susp_point) {
+ }
+ switch (coro_susp_point) {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+ self->private_impl.f_allow_leading_ars =
+ self->private_impl.f_quirk_enabled_allow_leading_ascii_record_separator;
+ self->private_impl.f_allow_leading_ubom =
+ self->private_impl
+ .f_quirk_enabled_allow_leading_unicode_byte_order_mark;
+ label__0__continue:;
+ while (self->private_impl.f_allow_leading_ars ||
+ self->private_impl.f_allow_leading_ubom) {
+ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+ goto label__0__continue;
+ }
+ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+ if (a_src && a_src->meta.closed) {
+ goto label__0__break;
+ }
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
+ goto label__0__continue;
+ }
+ v_c = wuffs_base__load_u8be__no_bounds_check(iop_a_src);
+ if ((v_c == 30) && self->private_impl.f_allow_leading_ars) {
+ self->private_impl.f_allow_leading_ars = false;
+ (iop_a_src += 1, wuffs_base__make_empty_struct());
+ *iop_a_dst++ = wuffs_base__make_token(
+ (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+ (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+ goto label__0__continue;
+ } else if ((v_c == 239) && self->private_impl.f_allow_leading_ubom) {
+ if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
+ if (a_src && a_src->meta.closed) {
+ goto label__0__break;
+ }
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
+ goto label__0__continue;
+ }
+ v_u = ((uint32_t)(wuffs_base__load_u24le__no_bounds_check(iop_a_src)));
+ if (v_u == 12565487) {
+ self->private_impl.f_allow_leading_ubom = false;
+ (iop_a_src += 3, wuffs_base__make_empty_struct());
+ *iop_a_dst++ = wuffs_base__make_token(
+ (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+ (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+ goto label__0__continue;
+ }
+ }
+ goto label__0__break;
+ }
+ label__0__break:;
+
+ goto ok;
+ ok:
+ self->private_impl.p_decode_leading[0] = 0;
+ goto exit;
+ }
+
+ goto suspend;
+suspend:
+ self->private_impl.p_decode_leading[0] =
+ wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+
+ goto exit;
+exit:
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+ }
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+
+ return status;
+}
+
#endif // !defined(WUFFS_CONFIG__MODULES) ||
// defined(WUFFS_CONFIG__MODULE__JSON)
diff --git a/std/json/decode_json.wuffs b/std/json/decode_json.wuffs
index 1bd524a..44d1678 100644
--- a/std/json/decode_json.wuffs
+++ b/std/json/decode_json.wuffs
@@ -13,6 +13,26 @@
// limitations under the License.
pub struct decoder? implements base.token_decoder(
+ quirk_enabled_allow_backslash_a : base.bool,
+ quirk_enabled_allow_backslash_capital_u : base.bool,
+ quirk_enabled_allow_backslash_e : base.bool,
+ quirk_enabled_allow_backslash_question_mark : base.bool,
+ quirk_enabled_allow_backslash_single_quote : base.bool,
+ quirk_enabled_allow_backslash_v : base.bool,
+ quirk_enabled_allow_backslash_x : base.bool,
+ quirk_enabled_allow_backslash_zero : base.bool,
+ quirk_enabled_allow_comment_block : base.bool,
+ quirk_enabled_allow_comment_line : base.bool,
+ quirk_enabled_allow_final_comma : base.bool,
+ quirk_enabled_allow_inf_nan_numbers : base.bool,
+ quirk_enabled_allow_leading_ascii_record_separator : base.bool,
+ quirk_enabled_allow_leading_unicode_byte_order_mark : base.bool,
+ quirk_enabled_allow_trailing_new_line : base.bool,
+ quirk_enabled_replace_invalid_utf_8 : base.bool,
+
+ allow_leading_ars : base.bool,
+ allow_leading_ubom : base.bool,
+
end_of_data : base.bool,
)(
// stack is conceptually an array of bits, implemented as an array of u32.
@@ -46,6 +66,42 @@
stack : array[1024 / 32] base.u32,
)
+pub func decoder.set_quirk_enabled!(quirk: base.u32, enabled: base.bool) {
+ if args.quirk == quirk_allow_backslash_a {
+ this.quirk_enabled_allow_backslash_a = args.enabled
+ } else if args.quirk == quirk_allow_backslash_capital_u {
+ this.quirk_enabled_allow_backslash_capital_u = args.enabled
+ } else if args.quirk == quirk_allow_backslash_e {
+ this.quirk_enabled_allow_backslash_e = args.enabled
+ } else if args.quirk == quirk_allow_backslash_question_mark {
+ this.quirk_enabled_allow_backslash_question_mark = args.enabled
+ } else if args.quirk == quirk_allow_backslash_single_quote {
+ this.quirk_enabled_allow_backslash_single_quote = args.enabled
+ } else if args.quirk == quirk_allow_backslash_v {
+ this.quirk_enabled_allow_backslash_v = args.enabled
+ } else if args.quirk == quirk_allow_backslash_x {
+ this.quirk_enabled_allow_backslash_x = args.enabled
+ } else if args.quirk == quirk_allow_backslash_zero {
+ this.quirk_enabled_allow_backslash_zero = args.enabled
+ } else if args.quirk == quirk_allow_comment_block {
+ this.quirk_enabled_allow_comment_block = args.enabled
+ } else if args.quirk == quirk_allow_comment_line {
+ this.quirk_enabled_allow_comment_line = args.enabled
+ } else if args.quirk == quirk_allow_final_comma {
+ this.quirk_enabled_allow_final_comma = args.enabled
+ } else if args.quirk == quirk_allow_inf_nan_numbers {
+ this.quirk_enabled_allow_inf_nan_numbers = args.enabled
+ } else if args.quirk == quirk_allow_leading_ascii_record_separator {
+ this.quirk_enabled_allow_leading_ascii_record_separator = args.enabled
+ } else if args.quirk == quirk_allow_leading_unicode_byte_order_mark {
+ this.quirk_enabled_allow_leading_unicode_byte_order_mark = args.enabled
+ } else if args.quirk == quirk_allow_trailing_new_line {
+ this.quirk_enabled_allow_trailing_new_line = args.enabled
+ } else if args.quirk == quirk_replace_invalid_utf_8 {
+ this.quirk_enabled_replace_invalid_utf_8 = args.enabled
+ }
+}
+
pub func decoder.decode_tokens?(dst: base.token_writer, src: base.io_reader) {
var vminor : base.u32[..= 0xFF_FFFF]
var number_length : base.u32[..= 0x3FF]
@@ -82,6 +138,11 @@
return base."@end of data"
}
+ if this.quirk_enabled_allow_leading_ascii_record_separator or
+ this.quirk_enabled_allow_leading_unicode_byte_order_mark {
+ this.decode_leading?(dst: args.dst, src: args.src)
+ }
+
expect = 0x0EB2 // EXPECT_VALUE
while.outer true {
@@ -1017,3 +1078,49 @@
}
return n
}
+
+pri func decoder.decode_leading?(dst: base.token_writer, src: base.io_reader) {
+ var c : base.u8
+ var u : base.u32
+
+ this.allow_leading_ars = this.quirk_enabled_allow_leading_ascii_record_separator
+ this.allow_leading_ubom = this.quirk_enabled_allow_leading_unicode_byte_order_mark
+ while this.allow_leading_ars or this.allow_leading_ubom {
+ if args.dst.available() <= 0 {
+ yield? base."$short write"
+ continue
+ }
+ if args.src.available() <= 0 {
+ if args.src.is_closed() {
+ break
+ }
+ yield? base."$short read"
+ continue
+ }
+ c = args.src.peek_u8()
+ if (c == 0x1E) and this.allow_leading_ars {
+ this.allow_leading_ars = false
+ args.src.skip32_fast!(actual: 1, worst_case: 1)
+ args.dst.write_fast_token!(
+ value_major: 0, value_minor: 0, link: 0x0, length: 1)
+ continue
+ } else if (c == 0xEF) and this.allow_leading_ubom {
+ if args.src.available() < 3 {
+ if args.src.is_closed() {
+ break
+ }
+ yield? base."$short read"
+ continue
+ }
+ u = args.src.peek_u24le_as_u32()
+ if u == 0xBF_BBEF {
+ this.allow_leading_ubom = false
+ args.src.skip32_fast!(actual: 3, worst_case: 3)
+ args.dst.write_fast_token!(
+ value_major: 0, value_minor: 0, link: 0x0, length: 3)
+ continue
+ }
+ }
+ break
+ }
+}
diff --git a/test/c/std/json.c b/test/c/std/json.c
index cdb91ca..2c1d712 100644
--- a/test/c/std/json.c
+++ b/test/c/std/json.c
@@ -1106,6 +1106,72 @@
}
const char* //
+test_wuffs_json_decode_quirk_allow_leading_etc() {
+ CHECK_FOCUS(__func__);
+
+ struct {
+ // want has 4 bytes, one for each possible q:
+ // - q&1 sets WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR.
+ // - q&2 sets WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK.
+ // A '+' or '-' means that decoding should succeed or fail.
+ const char* want;
+ const char* str;
+ } test_cases[] = {
+ {.want = "-+-+", .str = "\x1Etrue"},
+ {.want = "--++", .str = "\xEF\xBB\xBFtrue"},
+ {.want = "---+", .str = "\x1E\xEF\xBB\xBFtrue"},
+ {.want = "---+", .str = "\xEF\xBB\xBF\x1Etrue"},
+ {.want = "----", .str = " \x1Etrue"},
+ {.want = "----", .str = "\x1E \xEF\xBB\xBFtrue"},
+ {.want = "----", .str = "\x1E\x1Etrue"},
+ {.want = "----", .str = "\xEF\xBB"},
+ {.want = "----", .str = "\xEF\xBB\xBF"},
+ {.want = "----", .str = "\xEF\xBB\xBF$"},
+ {.want = "----", .str = "\xEFtrue"},
+ };
+
+ int tc;
+ for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+ int q;
+ for (q = 0; q < 4; 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_LEADING_ASCII_RECORD_SEPARATOR, q & 1);
+ wuffs_json__decoder__set_quirk_enabled(
+ &dec, WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK, q & 2);
+
+ 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);
+ }
+ }
+ }
+ return NULL;
+}
+
+const char* //
test_wuffs_json_decode_unicode4_escapes() {
CHECK_FOCUS(__func__);
@@ -1453,13 +1519,14 @@
test_strconv_parse_number_u64, //
test_strconv_utf_8_next, //
- test_wuffs_json_decode_end_of_data, //
- test_wuffs_json_decode_interface, //
- test_wuffs_json_decode_long_numbers, //
- test_wuffs_json_decode_prior_valid_utf_8, //
- test_wuffs_json_decode_src_io_buffer_length, //
- test_wuffs_json_decode_string, //
- test_wuffs_json_decode_unicode4_escapes, //
+ test_wuffs_json_decode_end_of_data, //
+ test_wuffs_json_decode_interface, //
+ test_wuffs_json_decode_long_numbers, //
+ test_wuffs_json_decode_prior_valid_utf_8, //
+ test_wuffs_json_decode_quirk_allow_leading_etc, //
+ test_wuffs_json_decode_src_io_buffer_length, //
+ test_wuffs_json_decode_string, //
+ test_wuffs_json_decode_unicode4_escapes, //
#ifdef WUFFS_MIMIC