Add std/cbor
diff --git a/example/jsonptr/jsonptr.cc b/example/jsonptr/jsonptr.cc
index b476875..b5f86b6 100644
--- a/example/jsonptr/jsonptr.cc
+++ b/example/jsonptr/jsonptr.cc
@@ -121,6 +121,7 @@
// code simply isn't compiled.
#define WUFFS_CONFIG__MODULES
#define WUFFS_CONFIG__MODULE__BASE
+#define WUFFS_CONFIG__MODULE__CBOR
#define WUFFS_CONFIG__MODULE__JSON
// If building this program in an environment that doesn't easily accommodate
@@ -152,6 +153,7 @@
"Flags:\n"
" -c -compact-output\n"
" -d=NUM -max-output-depth=NUM\n"
+ " -i=FMT -input-format={json,cbor}\n"
" -o=FMT -output-format={json,cbor}\n"
" -q=STR -query=STR\n"
" -s=NUM -spaces=NUM\n"
@@ -316,7 +318,9 @@
uint32_t g_suppress_write_dst;
bool g_wrote_to_dst;
-wuffs_json__decoder g_dec;
+wuffs_cbor__decoder g_cbor_decoder;
+wuffs_json__decoder g_json_decoder;
+wuffs_base__token_decoder* g_dec;
// cbor_output_string_array is a 4 KiB buffer. For -output-format=cbor, strings
// whose length are 4096 or less are written as a single definite-length
@@ -597,6 +601,7 @@
bool compact_output;
bool fail_if_unsandboxed;
+ file_format input_format;
bool input_json_extra_comma;
uint32_t max_output_depth;
file_format output_format;
@@ -656,6 +661,14 @@
g_flags.fail_if_unsandboxed = true;
continue;
}
+ if (!strcmp(arg, "i=cbor") || !strcmp(arg, "input-format=cbor")) {
+ g_flags.input_format = file_format::cbor;
+ continue;
+ }
+ if (!strcmp(arg, "i=json") || !strcmp(arg, "input-format=json")) {
+ g_flags.input_format = file_format::json;
+ continue;
+ }
if (!strcmp(arg, "input-json-extra-comma")) {
g_flags.input_json_extra_comma = true;
continue;
@@ -747,18 +760,27 @@
g_suppress_write_dst = g_query.next_fragment() ? 1 : 0;
g_wrote_to_dst = false;
- TRY(g_dec.initialize(sizeof__wuffs_json__decoder(), WUFFS_VERSION, 0)
- .message());
+ if (g_flags.input_format == file_format::json) {
+ TRY(g_json_decoder
+ .initialize(sizeof__wuffs_json__decoder(), WUFFS_VERSION, 0)
+ .message());
+ g_dec = g_json_decoder.upcast_as__wuffs_base__token_decoder();
+ } else {
+ TRY(g_cbor_decoder
+ .initialize(sizeof__wuffs_cbor__decoder(), WUFFS_VERSION, 0)
+ .message());
+ g_dec = g_cbor_decoder.upcast_as__wuffs_base__token_decoder();
+ }
if (g_flags.input_json_extra_comma) {
- g_dec.set_quirk_enabled(WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA, true);
+ g_dec->set_quirk_enabled(WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA, true);
}
// Consume an optional whitespace trailer. This isn't part of the JSON spec,
// but it works better with line oriented Unix tools (such as "echo 123 |
// jsonptr" where it's "echo", not "echo -n") or hand-edited JSON files which
// can accidentally contain trailing whitespace.
- g_dec.set_quirk_enabled(WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE, true);
+ g_dec->set_quirk_enabled(WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE, true);
return nullptr;
}
@@ -937,11 +959,48 @@
const char* //
write_number(uint64_t vbd, uint8_t* ptr, size_t len) {
- if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT) {
- if (g_flags.output_format == file_format::json) {
+ if (g_flags.output_format == file_format::json) {
+ if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT) {
return write_dst(ptr, len);
+ } else if ((vbd &
+ WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED) &&
+ (vbd &
+ WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN)) {
+ if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE) {
+ if (len == 0) {
+ goto fail;
+ }
+ ptr++;
+ len--;
+ }
+ uint64_t u;
+ switch (len) {
+ case 1:
+ u = wuffs_base__load_u8__no_bounds_check(ptr);
+ break;
+ case 2:
+ u = wuffs_base__load_u16be__no_bounds_check(ptr);
+ break;
+ case 4:
+ u = wuffs_base__load_u32be__no_bounds_check(ptr);
+ break;
+ case 8:
+ u = wuffs_base__load_u64be__no_bounds_check(ptr);
+ break;
+ default:
+ goto fail;
+ }
+ uint8_t buf[WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL];
+ size_t n = wuffs_base__render_number_u64(
+ wuffs_base__make_slice_u8(&buf[0], sizeof buf), u,
+ WUFFS_BASE__RENDER_NUMBER_XXX__DEFAULT_OPTIONS);
+ return write_dst(&buf[0], n);
}
+ // From here on, (g_flags.output_format == file_format::cbor).
+ } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN) {
+ return write_dst(ptr, len);
+ } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT) {
// First try to parse (ptr, len) as an integer. Something like
// "1180591620717411303424" is a valid number (in the JSON sense) but will
// overflow int64_t or uint64_t, so fall back to parsing it as a float64.
@@ -973,9 +1032,23 @@
}
}
+fail:
return "main: internal error: unexpected write_number argument";
}
+const char* //
+write_inline_integer(uint64_t vbd, uint8_t* ptr, size_t len) {
+ if (g_flags.output_format == file_format::cbor) {
+ return write_dst(ptr, len);
+ }
+
+ uint8_t buf[WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL];
+ size_t n = wuffs_base__render_number_i64(
+ wuffs_base__make_slice_u8(&buf[0], sizeof buf), (int16_t)vbd,
+ WUFFS_BASE__RENDER_NUMBER_XXX__DEFAULT_OPTIONS);
+ return write_dst(&buf[0], n);
+}
+
// ----
uint8_t //
@@ -1332,6 +1405,11 @@
TRY(write_number(vbd, g_src.data.ptr + g_curr_token_end_src_index - len,
len));
goto after_value;
+
+ case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER:
+ TRY(write_inline_integer(
+ vbd, g_src.data.ptr + g_curr_token_end_src_index - len, len));
+ goto after_value;
}
// Return an error if we didn't match the (vbc, vbd) pair.
@@ -1370,7 +1448,7 @@
bool start_of_token_chain = true;
while (true) {
- wuffs_base__status status = g_dec.decode_tokens(
+ wuffs_base__status status = g_dec->decode_tokens(
&g_tok, &g_src,
wuffs_base__make_slice_u8(g_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));