Have base_16 codec return a transform__output
diff --git a/example/jsonfindptrs/jsonfindptrs.cc b/example/jsonfindptrs/jsonfindptrs.cc
index 7eb845c..298179b 100644
--- a/example/jsonfindptrs/jsonfindptrs.cc
+++ b/example/jsonfindptrs/jsonfindptrs.cc
@@ -652,18 +652,22 @@
}
while (encoded.len) {
uint8_t decoded[64];
- size_t len = wuffs_base__hexadecimal__decode4(
- wuffs_base__make_slice_u8(&decoded[0], 64), encoded);
- if ((len > 64) || ((len * 4) > encoded.len)) {
+ const bool src_closed = true;
+ wuffs_base__transform__output o = wuffs_base__base_16__decode4(
+ wuffs_base__make_slice_u8(&decoded[0], 64), encoded, src_closed,
+ WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);
+ if (o.status.is_error()) {
+ return Result(o.status.message(), JsonThing());
+ } else if ((o.num_dst > 64) || (o.num_src > encoded.len)) {
return Result(
"main: internal error: inconsistent hexadecimal decoding",
JsonThing());
}
const char* ptr = // Convert from (uint8_t*).
static_cast<const char*>(static_cast<void*>(&decoded[0]));
- jt.value.s.append(ptr, len);
- encoded.ptr += len * 4;
- encoded.len -= len * 4;
+ jt.value.s.append(ptr, o.num_dst);
+ encoded.ptr += o.num_src;
+ encoded.len -= o.num_src;
}
} else {
diff --git a/internal/cgen/base/i64conv-submodule.c b/internal/cgen/base/i64conv-submodule.c
index f6fcb2e..b071c11 100644
--- a/internal/cgen/base/i64conv-submodule.c
+++ b/internal/cgen/base/i64conv-submodule.c
@@ -396,13 +396,30 @@
false);
}
-// ---------------- Hexadecimal
+// ---------------- Base-16
-WUFFS_BASE__MAYBE_STATIC size_t //
-wuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 src) {
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
+wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 src,
+ bool src_closed,
+ uint32_t options) {
+ wuffs_base__transform__output o;
size_t src_len2 = src.len / 2;
- size_t len = dst.len < src_len2 ? dst.len : src_len2;
+ size_t len;
+ if (dst.len < src_len2) {
+ len = dst.len;
+ o.status.repr = wuffs_base__suspension__short_write;
+ } else {
+ len = src_len2;
+ if (!src_closed) {
+ o.status.repr = wuffs_base__suspension__short_read;
+ } else if (src.len & 1) {
+ o.status.repr = wuffs_base__error__bad_data;
+ } else {
+ o.status.repr = NULL;
+ }
+ }
+
uint8_t* d = dst.ptr;
uint8_t* s = src.ptr;
size_t n = len;
@@ -414,14 +431,33 @@
s += 2;
}
- return len;
+ o.num_dst = len;
+ o.num_src = len * 2;
+ return o;
}
-WUFFS_BASE__MAYBE_STATIC size_t //
-wuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 src) {
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
+wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 src,
+ bool src_closed,
+ uint32_t options) {
+ wuffs_base__transform__output o;
size_t src_len4 = src.len / 4;
size_t len = dst.len < src_len4 ? dst.len : src_len4;
+ if (dst.len < src_len4) {
+ len = dst.len;
+ o.status.repr = wuffs_base__suspension__short_write;
+ } else {
+ len = src_len4;
+ if (!src_closed) {
+ o.status.repr = wuffs_base__suspension__short_read;
+ } else if (src.len & 1) {
+ o.status.repr = wuffs_base__error__bad_data;
+ } else {
+ o.status.repr = NULL;
+ }
+ }
+
uint8_t* d = dst.ptr;
uint8_t* s = src.ptr;
size_t n = len;
@@ -433,7 +469,9 @@
s += 4;
}
- return len;
+ o.num_dst = len;
+ o.num_src = len * 4;
+ return o;
}
// ---------------- Base-64
diff --git a/internal/cgen/base/strconv-public.h b/internal/cgen/base/strconv-public.h
index 071476d..b92c747 100644
--- a/internal/cgen/base/strconv-public.h
+++ b/internal/cgen/base/strconv-public.h
@@ -259,13 +259,14 @@
uint64_t x,
uint32_t options);
-// ---------------- Hexadecimal
+// ---------------- Base-16
-// wuffs_base__hexadecimal__decode2 converts "6A6b" to "jk", where e.g. 'j' is
-// U+006A. There are 2 source bytes for every destination byte.
-//
-// It returns the number of dst bytes written: the minimum of dst.len and
-// (src.len / 2). Excess source bytes are ignored.
+// Options (bitwise or'ed together) for wuffs_base__base_16__xxx functions.
+
+#define WUFFS_BASE__BASE_16__DEFAULT_OPTIONS ((uint32_t)0x00000000)
+
+// wuffs_base__base_16__decode2 converts "6A6b" to "jk", where e.g. 'j' is
+// U+006A. There are 2 src bytes for every dst byte.
//
// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),
// repeated. It may write nonsense bytes if not, although it will not read or
@@ -274,15 +275,14 @@
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
-WUFFS_BASE__MAYBE_STATIC size_t //
-wuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 src);
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
+wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 src,
+ bool src_closed,
+ uint32_t options);
-// wuffs_base__hexadecimal__decode4 converts "\\x6A\\x6b" to "jk", where e.g.
-// 'j' is U+006A. There are 4 source bytes for every destination byte.
-//
-// It returns the number of dst bytes written: the minimum of dst.len and
-// (src.len / 4). Excess source bytes are ignored.
+// wuffs_base__base_16__decode4 converts both "\\x6A\\x6b" and "??6a??6B" to
+// "jk", where e.g. 'j' is U+006A. There are 4 src bytes for every dst byte.
//
// It assumes that the src bytes are two ignored bytes and then two hexadecimal
// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,
@@ -291,9 +291,11 @@
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
-WUFFS_BASE__MAYBE_STATIC size_t //
-wuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 src);
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
+wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 src,
+ bool src_closed,
+ uint32_t options);
// ---------------- Base-64
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index 44b14b4..b6e7d85 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -175,8 +175,9 @@
" ptr -= 1;\n ptr[0] = (uint8_t)('0' + x);\n } else {\n size_t index = x * 2;\n uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0];\n uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1];\n ptr -= 2;\n ptr[0] = s0;\n ptr[1] = s1;\n }\n\n if (neg) {\n ptr -= 1;\n ptr[0] = '-';\n } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {\n ptr -= 1;\n ptr[0] = '+';\n }\n\n size_t n = sizeof(buf) - ((size_t)(ptr - &buf[0]));\n if (n > dst.len) {\n return 0;\n }\n memcpy(dst.ptr + ((options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)\n ? (dst.len - n)\n : 0),\n ptr, n);\n return n;\n}\n\nWUFFS_BASE__MAYBE_STATIC size_t //\nwuffs_base__render_number_i64(wuffs_base__slice_u8 dst,\n int64_t x,\n uint32_t options) {\n uint64_t u = (uint64_t)x;\n bool neg = x < 0;\n if (neg) {\n u = 1 + ~u;\n }\n return wuffs_base__private_implementation__render_numb" +
"er_u64(dst, u, options,\n neg);\n}\n\nWUFFS_BASE__MAYBE_STATIC size_t //\nwuffs_base__render_number_u64(wuffs_base__slice_u8 dst,\n uint64_t x,\n uint32_t options) {\n return wuffs_base__private_implementation__render_number_u64(dst, x, options,\n false);\n}\n\n" +
"" +
- "// ---------------- Hexadecimal\n\nWUFFS_BASE__MAYBE_STATIC size_t //\nwuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src) {\n size_t src_len2 = src.len / 2;\n size_t len = dst.len < src_len2 ? dst.len : src_len2;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n size_t n = len;\n\n while (n--) {\n *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) |\n (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F));\n d += 1;\n s += 2;\n }\n\n return len;\n}\n\nWUFFS_BASE__MAYBE_STATIC size_t //\nwuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src) {\n size_t src_len4 = src.len / 4;\n size_t len = dst.len < src_len4 ? dst.len : src_len4;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n size_t n = len;\n\n while (n--) {\n *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) |\n (wuffs_base__parse_number__hexa" +
- "decimal_digits[s[3]] & 0x0F));\n d += 1;\n s += 4;\n }\n\n return len;\n}\n\n" +
+ "// ---------------- Base-16\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //\nwuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src,\n bool src_closed,\n uint32_t options) {\n wuffs_base__transform__output o;\n size_t src_len2 = src.len / 2;\n size_t len;\n if (dst.len < src_len2) {\n len = dst.len;\n o.status.repr = wuffs_base__suspension__short_write;\n } else {\n len = src_len2;\n if (!src_closed) {\n o.status.repr = wuffs_base__suspension__short_read;\n } else if (src.len & 1) {\n o.status.repr = wuffs_base__error__bad_data;\n } else {\n o.status.repr = NULL;\n }\n }\n\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n size_t n = len;\n\n while (n--) {\n *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) |\n (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F));\n d += 1;\n s += 2;\n }\n\n o.num_dst = len;\n o.num_s" +
+ "rc = len * 2;\n return o;\n}\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //\nwuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src,\n bool src_closed,\n uint32_t options) {\n wuffs_base__transform__output o;\n size_t src_len4 = src.len / 4;\n size_t len = dst.len < src_len4 ? dst.len : src_len4;\n if (dst.len < src_len4) {\n len = dst.len;\n o.status.repr = wuffs_base__suspension__short_write;\n } else {\n len = src_len4;\n if (!src_closed) {\n o.status.repr = wuffs_base__suspension__short_read;\n } else if (src.len & 1) {\n o.status.repr = wuffs_base__error__bad_data;\n } else {\n o.status.repr = NULL;\n }\n }\n\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n size_t n = len;\n\n while (n--) {\n *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) |\n (wuffs_base__parse_number__hexadecimal_digits[s[3]] & 0x0F));\n d += 1;\n " +
+ " s += 4;\n }\n\n o.num_dst = len;\n o.num_src = len * 4;\n return o;\n}\n\n" +
"" +
"// ---------------- Base-64\n\n// The two base-64 alphabets, std and url, differ only in the last two codes.\n// - std: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"\n// - url: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\"\n\nstatic const uint8_t wuffs_base__base_64__decode_std[256] = {\n // 0 1 2 3 4 5 6 7\n // 8 9 A B C D E F\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27.\n 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, // 0x28 ..= 0x2F.\n 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37.\n 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F.\n\n 0x80, 0x00, 0x01, 0x02," +
" 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47.\n 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F.\n 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57.\n 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x58 ..= 0x5F.\n 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67.\n 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F.\n 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77.\n 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F.\n\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF.\n 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // " +
@@ -526,8 +527,8 @@
" (and no bytes are written).\n//\n// dst will never be too short if its length is at least 20, also known as\n// WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL.\n//\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not\n// just WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC size_t //\nwuffs_base__render_number_i64(wuffs_base__slice_u8 dst,\n int64_t x,\n uint32_t options);\n\n// wuffs_base__render_number_u64 writes the decimal encoding of x to dst and\n// returns the number of bytes written. If dst is shorter than the entire\n// encoding, it returns 0 (and no bytes are written).\n//\n// dst will never be too short if its length is at least 21, also known as\n// WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL.\n//\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not\n// ju" +
"st WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC size_t //\nwuffs_base__render_number_u64(wuffs_base__slice_u8 dst,\n uint64_t x,\n uint32_t options);\n\n" +
"" +
- "// ---------------- Hexadecimal\n\n// wuffs_base__hexadecimal__decode2 converts \"6A6b\" to \"jk\", where e.g. 'j' is\n// U+006A. There are 2 source bytes for every destination byte.\n//\n// It returns the number of dst bytes written: the minimum of dst.len and\n// (src.len / 2). Excess source bytes are ignored.\n//\n// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),\n// repeated. It may write nonsense bytes if not, although it will not read or\n// write out of bounds.\n//\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not\n// just WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC size_t //\nwuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src);\n\n// wuffs_base__hexadecimal__decode4 converts \"\\\\x6A\\\\x6b\" to \"jk\", where e.g.\n// 'j' is U+006A. There are 4 source bytes for every destination byte.\n//\n// It returns the number of d" +
- "st bytes written: the minimum of dst.len and\n// (src.len / 4). Excess source bytes are ignored.\n//\n// It assumes that the src bytes are two ignored bytes and then two hexadecimal\n// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,\n// although it will not read or write out of bounds.\n//\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not\n// just WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC size_t //\nwuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src);\n\n" +
+ "// ---------------- Base-16\n\n// Options (bitwise or'ed together) for wuffs_base__base_16__xxx functions.\n\n#define WUFFS_BASE__BASE_16__DEFAULT_OPTIONS ((uint32_t)0x00000000)\n\n// wuffs_base__base_16__decode2 converts \"6A6b\" to \"jk\", where e.g. 'j' is\n// U+006A. There are 2 src bytes for every dst byte.\n//\n// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),\n// repeated. It may write nonsense bytes if not, although it will not read or\n// write out of bounds.\n//\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not\n// just WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //\nwuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src,\n bool src_closed,\n uint32_t options);\n\n// wuffs_base__base_16__decode4 converts both \"\\\\x6A\\\\x6b\" and" +
+ " \"??6a??6B\" to\n// \"jk\", where e.g. 'j' is U+006A. There are 4 src bytes for every dst byte.\n//\n// It assumes that the src bytes are two ignored bytes and then two hexadecimal\n// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,\n// although it will not read or write out of bounds.\n//\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not\n// just WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //\nwuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src,\n bool src_closed,\n uint32_t options);\n\n" +
"" +
"// ---------------- Base-64\n\n// Options (bitwise or'ed together) for wuffs_base__base_64__xxx functions.\n\n#define WUFFS_BASE__BASE_64__DEFAULT_OPTIONS ((uint32_t)0x00000000)\n\n// WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING means that, when decoding base-64,\n// the input may (but does not need to) be padded with '=' bytes so that the\n// overall encoded length in bytes is a multiple of 4. A successful decoding\n// will return a num_src that includes those padding bytes.\n//\n// Excess padding (e.g. three final '='s) will be rejected as bad data.\n#define WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING ((uint32_t)0x00000001)\n\n// WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING means that, when encoding base-64,\n// the output will be padded with '=' bytes so that the overall encoded length\n// in bytes is a multiple of 4.\n#define WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING ((uint32_t)0x00000002)\n\n// WUFFS_BASE__BASE_64__URL_ALPHABET means that, for base-64, the URL-friendly\n// and file-name-friendly alphabet be used, as per RFC 4648 sect" +
"ion 5. When\n// this option bit is off, the standard alphabet from section 4 is used.\n#define WUFFS_BASE__BASE_64__URL_ALPHABET ((uint32_t)0x00000100)\n\n// wuffs_base__base_64__decode transforms base-64 encoded bytes from src to\n// arbitrary bytes in dst.\n//\n// It will not permit line breaks or other whitespace in src. Filtering those\n// out is the responsibility of the caller.\n//\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not\n// just WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //\nwuffs_base__base_64__decode(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src,\n bool src_closed,\n uint32_t options);\n\n// wuffs_base__base_64__encode transforms arbitrary bytes from src to base-64\n// encoded bytes in dst.\n//\n// For modular builds that divide the base module into sub-modules, using this" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 9f188e1..a7a6592 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -4176,13 +4176,14 @@
uint64_t x,
uint32_t options);
-// ---------------- Hexadecimal
+// ---------------- Base-16
-// wuffs_base__hexadecimal__decode2 converts "6A6b" to "jk", where e.g. 'j' is
-// U+006A. There are 2 source bytes for every destination byte.
-//
-// It returns the number of dst bytes written: the minimum of dst.len and
-// (src.len / 2). Excess source bytes are ignored.
+// Options (bitwise or'ed together) for wuffs_base__base_16__xxx functions.
+
+#define WUFFS_BASE__BASE_16__DEFAULT_OPTIONS ((uint32_t)0x00000000)
+
+// wuffs_base__base_16__decode2 converts "6A6b" to "jk", where e.g. 'j' is
+// U+006A. There are 2 src bytes for every dst byte.
//
// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),
// repeated. It may write nonsense bytes if not, although it will not read or
@@ -4191,15 +4192,14 @@
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
-WUFFS_BASE__MAYBE_STATIC size_t //
-wuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 src);
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
+wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 src,
+ bool src_closed,
+ uint32_t options);
-// wuffs_base__hexadecimal__decode4 converts "\\x6A\\x6b" to "jk", where e.g.
-// 'j' is U+006A. There are 4 source bytes for every destination byte.
-//
-// It returns the number of dst bytes written: the minimum of dst.len and
-// (src.len / 4). Excess source bytes are ignored.
+// wuffs_base__base_16__decode4 converts both "\\x6A\\x6b" and "??6a??6B" to
+// "jk", where e.g. 'j' is U+006A. There are 4 src bytes for every dst byte.
//
// It assumes that the src bytes are two ignored bytes and then two hexadecimal
// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,
@@ -4208,9 +4208,11 @@
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__I64CONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
-WUFFS_BASE__MAYBE_STATIC size_t //
-wuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 src);
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
+wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 src,
+ bool src_closed,
+ uint32_t options);
// ---------------- Base-64
@@ -11963,13 +11965,30 @@
false);
}
-// ---------------- Hexadecimal
+// ---------------- Base-16
-WUFFS_BASE__MAYBE_STATIC size_t //
-wuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 src) {
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
+wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 src,
+ bool src_closed,
+ uint32_t options) {
+ wuffs_base__transform__output o;
size_t src_len2 = src.len / 2;
- size_t len = dst.len < src_len2 ? dst.len : src_len2;
+ size_t len;
+ if (dst.len < src_len2) {
+ len = dst.len;
+ o.status.repr = wuffs_base__suspension__short_write;
+ } else {
+ len = src_len2;
+ if (!src_closed) {
+ o.status.repr = wuffs_base__suspension__short_read;
+ } else if (src.len & 1) {
+ o.status.repr = wuffs_base__error__bad_data;
+ } else {
+ o.status.repr = NULL;
+ }
+ }
+
uint8_t* d = dst.ptr;
uint8_t* s = src.ptr;
size_t n = len;
@@ -11981,14 +12000,33 @@
s += 2;
}
- return len;
+ o.num_dst = len;
+ o.num_src = len * 2;
+ return o;
}
-WUFFS_BASE__MAYBE_STATIC size_t //
-wuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 src) {
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
+wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 src,
+ bool src_closed,
+ uint32_t options) {
+ wuffs_base__transform__output o;
size_t src_len4 = src.len / 4;
size_t len = dst.len < src_len4 ? dst.len : src_len4;
+ if (dst.len < src_len4) {
+ len = dst.len;
+ o.status.repr = wuffs_base__suspension__short_write;
+ } else {
+ len = src_len4;
+ if (!src_closed) {
+ o.status.repr = wuffs_base__suspension__short_read;
+ } else if (src.len & 1) {
+ o.status.repr = wuffs_base__error__bad_data;
+ } else {
+ o.status.repr = NULL;
+ }
+ }
+
uint8_t* d = dst.ptr;
uint8_t* s = src.ptr;
size_t n = len;
@@ -12000,7 +12038,9 @@
s += 4;
}
- return len;
+ o.num_dst = len;
+ o.num_src = len * 4;
+ return o;
}
// ---------------- Base-64
diff --git a/test/c/std/json.c b/test/c/std/json.c
index 7c8f527..e6840b5 100644
--- a/test/c/std/json.c
+++ b/test/c/std/json.c
@@ -422,17 +422,26 @@
// ----------------
const char* //
-test_wuffs_strconv_hexadecimal() {
+test_wuffs_strconv_base_16() {
CHECK_FOCUS(__func__);
+ const bool src_closed = true;
{
- const char* str = "6A6b7"; // The "7" should be ignored.
+ const char* str = "6A6b7"; // The "7" should cause "#base: bad data".
wuffs_base__slice_u8 dst = g_have_slice_u8;
wuffs_base__slice_u8 src =
wuffs_base__make_slice_u8((void*)str, strlen(str));
- size_t have = wuffs_base__hexadecimal__decode2(dst, src);
- if (have != 2) {
- RETURN_FAIL("decode2: have %zu, want 2", have);
+ wuffs_base__transform__output have = wuffs_base__base_16__decode2(
+ dst, src, src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);
+ if (have.status.repr != wuffs_base__error__bad_data) {
+ RETURN_FAIL("decode2: have \"%s\", want \"%s\"", have.status.repr,
+ wuffs_base__error__bad_data);
+ }
+ if (have.num_dst != 2) {
+ RETURN_FAIL("decode2: num_dst: have %zu, want 2", have.num_dst);
+ }
+ if (have.num_src != 4) {
+ RETURN_FAIL("decode2: num_src: have %zu, want 3", have.num_src);
}
if (g_have_array_u8[0] != 0x6A) {
RETURN_FAIL("decode2: dst[0]: have 0x%02X, want 0x6A",
@@ -449,9 +458,16 @@
wuffs_base__slice_u8 dst = g_have_slice_u8;
wuffs_base__slice_u8 src =
wuffs_base__make_slice_u8((void*)str, strlen(str));
- size_t have = wuffs_base__hexadecimal__decode4(dst, src);
- if (have != 3) {
- RETURN_FAIL("decode4: have %zu, want 3", have);
+ wuffs_base__transform__output have = wuffs_base__base_16__decode4(
+ dst, src, src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);
+ if (have.status.repr) {
+ RETURN_FAIL("decode2: %s", have.status.repr);
+ }
+ if (have.num_dst != 3) {
+ RETURN_FAIL("decode4: num_dst: have %zu, want 3", have.num_dst);
+ }
+ if (have.num_src != 12) {
+ RETURN_FAIL("decode4: num_src: have %zu, want 3", have.num_src);
}
if (g_have_array_u8[0] != 0xA9) {
RETURN_FAIL("decode4: dst[0]: have 0x%02X, want 0xA9",
@@ -2468,11 +2484,13 @@
(vbd &
WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X)) {
uint8_t b[8] = {0};
- size_t n = wuffs_base__hexadecimal__decode4(
+ const bool src_closed = true;
+ wuffs_base__transform__output o = wuffs_base__base_16__decode4(
wuffs_base__make_slice_u8(&b[0], 8),
- wuffs_base__make_slice_u8(src_slice.ptr + src_index, token_length));
+ wuffs_base__make_slice_u8(src_slice.ptr + src_index, token_length),
+ src_closed, 0);
size_t i = 0;
- for (; i < n; i++) {
+ for (; i < o.num_dst; i++) {
have_bytes <<= 8;
have_bytes |= b[i];
}
@@ -3437,7 +3455,7 @@
// good as any other place.
test_wuffs_core_count_leading_zeroes_u64,
test_wuffs_core_multiply_u64,
- test_wuffs_strconv_hexadecimal,
+ test_wuffs_strconv_base_16,
test_wuffs_strconv_base_64,
test_wuffs_strconv_hpd_rounded_integer,
test_wuffs_strconv_hpd_shift,