From c63114710eddebe73f35c89bf3eae3b47b0983dc Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 11 Sep 2024 17:11:44 -0400 Subject: [PATCH 01/17] coreboot patches: remove lib/jpeg patches for heap increase and alloc failure. Add https://review.coreboot.org/c/coreboot/+/83895 Repro: rm patches/coreboot-24.02.01/0001* patches/coreboot-24.02.01/0002* git fetch https://review.coreboot.org/coreboot refs/changes/94/83894/2 && git format-patch -1 --stdout FETCH_HEAD > patches/coreboot-24.02.01/0001-vc_wuffs-upgrade-to-Wuffs_0.4.0-alpha.8.patch git fetch https://review.coreboot.org/coreboot refs/changes/95/83895/3 && git format-patch -1 --stdout FETCH_HEAD > patches/coreboot-24.02.01/0002-lib_jpeg-avoidcalling-malloc-and-free.patch sed -i 's/CONFIG_HEAP_SIZE=0x400000/CONFIG_HEAP_SIZE=0x100000/g' config/coreboot-* Signed-off-by: Thierry Laurion --- config/coreboot-librem_11.config | 2 +- config/coreboot-librem_13v2.config | 2 +- config/coreboot-librem_13v4.config | 2 +- config/coreboot-librem_14.config | 2 +- config/coreboot-librem_15v3.config | 2 +- config/coreboot-librem_15v4.config | 2 +- config/coreboot-librem_l1um_v2.config | 2 +- config/coreboot-librem_mini.config | 2 +- config/coreboot-librem_mini_v2.config | 2 +- config/coreboot-qemu-tpm1.config | 2 +- config/coreboot-qemu-tpm2.config | 2 +- config/coreboot-t420-maximized.config | 2 +- config/coreboot-t430-maximized.config | 2 +- config/coreboot-t440p.config | 2 +- config/coreboot-t530-maximized.config | 2 +- config/coreboot-w530-maximized.config | 2 +- config/coreboot-w541.config | 2 +- config/coreboot-x220-maximized.config | 2 +- config/coreboot-x230-legacy-flash.config | 2 +- config/coreboot-x230-legacy.config | 2 +- config/coreboot-x230-maximized-fhd_edp.config | 2 +- config/coreboot-x230-maximized.config | 2 +- config/coreboot-z220-cmt.config | 2 +- ...h_heap_allocation_failure_to_booting.patch | 80 - ...wuffs-upgrade-to-Wuffs_0.4.0-alpha.8.patch | 111421 +++++++++++++++ ...rom1mb_to4mb_when_bootpslash_enabled.patch | 44 - ...ib_jpeg-avoidcalling-malloc-and-free.patch | 91 + 27 files changed, 111535 insertions(+), 147 deletions(-) delete mode 100644 patches/coreboot-24.02.01/0001-prevent_bootsplash_heap_allocation_failure_to_booting.patch create mode 100644 patches/coreboot-24.02.01/0001-vc_wuffs-upgrade-to-Wuffs_0.4.0-alpha.8.patch delete mode 100644 patches/coreboot-24.02.01/0002-increase_heap_from1mb_to4mb_when_bootpslash_enabled.patch create mode 100644 patches/coreboot-24.02.01/0002-lib_jpeg-avoidcalling-malloc-and-free.patch diff --git a/config/coreboot-librem_11.config b/config/coreboot-librem_11.config index b153955f..e4fb403d 100644 --- a/config/coreboot-librem_11.config +++ b/config/coreboot-librem_11.config @@ -478,7 +478,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-librem_13v2.config b/config/coreboot-librem_13v2.config index 001115ac..699c54a3 100644 --- a/config/coreboot-librem_13v2.config +++ b/config/coreboot-librem_13v2.config @@ -501,7 +501,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-librem_13v4.config b/config/coreboot-librem_13v4.config index 9eb08a47..84b37ae2 100644 --- a/config/coreboot-librem_13v4.config +++ b/config/coreboot-librem_13v4.config @@ -501,7 +501,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-librem_14.config b/config/coreboot-librem_14.config index 4bdcee32..f72db439 100644 --- a/config/coreboot-librem_14.config +++ b/config/coreboot-librem_14.config @@ -498,7 +498,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-librem_15v3.config b/config/coreboot-librem_15v3.config index 012f3742..395a8be8 100644 --- a/config/coreboot-librem_15v3.config +++ b/config/coreboot-librem_15v3.config @@ -501,7 +501,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-librem_15v4.config b/config/coreboot-librem_15v4.config index 998fe279..dd16e94c 100644 --- a/config/coreboot-librem_15v4.config +++ b/config/coreboot-librem_15v4.config @@ -501,7 +501,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-librem_l1um_v2.config b/config/coreboot-librem_l1um_v2.config index aa599988..ca70ea96 100644 --- a/config/coreboot-librem_l1um_v2.config +++ b/config/coreboot-librem_l1um_v2.config @@ -498,7 +498,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-librem_mini.config b/config/coreboot-librem_mini.config index 82f90810..62d2c37d 100644 --- a/config/coreboot-librem_mini.config +++ b/config/coreboot-librem_mini.config @@ -502,7 +502,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-librem_mini_v2.config b/config/coreboot-librem_mini_v2.config index 02d16d24..85ed80b7 100644 --- a/config/coreboot-librem_mini_v2.config +++ b/config/coreboot-librem_mini_v2.config @@ -504,7 +504,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-qemu-tpm1.config b/config/coreboot-qemu-tpm1.config index 51bc7b1f..3282918c 100644 --- a/config/coreboot-qemu-tpm1.config +++ b/config/coreboot-qemu-tpm1.config @@ -327,7 +327,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-qemu-tpm2.config b/config/coreboot-qemu-tpm2.config index 56ce7eb9..ec561985 100644 --- a/config/coreboot-qemu-tpm2.config +++ b/config/coreboot-qemu-tpm2.config @@ -324,7 +324,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-t420-maximized.config b/config/coreboot-t420-maximized.config index 44f4610e..fdd176c2 100644 --- a/config/coreboot-t420-maximized.config +++ b/config/coreboot-t420-maximized.config @@ -424,7 +424,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-t430-maximized.config b/config/coreboot-t430-maximized.config index 1e6c97de..53058322 100644 --- a/config/coreboot-t430-maximized.config +++ b/config/coreboot-t430-maximized.config @@ -424,7 +424,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-t440p.config b/config/coreboot-t440p.config index 392c87b1..ac28f675 100644 --- a/config/coreboot-t440p.config +++ b/config/coreboot-t440p.config @@ -422,7 +422,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-t530-maximized.config b/config/coreboot-t530-maximized.config index 2fad20d3..2008200d 100644 --- a/config/coreboot-t530-maximized.config +++ b/config/coreboot-t530-maximized.config @@ -424,7 +424,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-w530-maximized.config b/config/coreboot-w530-maximized.config index 8d4a35eb..b79e61a4 100644 --- a/config/coreboot-w530-maximized.config +++ b/config/coreboot-w530-maximized.config @@ -427,7 +427,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-w541.config b/config/coreboot-w541.config index b8ccf8e4..5515e064 100644 --- a/config/coreboot-w541.config +++ b/config/coreboot-w541.config @@ -422,7 +422,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-x220-maximized.config b/config/coreboot-x220-maximized.config index e2bd2aa7..5809a48a 100644 --- a/config/coreboot-x220-maximized.config +++ b/config/coreboot-x220-maximized.config @@ -424,7 +424,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-x230-legacy-flash.config b/config/coreboot-x230-legacy-flash.config index d0cfe88a..1e288a21 100644 --- a/config/coreboot-x230-legacy-flash.config +++ b/config/coreboot-x230-legacy-flash.config @@ -413,7 +413,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-x230-legacy.config b/config/coreboot-x230-legacy.config index dc57f10d..336170d9 100644 --- a/config/coreboot-x230-legacy.config +++ b/config/coreboot-x230-legacy.config @@ -413,7 +413,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-x230-maximized-fhd_edp.config b/config/coreboot-x230-maximized-fhd_edp.config index f7b59b0f..56eaea73 100644 --- a/config/coreboot-x230-maximized-fhd_edp.config +++ b/config/coreboot-x230-maximized-fhd_edp.config @@ -425,7 +425,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-x230-maximized.config b/config/coreboot-x230-maximized.config index 64d57bfb..1f898e3f 100644 --- a/config/coreboot-x230-maximized.config +++ b/config/coreboot-x230-maximized.config @@ -424,7 +424,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/config/coreboot-z220-cmt.config b/config/coreboot-z220-cmt.config index cb17a7ad..e03169aa 100644 --- a/config/coreboot-z220-cmt.config +++ b/config/coreboot-z220-cmt.config @@ -401,7 +401,7 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 +CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y diff --git a/patches/coreboot-24.02.01/0001-prevent_bootsplash_heap_allocation_failure_to_booting.patch b/patches/coreboot-24.02.01/0001-prevent_bootsplash_heap_allocation_failure_to_booting.patch deleted file mode 100644 index 3913ba10..00000000 --- a/patches/coreboot-24.02.01/0001-prevent_bootsplash_heap_allocation_failure_to_booting.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 8b6fc3a877d8169091d034ea6ac6d15593cc69a0 Mon Sep 17 00:00:00 2001 -From: Jonathon Hall -Date: Mon, 15 Jul 2024 15:01:52 -0400 -Subject: [PATCH] src/lib/malloc.c: If allocation fails, leave the heap - unchanged - -If an allocation fails because it is too large for the rest of the heap, -don't consume the rest of the heap needlessly. - -This started occurring with the Heads bootsplash image in 24.02.01, -following the switch to the Wuffs JPEG decoder. The work area needed -was too large for the heap. The bootsplash failed to show, but worse, -the boot failed entirely because we were then out of heap space, even -though we did not actually use the large allocation that failed. - -With this change, that failure no longer prevents boot. - -The error message is improved slightly also: -* missing line break is added -* "Tried to round up" now shows the beginning of the allocation before - and after rounding instead of the unrounded beginning and rounded end - (misleading, looked like it was trying to align by 1 MB when it - was actually allocating 1 MB) - -Change-Id: Ie72814027d9daa517c0794f3ea7abec2b9a9d596 -Signed-off-by: Jonathon Hall ---- - src/lib/malloc.c | 25 ++++++++++++------------- - 1 file changed, 12 insertions(+), 13 deletions(-) - -diff --git a/src/lib/malloc.c b/src/lib/malloc.c -index 30298064d9..281792c3d5 100644 ---- a/src/lib/malloc.c -+++ b/src/lib/malloc.c -@@ -26,30 +26,29 @@ void *memalign(size_t boundary, size_t size) - MALLOCDBG("%s Enter, boundary %zu, size %zu, free_mem_ptr %p\n", - __func__, boundary, size, free_mem_ptr); - -- free_mem_ptr = (void *)ALIGN_UP((unsigned long)free_mem_ptr, boundary); -+ p = (void *)ALIGN_UP((unsigned long)free_mem_ptr, boundary); - -- p = free_mem_ptr; -- free_mem_ptr += size; -- /* -- * Store last allocation pointer after ALIGN, as malloc() will -- * return it. This may cause n bytes of gap between allocations -- * where n < boundary. -- */ -- free_last_alloc_ptr = p; -- -- if (free_mem_ptr >= free_mem_end_ptr) { -+ if (p + size >= free_mem_end_ptr) { - printk(BIOS_ERR, "%s(boundary=%zu, size=%zu): failed: ", - __func__, boundary, size); - printk(BIOS_ERR, "Tried to round up free_mem_ptr %p to %p\n", -- p, free_mem_ptr); -+ free_mem_ptr, p); - printk(BIOS_ERR, "but free_mem_end_ptr is %p\n", - free_mem_end_ptr); - printk(BIOS_ERR, "Error! %s: Out of memory " -- "(free_mem_ptr >= free_mem_end_ptr)", -+ "(free_mem_ptr >= free_mem_end_ptr)\n", - __func__); - return NULL; - } - -+ free_mem_ptr = p + size; -+ /* -+ * Store last allocation pointer after ALIGN, as malloc() will -+ * return it. This may cause n bytes of gap between allocations -+ * where n < boundary. -+ */ -+ free_last_alloc_ptr = p; -+ - MALLOCDBG("%s %p\n", __func__, p); - - return p; --- -2.39.2 - diff --git a/patches/coreboot-24.02.01/0001-vc_wuffs-upgrade-to-Wuffs_0.4.0-alpha.8.patch b/patches/coreboot-24.02.01/0001-vc_wuffs-upgrade-to-Wuffs_0.4.0-alpha.8.patch new file mode 100644 index 00000000..7208d5eb --- /dev/null +++ b/patches/coreboot-24.02.01/0001-vc_wuffs-upgrade-to-Wuffs_0.4.0-alpha.8.patch @@ -0,0 +1,111421 @@ +From b598d05d389e137baa10e277a37fca2c363fb295 Mon Sep 17 00:00:00 2001 +From: Nigel Tao +Date: Tue, 13 Aug 2024 22:10:52 +1000 +Subject: [PATCH] vc/wuffs: upgrade to Wuffs 0.4.0-alpha.8 + +We were previously at Wuffs 0.4.0-alpha.2. The C file was copied from +https://github.com/google/wuffs-mirror-release-c and its hash matches +https://github.com/google/wuffs-mirror-release-c/blob/90e4d81a6a8b7b601e8e568da32a105d7f7705e5/sync.txt#L9-L10 + +$ sha256sum src/vendorcode/wuffs/wuffs-v0.4.c +6c22caff4af929112601379a73f72461bc4719a5215366bcc90d599cbc442bb6 src/vendorcode/wuffs/wuffs-v0.4.c + +Change-Id: Ie90d989384e0db2b23d7d1b3d9a57920ac8a95a2 +Signed-off-by: Nigel Tao +Reviewed-on: https://review.coreboot.org/c/coreboot/+/83894 +Reviewed-by: Felix Singer +Reviewed-by: Nico Huber +Tested-by: build bot (Jenkins) +--- + src/vendorcode/wuffs/wuffs-v0.4.c | 101194 ++++++++++++++++----------- + 1 file changed, 58878 insertions(+), 42316 deletions(-) + +diff --git a/src/vendorcode/wuffs/wuffs-v0.4.c b/src/vendorcode/wuffs/wuffs-v0.4.c +index bce9eb9798..0c6616a652 100644 +--- a/src/vendorcode/wuffs/wuffs-v0.4.c ++++ b/src/vendorcode/wuffs/wuffs-v0.4.c +@@ -81,15 +81,43 @@ extern "C" { + // each major.minor branch, the commit count should increase monotonically. + // + // WUFFS_VERSION was overridden by "wuffs gen -version" based on revision +-// ae8531f7f846fbbe3a7340bf88499ad294a1367b committed on 2023-10-07. ++// 5d69840f8e7ca481551b02c7e8d4c5fb69521bb9 committed on 2024-08-12. + #define WUFFS_VERSION 0x000040000 + #define WUFFS_VERSION_MAJOR 0 + #define WUFFS_VERSION_MINOR 4 + #define WUFFS_VERSION_PATCH 0 +-#define WUFFS_VERSION_PRE_RELEASE_LABEL "alpha.2" +-#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 3603 +-#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 20231007 +-#define WUFFS_VERSION_STRING "0.4.0-alpha.2+3603.20231007" ++#define WUFFS_VERSION_PRE_RELEASE_LABEL "alpha.8" ++#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 3796 ++#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 20240812 ++#define WUFFS_VERSION_STRING "0.4.0-alpha.8+3796.20240812" ++ ++// ---------------- Private Implementation Macros Re-definition Check ++ ++// Users (those who #include the "wuffs-vM.N.c" file) should not define any ++// WUFFS_PRIVATE_IMPL__ETC macros, only WUFFS_CONFIG__ETC macros (and ++// WUFFS_IMPLEMENTATION). Mucking about with the private implementation macros ++// is not supported and may break when upgrading to newer Wuffs versions. ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32) || \ ++ defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) || \ ++ defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) || \ ++ defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) || \ ++ defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) || \ ++ defined(WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE) || \ ++ defined(WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION) || \ ++ defined(WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL) || \ ++ defined(WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U16) || \ ++ defined(WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32) || \ ++ defined(WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U64) || \ ++ defined(WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U8) ++ ++#if defined(__GNUC__) || defined(__clang__) ++#warning "Defining WUFFS_PRIVATE_IMPL__ETC yourself is not supported" ++#elif defined(_MSC_VER) ++#pragma message("Defining WUFFS_PRIVATE_IMPL__ETC yourself is not supported") ++#endif ++ ++#endif + + // ---------------- Configuration + +@@ -117,11 +145,11 @@ extern "C" { + // intrinsics. Look for __ARM_FEATURE_CRC32 instead. + #if defined(__ARM_FEATURE_CRC32) + #include +-#define WUFFS_BASE__CPU_ARCH__ARM_CRC32 ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32 + #endif // defined(__ARM_FEATURE_CRC32) + #if defined(__ARM_NEON) + #include +-#define WUFFS_BASE__CPU_ARCH__ARM_NEON ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON + #endif // defined(__ARM_NEON) + #endif // defined(__ARM_FEATURE_UNALIGNED) etc + +@@ -129,26 +157,82 @@ extern "C" { + // POPCNT. This is checked at runtime via cpuid, not at compile time. + // + // Likewise, "cpu_arch >= x86_avx2" also requires PCLMUL, POPCNT and SSE4.2. +-#if defined(__i386__) || defined(__x86_64__) ++// ++// ---- ++// ++// Technically, we could use the SSE family on 32-bit x86, not just 64-bit x86. ++// But some intrinsics don't compile in 32-bit mode. It's not worth the hassle. ++// https://github.com/google/wuffs/issues/145 ++#if defined(__x86_64__) + #if !defined(__native_client__) + #include + #include +-// X86_FAMILY means X86 (32-bit) or X86_64 (64-bit, obviously). +-#define WUFFS_BASE__CPU_ARCH__X86_FAMILY +-#if defined(__x86_64__) +-#define WUFFS_BASE__CPU_ARCH__X86_64 +-#endif // defined(__x86_64__) ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64 ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2 ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3 + #endif // !defined(__native_client__) +-#endif // defined(__i386__) || defined(__x86_64__) ++#endif // defined(__x86_64__) + + #elif defined(_MSC_VER) // (#if-chain ref AVOID_CPU_ARCH_1) + +-#if defined(_M_IX86) || defined(_M_X64) +-#if defined(__AVX__) || defined(__clang__) ++#if defined(_M_X64) ++ ++// On X86_64, Microsoft Visual C/C++ (MSVC) only supports SSE2 by default. ++// There are /arch:SSE2, /arch:AVX and /arch:AVX2 compiler flags (the AVX2 one ++// is roughly equivalent to X86_64_V3), but there is no /arch:SSE42 compiler ++// flag that's equivalent to X86_64_V2. ++// ++// For getting maximum performance with X86_64 MSVC and Wuffs, pass /arch:AVX2 ++// (and then test on the oldest hardware you intend to support). ++// ++// Absent that compiler flag, either define one of the three macros listed ++// below or else the X86_64 SIMD code will be disabled and you'll get a #pragma ++// message stating this library "performs best with /arch:AVX2". This message ++// is harmless and ignorable, in that the non-SIMD code is still correct and ++// reasonably performant, but is a reminder that when combining Wuffs and MSVC, ++// some compiler configuration is required for maximum performance. ++// ++// - WUFFS_CONFIG__DISABLE_MSVC_CPU_ARCH__X86_64_FAMILY ++// - WUFFS_CONFIG__ENABLE_MSVC_CPU_ARCH__X86_64_V2 (enables SSE4.2 and below) ++// - WUFFS_CONFIG__ENABLE_MSVC_CPU_ARCH__X86_64_V3 (enables AVX2 and below) ++// ++// Defining the first one (WUFFS_CONFIG__DISABLE_MSVC_CPU_ARCH__X86_64_FAMILY) ++// or defining none of those three (the default state) are equivalent (in that ++// both disable the SIMD code paths), other than that pragma message. ++// ++// When defining these WUFFS_CONFIG__ENABLE_ETC macros with MSVC, be aware that ++// some users report it leading to ICEs (Internal Compiler Errors), but other ++// users report no problems at all (and improved performance). It's unclear ++// exactly what combination of SIMD code and MSVC configuration lead to ICEs. ++// Do your own testing with your own MSVC version and configuration. ++// ++// https://github.com/google/wuffs/issues/148 ++// https://github.com/google/wuffs/issues/151 ++// https://developercommunity.visualstudio.com/t/fatal--error-C1001:-Internal-compiler-er/10703305 ++// ++// Clang (including clang-cl) and GCC don't need this WUFFS_CONFIG__ETC macro ++// machinery, or having the Wuffs-the-library user to fiddle with compiler ++// flags, because they support "__attribute__((target(arg)))". ++#if defined(__AVX2__) || defined(__clang__) || \ ++ defined(WUFFS_CONFIG__ENABLE_MSVC_CPU_ARCH__X86_64_V3) ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64 ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2 ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3 ++#elif defined(WUFFS_CONFIG__ENABLE_MSVC_CPU_ARCH__X86_64_V2) ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64 ++#define WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2 ++#elif !defined(WUFFS_CONFIG__DISABLE_MSVC_CPU_ARCH__X86_64_FAMILY) ++#pragma message("Wuffs with MSVC+X64 performs best with /arch:AVX2") ++#endif // defined(__AVX2__) || defined(__clang__) || etc ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) ++ ++#if defined(WUFFS_CONFIG__DISABLE_MSVC_CPU_ARCH__X86_64_FAMILY) ++#error "MSVC_CPU_ARCH simultaneously enabled and disabled" ++#endif + +-// We need for the __cpuid function. + #include +-// That's not enough for X64 SIMD, with clang-cl, if we want to use ++// intrin.h isn't enough for X64 SIMD, with clang-cl, if we want to use + // "__attribute__((target(arg)))" without e.g. "/arch:AVX". + // + // Some web pages suggest that is all you need, as it pulls in +@@ -157,25 +241,9 @@ extern "C" { + #include // AVX, AVX2, FMA, POPCNT + #include // SSE4.2 + #include // AES, PCLMUL +-// X86_FAMILY means X86 (32-bit) or X86_64 (64-bit, obviously). +-#define WUFFS_BASE__CPU_ARCH__X86_FAMILY +-#if defined(_M_X64) +-#define WUFFS_BASE__CPU_ARCH__X86_64 +-#endif // defined(_M_X64) +- +-#else // defined(__AVX__) || defined(__clang__) +- +-// clang-cl (which defines both __clang__ and _MSC_VER) supports +-// "__attribute__((target(arg)))". +-// +-// For MSVC's cl.exe (unlike clang or gcc), SIMD capability is a compile-time +-// property of the source file (e.g. a /arch:AVX or -mavx compiler flag), not +-// of individual functions (that can be conditionally selected at runtime). +-#pragma message("Wuffs with MSVC+IX86/X64 needs /arch:AVX for best performance") +- +-#endif // defined(__AVX__) || defined(__clang__) +-#endif // defined(_M_IX86) || defined(_M_X64) + ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) ++#endif // defined(_M_X64) + #endif // (#if-chain ref AVOID_CPU_ARCH_1) + #endif // (#if-chain ref AVOID_CPU_ARCH_0) + +@@ -198,20 +266,20 @@ extern "C" { + + static inline bool // + wuffs_base__cpu_arch__have_arm_crc32(void) { +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32) ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32) + return true; + #else + return false; +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32) ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32) + } + + static inline bool // + wuffs_base__cpu_arch__have_arm_neon(void) { +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) + return true; + #else + return false; +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) + } + + static inline bool // +@@ -220,7 +288,7 @@ wuffs_base__cpu_arch__have_x86_avx2(void) { + defined(__AVX2__) + return true; + #else +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) + // GCC defines these macros but MSVC does not. + // - bit_AVX2 = (1 << 5) + const unsigned int avx2_ebx7 = 0x00000020; +@@ -258,9 +326,9 @@ wuffs_base__cpu_arch__have_x86_avx2(void) { + } + } + #else +-#error "WUFFS_BASE__CPU_ARCH__ETC combined with an unsupported compiler" ++#error "WUFFS_PRIVATE_IMPL__CPU_ARCH__ETC combined with an unsupported compiler" + #endif // defined(__GNUC__); defined(_MSC_VER) +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_64) ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) + return false; + #endif // defined(__PCLMUL__) && defined(__POPCNT__) && defined(__SSE4_2__) && + // defined(__AVX2__) +@@ -271,7 +339,7 @@ wuffs_base__cpu_arch__have_x86_bmi2(void) { + #if defined(__BMI2__) + return true; + #else +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) + // GCC defines these macros but MSVC does not. + // - bit_BMI2 = (1 << 8) + const unsigned int bmi2_ebx7 = 0x00000100; +@@ -293,9 +361,9 @@ wuffs_base__cpu_arch__have_x86_bmi2(void) { + return true; + } + #else +-#error "WUFFS_BASE__CPU_ARCH__ETC combined with an unsupported compiler" ++#error "WUFFS_PRIVATE_IMPL__CPU_ARCH__ETC combined with an unsupported compiler" + #endif // defined(__GNUC__); defined(_MSC_VER) +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) + return false; + #endif // defined(__BMI2__) + } +@@ -305,7 +373,7 @@ wuffs_base__cpu_arch__have_x86_sse42(void) { + #if defined(__PCLMUL__) && defined(__POPCNT__) && defined(__SSE4_2__) + return true; + #else +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) + // GCC defines these macros but MSVC does not. + // - bit_PCLMUL = (1 << 1) + // - bit_POPCNT = (1 << 23) +@@ -329,9 +397,9 @@ wuffs_base__cpu_arch__have_x86_sse42(void) { + return true; + } + #else +-#error "WUFFS_BASE__CPU_ARCH__ETC combined with an unsupported compiler" ++#error "WUFFS_PRIVATE_IMPL__CPU_ARCH__ETC combined with an unsupported compiler" + #endif // defined(__GNUC__); defined(_MSC_VER) +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64) + return false; + #endif // defined(__PCLMUL__) && defined(__POPCNT__) && defined(__SSE4_2__) + } +@@ -350,9 +418,15 @@ wuffs_base__cpu_arch__have_x86_sse42(void) { + // The "defined(__clang__)" isn't redundant. While vanilla clang defines + // __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not. + #if defined(__GNUC__) || defined(__clang__) ++#define WUFFS_BASE__FORCE_INLINE __attribute__((__always_inline__)) + #define WUFFS_BASE__POTENTIALLY_UNUSED __attribute__((unused)) + #define WUFFS_BASE__WARN_UNUSED_RESULT __attribute__((warn_unused_result)) ++#elif defined(_MSC_VER) ++#define WUFFS_BASE__FORCE_INLINE __forceinline ++#define WUFFS_BASE__POTENTIALLY_UNUSED ++#define WUFFS_BASE__WARN_UNUSED_RESULT + #else ++#define WUFFS_BASE__FORCE_INLINE + #define WUFFS_BASE__POTENTIALLY_UNUSED + #define WUFFS_BASE__WARN_UNUSED_RESULT + #endif +@@ -415,6 +489,37 @@ struct wuffs_unique_ptr_deleter { + + // -------- + ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wcast-qual" ++#endif ++ ++static inline uint8_t* // ++wuffs_base__strip_const_from_u8_ptr(const uint8_t* ptr) { ++ return (uint8_t*)ptr; ++} ++ ++static inline uint16_t* // ++wuffs_base__strip_const_from_u16_ptr(const uint16_t* ptr) { ++ return (uint16_t*)ptr; ++} ++ ++static inline uint32_t* // ++wuffs_base__strip_const_from_u32_ptr(const uint32_t* ptr) { ++ return (uint32_t*)ptr; ++} ++ ++static inline uint64_t* // ++wuffs_base__strip_const_from_u64_ptr(const uint64_t* ptr) { ++ return (uint64_t*)ptr; ++} ++ ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ ++// -------- ++ + // wuffs_base__empty_struct is used when a Wuffs function returns an empty + // struct. In C, if a function f returns void, you can't say "x = f()", but in + // Wuffs, if a function g returns empty, you can say "y = g()". +@@ -483,6 +588,7 @@ extern const char wuffs_base__suspension__even_more_information[]; + extern const char wuffs_base__suspension__mispositioned_read[]; + extern const char wuffs_base__suspension__mispositioned_write[]; + extern const char wuffs_base__suspension__short_read[]; ++extern const char wuffs_base__suspension__short_workbuf[]; + extern const char wuffs_base__suspension__short_write[]; + extern const char wuffs_base__error__bad_i_o_position[]; + extern const char wuffs_base__error__bad_argument_length_too_short[]; +@@ -496,9 +602,11 @@ extern const char wuffs_base__error__bad_vtable[]; + extern const char wuffs_base__error__bad_workbuf_length[]; + extern const char wuffs_base__error__bad_wuffs_version[]; + extern const char wuffs_base__error__cannot_return_a_suspension[]; ++extern const char wuffs_base__error__disabled_by_wuffs_config_dst_pixel_format_enable_allowlist[]; + extern const char wuffs_base__error__disabled_by_previous_error[]; + extern const char wuffs_base__error__initialize_falsely_claimed_already_zeroed[]; + extern const char wuffs_base__error__initialize_not_called[]; ++extern const char wuffs_base__error__insufficient_history[]; + extern const char wuffs_base__error__interleaved_coroutine_calls[]; + extern const char wuffs_base__error__no_more_information[]; + extern const char wuffs_base__error__not_enough_data[]; +@@ -728,6 +836,9 @@ typedef struct wuffs_base__transform__output__struct { + // Lempel–Ziv 4. + #define WUFFS_BASE__FOURCC__LZ4 0x4C5A3420 + ++// Lzip. ++#define WUFFS_BASE__FOURCC__LZIP 0x4C5A4950 ++ + // Lempel–Ziv Markov-chain Algorithm. + #define WUFFS_BASE__FOURCC__LZMA 0x4C5A4D41 + +@@ -839,6 +950,8 @@ typedef struct wuffs_base__transform__output__struct { + + #define WUFFS_BASE__QUIRK_IGNORE_CHECKSUM 1 + ++#define WUFFS_BASE__QUIRK_QUALITY 2 ++ + // -------- + + // Flicks are a unit of time. One flick (frame-tick) is 1 / 705_600_000 of a +@@ -1092,6 +1205,96 @@ wuffs_base__multiply_u64(uint64_t x, uint64_t y) { + + // -------- + ++typedef struct wuffs_base__bitvec256__struct { ++ // elements_u64[0] holds the LSBs (least significant bits) and ++ // elements_u64[3] holds the MSBs (most significant bits). ++ uint64_t elements_u64[4]; ++} wuffs_base__bitvec256; ++ ++static inline wuffs_base__bitvec256 // ++wuffs_base__make_bitvec256(uint64_t e00, ++ uint64_t e01, ++ uint64_t e02, ++ uint64_t e03) { ++ wuffs_base__bitvec256 res; ++ res.elements_u64[0] = e00; ++ res.elements_u64[1] = e01; ++ res.elements_u64[2] = e02; ++ res.elements_u64[3] = e03; ++ return res; ++} ++ ++static inline uint64_t // ++wuffs_base__bitvec256__get_u64(const wuffs_base__bitvec256* b, uint32_t i) { ++ return b->elements_u64[i & 3]; ++} ++ ++// -------- ++ ++// wuffs_base__optional_u63 is like a std::optional, but for C (not ++// just C++) and the value can only hold 63 bits (not 64). ++// ++// Do not manipulate repr directly; it is a private implementation detail. ++typedef struct wuffs_base__optional_u63__struct { ++ uint64_t repr; ++ ++#ifdef __cplusplus ++ inline bool has_value() const; ++ inline uint64_t value() const; ++ inline uint64_t value_or(uint64_t default_value) const; ++#endif // __cplusplus ++ ++} wuffs_base__optional_u63; ++ ++// wuffs_base__make_optional_u63 ignores value when has_value is false. ++// ++// Preconditions: ++// - value < (1 << 63). ++static inline wuffs_base__optional_u63 // ++wuffs_base__make_optional_u63(bool has_value, uint64_t value) { ++ wuffs_base__optional_u63 res; ++ res.repr = has_value ? ((value << 1u) | 1u) : 0u; ++ return res; ++} ++ ++static inline bool // ++wuffs_base__optional_u63__has_value(const wuffs_base__optional_u63* o) { ++ return o->repr; ++} ++ ++// wuffs_base__optional_u63__value returns zero when o does not have a value. ++static inline uint64_t // ++wuffs_base__optional_u63__value(const wuffs_base__optional_u63* o) { ++ return o->repr >> 1u; ++} ++ ++static inline uint64_t // ++wuffs_base__optional_u63__value_or(const wuffs_base__optional_u63* o, ++ uint64_t default_value) { ++ return o->repr ? (o->repr >> 1u) : default_value; ++} ++ ++#ifdef __cplusplus ++ ++inline bool // ++wuffs_base__optional_u63::has_value() const { ++ return wuffs_base__optional_u63__has_value(this); ++} ++ ++inline uint64_t // ++wuffs_base__optional_u63::value() const { ++ return wuffs_base__optional_u63__value(this); ++} ++ ++inline uint64_t // ++wuffs_base__optional_u63::value_or(uint64_t default_value) const { ++ return wuffs_base__optional_u63__value_or(this, default_value); ++} ++ ++#endif // __cplusplus ++ ++// -------- ++ + // The "defined(__clang__)" isn't redundant. While vanilla clang defines + // __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not. + #if (defined(__GNUC__) || defined(__clang__)) && (__SIZEOF_LONG__ == 8) +@@ -1529,7 +1732,7 @@ wuffs_base__make_slice_u64(uint64_t* ptr, size_t len) { + static inline wuffs_base__slice_u8 // + wuffs_base__make_slice_u8_ij(uint8_t* ptr, size_t i, size_t j) { + wuffs_base__slice_u8 ret; +- ret.ptr = ptr + i; ++ ret.ptr = ptr ? (ptr + i) : NULL; + ret.len = (j >= i) ? (j - i) : 0; + return ret; + } +@@ -1537,7 +1740,7 @@ wuffs_base__make_slice_u8_ij(uint8_t* ptr, size_t i, size_t j) { + static inline wuffs_base__slice_u16 // + wuffs_base__make_slice_u16_ij(uint16_t* ptr, size_t i, size_t j) { + wuffs_base__slice_u16 ret; +- ret.ptr = ptr + i; ++ ret.ptr = ptr ? (ptr + i) : NULL; + ret.len = (j >= i) ? (j - i) : 0; + return ret; + } +@@ -1545,7 +1748,7 @@ wuffs_base__make_slice_u16_ij(uint16_t* ptr, size_t i, size_t j) { + static inline wuffs_base__slice_u32 // + wuffs_base__make_slice_u32_ij(uint32_t* ptr, size_t i, size_t j) { + wuffs_base__slice_u32 ret; +- ret.ptr = ptr + i; ++ ret.ptr = ptr ? (ptr + i) : NULL; + ret.len = (j >= i) ? (j - i) : 0; + return ret; + } +@@ -1553,7 +1756,7 @@ wuffs_base__make_slice_u32_ij(uint32_t* ptr, size_t i, size_t j) { + static inline wuffs_base__slice_u64 // + wuffs_base__make_slice_u64_ij(uint64_t* ptr, size_t i, size_t j) { + wuffs_base__slice_u64 ret; +- ret.ptr = ptr + i; ++ ret.ptr = ptr ? (ptr + i) : NULL; + ret.len = (j >= i) ? (j - i) : 0; + return ret; + } +@@ -1696,7 +1899,7 @@ wuffs_base__slice_u8__subslice_i(wuffs_base__slice_u8 s, uint64_t i) { + if ((i <= SIZE_MAX) && (i <= s.len)) { + return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(s.len - i))); + } +- return wuffs_base__make_slice_u8(NULL, 0); ++ return wuffs_base__empty_slice_u8(); + } + + // wuffs_base__slice_u8__subslice_j returns s[:j]. +@@ -1707,7 +1910,7 @@ wuffs_base__slice_u8__subslice_j(wuffs_base__slice_u8 s, uint64_t j) { + if ((j <= SIZE_MAX) && (j <= s.len)) { + return wuffs_base__make_slice_u8(s.ptr, ((size_t)j)); + } +- return wuffs_base__make_slice_u8(NULL, 0); ++ return wuffs_base__empty_slice_u8(); + } + + // wuffs_base__slice_u8__subslice_ij returns s[i:j]. +@@ -1720,7 +1923,7 @@ wuffs_base__slice_u8__subslice_ij(wuffs_base__slice_u8 s, + if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) { + return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(j - i))); + } +- return wuffs_base__make_slice_u8(NULL, 0); ++ return wuffs_base__empty_slice_u8(); + } + + // wuffs_base__table_u8__subtable_ij returns t[ix:jx, iy:jy]. +@@ -1814,6 +2017,20 @@ WUFFS_BASE__MAYBE_STATIC int32_t // + wuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix_data, + bool prefix_closed); + ++// ---------------- Quirk Values ++ ++// These constants are the value half of a key-value pair, where the key is ++// WUFFS_BASE__QUIRK_QUALITY. ++// ++// In the Wuffs API, set_quirk takes a u64 value. These macro definitions are ++// likewise unsigned values (uint64_t) but for this particular key, they are ++// best interpreted as signed values (int64_t). "Lower-than-default quality" ++// and "higher-than-default quality", as signed values, are -1 and +1. ++// ++// See doc/note/quirks.md for some more discussion about trade-offs. ++#define WUFFS_BASE__QUIRK_QUALITY__VALUE__LOWER_QUALITY UINT64_MAX ++#define WUFFS_BASE__QUIRK_QUALITY__VALUE__HIGHER_QUALITY ((uint64_t)1) ++ + // ---------------- Ranges and Rects + + // See https://github.com/google/wuffs/blob/main/doc/note/ranges-and-rects.md +@@ -3011,7 +3228,8 @@ wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) { + // wuffs_base__io_buffer__compact_retaining moves any written but unread bytes + // closer to the start of the buffer. It retains H bytes of history (the most + // recently read bytes), where H is min(buf->meta.ri, history_retain_length). +-// A postcondition is that buf->meta.ri == H. ++// It is therefore a no-op if history_retain_length is UINT64_MAX. A ++// postcondition is that buf->meta.ri == H. + // + // wuffs_base__io_buffer__compact_retaining(0) is equivalent to + // wuffs_base__io_buffer__compact(). +@@ -3056,7 +3274,7 @@ wuffs_base__io_buffer__reader_length(const wuffs_base__io_buffer* buf) { + + static inline uint8_t* // + wuffs_base__io_buffer__reader_pointer(const wuffs_base__io_buffer* buf) { +- return buf ? (buf->data.ptr + buf->meta.ri) : NULL; ++ return (buf && buf->data.ptr) ? (buf->data.ptr + buf->meta.ri) : NULL; + } + + static inline uint64_t // +@@ -3066,7 +3284,8 @@ wuffs_base__io_buffer__reader_position(const wuffs_base__io_buffer* buf) { + + static inline wuffs_base__slice_u8 // + wuffs_base__io_buffer__reader_slice(const wuffs_base__io_buffer* buf) { +- return buf ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.ri, ++ return (buf && buf->data.ptr) ++ ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.ri, + buf->meta.wi - buf->meta.ri) + : wuffs_base__empty_slice_u8(); + } +@@ -3078,7 +3297,7 @@ wuffs_base__io_buffer__writer_length(const wuffs_base__io_buffer* buf) { + + static inline uint8_t* // + wuffs_base__io_buffer__writer_pointer(const wuffs_base__io_buffer* buf) { +- return buf ? (buf->data.ptr + buf->meta.wi) : NULL; ++ return (buf && buf->data.ptr) ? (buf->data.ptr + buf->meta.wi) : NULL; + } + + static inline uint64_t // +@@ -3088,7 +3307,8 @@ wuffs_base__io_buffer__writer_position(const wuffs_base__io_buffer* buf) { + + static inline wuffs_base__slice_u8 // + wuffs_base__io_buffer__writer_slice(const wuffs_base__io_buffer* buf) { +- return buf ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.wi, ++ return (buf && buf->data.ptr) ++ ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.wi, + buf->data.len - buf->meta.wi) + : wuffs_base__empty_slice_u8(); + } +@@ -3183,49 +3403,53 @@ wuffs_base__make_token(uint64_t repr) { + + // -------- + ++// clang-format off ++ ++// -------- ++ + #define WUFFS_BASE__TOKEN__LENGTH__MAX_INCL 0xFFFF + +-#define WUFFS_BASE__TOKEN__VALUE__SHIFT 17 +-#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT 17 +-#define WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT 42 +-#define WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT 17 ++#define WUFFS_BASE__TOKEN__VALUE__SHIFT 17 ++#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT 17 ++#define WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT 42 ++#define WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT 17 + #define WUFFS_BASE__TOKEN__VALUE_BASE_CATEGORY__SHIFT 38 +-#define WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT 17 +-#define WUFFS_BASE__TOKEN__CONTINUED__SHIFT 16 +-#define WUFFS_BASE__TOKEN__LENGTH__SHIFT 0 ++#define WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT 17 ++#define WUFFS_BASE__TOKEN__CONTINUED__SHIFT 16 ++#define WUFFS_BASE__TOKEN__LENGTH__SHIFT 0 + +-#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__NUM_BITS 46 ++#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__NUM_BITS 46 + + // -------- + +-#define WUFFS_BASE__TOKEN__VBC__FILLER 0 +-#define WUFFS_BASE__TOKEN__VBC__STRUCTURE 1 +-#define WUFFS_BASE__TOKEN__VBC__STRING 2 +-#define WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT 3 +-#define WUFFS_BASE__TOKEN__VBC__LITERAL 4 +-#define WUFFS_BASE__TOKEN__VBC__NUMBER 5 +-#define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED 6 ++#define WUFFS_BASE__TOKEN__VBC__FILLER 0 ++#define WUFFS_BASE__TOKEN__VBC__STRUCTURE 1 ++#define WUFFS_BASE__TOKEN__VBC__STRING 2 ++#define WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT 3 ++#define WUFFS_BASE__TOKEN__VBC__LITERAL 4 ++#define WUFFS_BASE__TOKEN__VBC__NUMBER 5 ++#define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED 6 + #define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED 7 + + // -------- + +-#define WUFFS_BASE__TOKEN__VBD__FILLER__PUNCTUATION 0x00001 ++#define WUFFS_BASE__TOKEN__VBD__FILLER__PUNCTUATION 0x00001 + #define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_BLOCK 0x00002 +-#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_LINE 0x00004 ++#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_LINE 0x00004 + + // COMMENT_ANY is a bit-wise or of COMMENT_BLOCK AND COMMENT_LINE. +-#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_ANY 0x00006 ++#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_ANY 0x00006 + + // -------- + +-#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH 0x00001 +-#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP 0x00002 ++#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH 0x00001 ++#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP 0x00002 + #define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE 0x00010 + #define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST 0x00020 + #define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT 0x00040 +-#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE 0x01000 +-#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST 0x02000 +-#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT 0x04000 ++#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE 0x01000 ++#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST 0x02000 ++#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT 0x04000 + + // -------- + +@@ -3245,11 +3469,11 @@ wuffs_base__make_token(uint64_t repr) { + // + // The lack of any particular bit is conservative: it is valid for all-ASCII + // strings, in a single- or multi-token chain, to have none of these bits set. +-#define WUFFS_BASE__TOKEN__VBD__STRING__DEFINITELY_UTF_8 0x00001 +-#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8 0x00002 ++#define WUFFS_BASE__TOKEN__VBD__STRING__DEFINITELY_UTF_8 0x00001 ++#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8 0x00002 + #define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_SHOULD_BE_UTF_8 0x00004 +-#define WUFFS_BASE__TOKEN__VBD__STRING__DEFINITELY_ASCII 0x00010 +-#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_ASCII 0x00020 ++#define WUFFS_BASE__TOKEN__VBD__STRING__DEFINITELY_ASCII 0x00010 ++#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_ASCII 0x00020 + #define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_SHOULD_BE_ASCII 0x00040 + + // CONVERT_D_DST_S_SRC means that multiples of S source bytes (possibly padded) +@@ -3264,22 +3488,22 @@ wuffs_base__make_token(uint64_t repr) { + // When src is the empty string, multiple conversion algorithms are applicable + // (so these bits are not necessarily mutually exclusive), all producing the + // same empty dst string. +-#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP 0x00100 +-#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY 0x00200 ++#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP 0x00100 ++#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY 0x00200 + #define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_2_SRC_HEXADECIMAL 0x00400 + #define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X 0x00800 + #define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_3_DST_4_SRC_BASE_64_STD 0x01000 + #define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_3_DST_4_SRC_BASE_64_URL 0x02000 +-#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_4_DST_5_SRC_ASCII_85 0x04000 ++#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_4_DST_5_SRC_ASCII_85 0x04000 + #define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_5_DST_8_SRC_BASE_32_HEX 0x08000 + #define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_5_DST_8_SRC_BASE_32_STD 0x10000 + + // -------- + + #define WUFFS_BASE__TOKEN__VBD__LITERAL__UNDEFINED 0x00001 +-#define WUFFS_BASE__TOKEN__VBD__LITERAL__NULL 0x00002 +-#define WUFFS_BASE__TOKEN__VBD__LITERAL__FALSE 0x00004 +-#define WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE 0x00008 ++#define WUFFS_BASE__TOKEN__VBD__LITERAL__NULL 0x00002 ++#define WUFFS_BASE__TOKEN__VBD__LITERAL__FALSE 0x00004 ++#define WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE 0x00008 + + // -------- + +@@ -3292,8 +3516,8 @@ wuffs_base__make_token(uint64_t repr) { + // For a source string of "+123" or "-0x9A", only the first two are valid. + // + // For a source string of "123.", only the first one is valid. +-#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT 0x00001 +-#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED 0x00002 ++#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT 0x00001 ++#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED 0x00002 + #define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED 0x00004 + + #define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF 0x00010 +@@ -3305,11 +3529,15 @@ wuffs_base__make_token(uint64_t repr) { + // "300", which are big-endian, little-endian or text. For binary formats, the + // token length (after adjusting for FORMAT_IGNORE_ETC) discriminates + // e.g. u16 little-endian vs u32 little-endian. +-#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN 0x00100 ++#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN 0x00100 + #define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_LITTLE_ENDIAN 0x00200 +-#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT 0x00400 ++#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT 0x00400 ++ ++#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE 0x01000 ++ ++// -------- + +-#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE 0x01000 ++// clang-format on + + // -------- + +@@ -3421,6 +3649,22 @@ wuffs_base__token::length() const { + + // -------- + ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wcast-qual" ++#endif ++ ++static inline wuffs_base__token* // ++wuffs_base__strip_const_from_token_ptr(const wuffs_base__token* ptr) { ++ return (wuffs_base__token*)ptr; ++} ++ ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ ++// -------- ++ + typedef WUFFS_BASE__SLICE(wuffs_base__token) wuffs_base__slice_token; + + static inline wuffs_base__slice_token // +@@ -3574,7 +3818,8 @@ wuffs_base__token_buffer__compact(wuffs_base__token_buffer* buf) { + // wuffs_base__token_buffer__compact_retaining moves any written but unread + // tokens closer to the start of the buffer. It retains H tokens of history + // (the most recently read tokens), where H is min(buf->meta.ri, +-// history_retain_length). A postcondition is that buf->meta.ri == H. ++// history_retain_length). It is therefore a no-op if history_retain_length is ++// UINT64_MAX. A postcondition is that buf->meta.ri == H. + // + // wuffs_base__token_buffer__compact_retaining(0) is equivalent to + // wuffs_base__token_buffer__compact(). +@@ -3730,51 +3975,51 @@ wuffs_base__token_buffer::writer_token_position() const { + // + // You can pass the C stdlib's malloc as the malloc_func. + // +-// It returns an empty slice (containing a NULL ptr field) if (num_uxx * +-// sizeof(uintxx_t)) would overflow SIZE_MAX. ++// It returns an empty slice (containing a NULL ptr field) if num_uxx is zero ++// or if (num_uxx * sizeof(uintxx_t)) would overflow SIZE_MAX. + + static inline wuffs_base__slice_u8 // + wuffs_base__malloc_slice_u8(void* (*malloc_func)(size_t), uint64_t num_u8) { +- if (malloc_func && (num_u8 <= (SIZE_MAX / sizeof(uint8_t)))) { ++ if (malloc_func && num_u8 && (num_u8 <= (SIZE_MAX / sizeof(uint8_t)))) { + void* p = (*malloc_func)((size_t)(num_u8 * sizeof(uint8_t))); + if (p) { + return wuffs_base__make_slice_u8((uint8_t*)(p), (size_t)num_u8); + } + } +- return wuffs_base__make_slice_u8(NULL, 0); ++ return wuffs_base__empty_slice_u8(); + } + + static inline wuffs_base__slice_u16 // + wuffs_base__malloc_slice_u16(void* (*malloc_func)(size_t), uint64_t num_u16) { +- if (malloc_func && (num_u16 <= (SIZE_MAX / sizeof(uint16_t)))) { ++ if (malloc_func && num_u16 && (num_u16 <= (SIZE_MAX / sizeof(uint16_t)))) { + void* p = (*malloc_func)((size_t)(num_u16 * sizeof(uint16_t))); + if (p) { + return wuffs_base__make_slice_u16((uint16_t*)(p), (size_t)num_u16); + } + } +- return wuffs_base__make_slice_u16(NULL, 0); ++ return wuffs_base__empty_slice_u16(); + } + + static inline wuffs_base__slice_u32 // + wuffs_base__malloc_slice_u32(void* (*malloc_func)(size_t), uint64_t num_u32) { +- if (malloc_func && (num_u32 <= (SIZE_MAX / sizeof(uint32_t)))) { ++ if (malloc_func && num_u32 && (num_u32 <= (SIZE_MAX / sizeof(uint32_t)))) { + void* p = (*malloc_func)((size_t)(num_u32 * sizeof(uint32_t))); + if (p) { + return wuffs_base__make_slice_u32((uint32_t*)(p), (size_t)num_u32); + } + } +- return wuffs_base__make_slice_u32(NULL, 0); ++ return wuffs_base__empty_slice_u32(); + } + + static inline wuffs_base__slice_u64 // + wuffs_base__malloc_slice_u64(void* (*malloc_func)(size_t), uint64_t num_u64) { +- if (malloc_func && (num_u64 <= (SIZE_MAX / sizeof(uint64_t)))) { ++ if (malloc_func && num_u64 && (num_u64 <= (SIZE_MAX / sizeof(uint64_t)))) { + void* p = (*malloc_func)((size_t)(num_u64 * sizeof(uint64_t))); + if (p) { + return wuffs_base__make_slice_u64((uint64_t*)(p), (size_t)num_u64); + } + } +- return wuffs_base__make_slice_u64(NULL, 0); ++ return wuffs_base__empty_slice_u64(); + } + + // ---------------- Images +@@ -3838,6 +4083,26 @@ wuffs_base__color_u32_argb_premul__as__color_u8_gray( + return (uint8_t)(weighted_average >> 24); + } + ++static inline uint16_t // ++wuffs_base__color_u32_argb_premul__as__color_u16_alpha_gray_nonpremul( ++ wuffs_base__color_u32_argb_premul c) { ++ uint32_t a = 0xFF & (c >> 24); ++ if (a == 0) { ++ return 0; ++ } ++ uint32_t a16 = a * 0x101; ++ ++ uint32_t cr = 0xFF & (c >> 16); ++ cr = (cr * (0x101 * 0xFFFF)) / a16; ++ uint32_t cg = 0xFF & (c >> 8); ++ cg = (cg * (0x101 * 0xFFFF)) / a16; ++ uint32_t cb = 0xFF & (c >> 0); ++ cb = (cb * (0x101 * 0xFFFF)) / a16; ++ ++ uint32_t weighted_average = (19595 * cr) + (38470 * cg) + (7471 * cb) + 32768; ++ return (uint16_t)((a16 & 0xFF00) | (weighted_average >> 24)); ++} ++ + static inline uint16_t // + wuffs_base__color_u32_argb_premul__as__color_u16_gray( + wuffs_base__color_u32_argb_premul c) { +@@ -4114,49 +4379,53 @@ wuffs_base__make_pixel_format(uint32_t repr) { + // Common 8-bit-depth pixel formats. This list is not exhaustive; not all valid + // wuffs_base__pixel_format values are present. + +-#define WUFFS_BASE__PIXEL_FORMAT__INVALID 0x00000000 ++// clang-format off ++ ++#define WUFFS_BASE__PIXEL_FORMAT__INVALID 0x00000000 + +-#define WUFFS_BASE__PIXEL_FORMAT__A 0x02000008 ++#define WUFFS_BASE__PIXEL_FORMAT__A 0x02000008 + +-#define WUFFS_BASE__PIXEL_FORMAT__Y 0x20000008 +-#define WUFFS_BASE__PIXEL_FORMAT__Y_16LE 0x2000000B +-#define WUFFS_BASE__PIXEL_FORMAT__Y_16BE 0x2010000B +-#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL 0x21000008 +-#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL 0x22000008 ++#define WUFFS_BASE__PIXEL_FORMAT__Y 0x20000008 ++#define WUFFS_BASE__PIXEL_FORMAT__Y_16LE 0x2000000B ++#define WUFFS_BASE__PIXEL_FORMAT__Y_16BE 0x2010000B ++#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL 0x21000088 ++#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL 0x22000088 + +-#define WUFFS_BASE__PIXEL_FORMAT__YCBCR 0x40020888 +-#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL 0x41038888 +-#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK 0x50038888 ++#define WUFFS_BASE__PIXEL_FORMAT__YCBCR 0x40020888 ++#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL 0x41038888 ++#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK 0x50038888 + +-#define WUFFS_BASE__PIXEL_FORMAT__YCOCG 0x60020888 +-#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL 0x61038888 +-#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK 0x70038888 ++#define WUFFS_BASE__PIXEL_FORMAT__YCOCG 0x60020888 ++#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL 0x61038888 ++#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK 0x70038888 + +-#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL 0x81040008 +-#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL 0x82040008 +-#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY 0x83040008 ++#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL 0x81040008 ++#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL 0x82040008 ++#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY 0x83040008 + +-#define WUFFS_BASE__PIXEL_FORMAT__BGR_565 0x80000565 +-#define WUFFS_BASE__PIXEL_FORMAT__BGR 0x80000888 +-#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL 0x81008888 +-#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE 0x8100BBBB +-#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL 0x82008888 +-#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE 0x8200BBBB +-#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY 0x83008888 +-#define WUFFS_BASE__PIXEL_FORMAT__BGRX 0x90008888 ++#define WUFFS_BASE__PIXEL_FORMAT__BGR_565 0x80000565 ++#define WUFFS_BASE__PIXEL_FORMAT__BGR 0x80000888 ++#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL 0x81008888 ++#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE 0x8100BBBB ++#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL 0x82008888 ++#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE 0x8200BBBB ++#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY 0x83008888 ++#define WUFFS_BASE__PIXEL_FORMAT__BGRX 0x90008888 + +-#define WUFFS_BASE__PIXEL_FORMAT__RGB 0xA0000888 +-#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL 0xA1008888 +-#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE 0xA100BBBB +-#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL 0xA2008888 +-#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE 0xA200BBBB +-#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY 0xA3008888 +-#define WUFFS_BASE__PIXEL_FORMAT__RGBX 0xB0008888 ++#define WUFFS_BASE__PIXEL_FORMAT__RGB 0xA0000888 ++#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL 0xA1008888 ++#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE 0xA100BBBB ++#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL 0xA2008888 ++#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE 0xA200BBBB ++#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY 0xA3008888 ++#define WUFFS_BASE__PIXEL_FORMAT__RGBX 0xB0008888 + +-#define WUFFS_BASE__PIXEL_FORMAT__CMY 0xC0020888 +-#define WUFFS_BASE__PIXEL_FORMAT__CMYK 0xD0038888 ++#define WUFFS_BASE__PIXEL_FORMAT__CMY 0xC0020888 ++#define WUFFS_BASE__PIXEL_FORMAT__CMYK 0xD0038888 + +-extern const uint32_t wuffs_base__pixel_format__bits_per_channel[16]; ++// clang-format on ++ ++extern const uint32_t wuffs_private_impl__pixel_format__bits_per_channel[16]; + + static inline bool // + wuffs_base__pixel_format__is_valid(const wuffs_base__pixel_format* f) { +@@ -4170,10 +4439,14 @@ wuffs_base__pixel_format__bits_per_pixel(const wuffs_base__pixel_format* f) { + if (((f->repr >> 16) & 0x03) != 0) { + return 0; + } +- return wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 0)] + +- wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 4)] + +- wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 8)] + +- wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 12)]; ++ return wuffs_private_impl__pixel_format__bits_per_channel[0x0F & ++ (f->repr >> 0)] + ++ wuffs_private_impl__pixel_format__bits_per_channel[0x0F & ++ (f->repr >> 4)] + ++ wuffs_private_impl__pixel_format__bits_per_channel[0x0F & ++ (f->repr >> 8)] + ++ wuffs_private_impl__pixel_format__bits_per_channel[0x0F & ++ (f->repr >> 12)]; + } + + static inline bool // +@@ -4391,15 +4664,20 @@ wuffs_base__pixel_config__set(wuffs_base__pixel_config* c, + return; + } + if (pixfmt_repr) { +- uint64_t wh = ((uint64_t)width) * ((uint64_t)height); +- // TODO: handle things other than 1 byte per pixel. +- if (wh <= ((uint64_t)SIZE_MAX)) { ++ do { ++#if SIZE_MAX < 0xFFFFFFFFFFFFFFFFull ++ uint64_t wh = ((uint64_t)width) * ((uint64_t)height); ++ // TODO: handle things other than 1 byte per pixel. ++ if (wh > ((uint64_t)SIZE_MAX)) { ++ break; ++ } ++#endif + c->private_impl.pixfmt.repr = pixfmt_repr; + c->private_impl.pixsub.repr = pixsub_repr; + c->private_impl.width = width; + c->private_impl.height = height; + return; +- } ++ } while (0); + } + + c->private_impl.pixfmt.repr = 0; +@@ -5117,7 +5395,7 @@ wuffs_base__pixel_buffer__palette(wuffs_base__pixel_buffer* pb) { + tab->ptr, WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH); + } + } +- return wuffs_base__make_slice_u8(NULL, 0); ++ return wuffs_base__empty_slice_u8(); + } + + static inline wuffs_base__slice_u8 // +@@ -6202,6 +6480,113 @@ struct wuffs_base__hasher_u64__struct { + + // -------- + ++extern const char wuffs_base__hasher_bitvec256__vtable_name[]; ++ ++typedef struct wuffs_base__hasher_bitvec256__func_ptrs__struct { ++ wuffs_base__bitvec256 (*checksum_bitvec256)( ++ const void* self); ++ uint64_t (*get_quirk)( ++ const void* self, ++ uint32_t a_key); ++ wuffs_base__status (*set_quirk)( ++ void* self, ++ uint32_t a_key, ++ uint64_t a_value); ++ wuffs_base__empty_struct (*update)( ++ void* self, ++ wuffs_base__slice_u8 a_x); ++ wuffs_base__bitvec256 (*update_bitvec256)( ++ void* self, ++ wuffs_base__slice_u8 a_x); ++} wuffs_base__hasher_bitvec256__func_ptrs; ++ ++typedef struct wuffs_base__hasher_bitvec256__struct wuffs_base__hasher_bitvec256; ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__bitvec256 ++wuffs_base__hasher_bitvec256__checksum_bitvec256( ++ const wuffs_base__hasher_bitvec256* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__hasher_bitvec256__get_quirk( ++ const wuffs_base__hasher_bitvec256* self, ++ uint32_t a_key); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__hasher_bitvec256__set_quirk( ++ wuffs_base__hasher_bitvec256* self, ++ uint32_t a_key, ++ uint64_t a_value); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_base__hasher_bitvec256__update( ++ wuffs_base__hasher_bitvec256* self, ++ wuffs_base__slice_u8 a_x); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__bitvec256 ++wuffs_base__hasher_bitvec256__update_bitvec256( ++ wuffs_base__hasher_bitvec256* self, ++ wuffs_base__slice_u8 a_x); ++ ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++struct wuffs_base__hasher_bitvec256__struct { ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable first_vtable; ++ } private_impl; ++ ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; ++#endif ++ ++ inline wuffs_base__bitvec256 ++ checksum_bitvec256() const { ++ return wuffs_base__hasher_bitvec256__checksum_bitvec256(this); ++ } ++ ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_base__hasher_bitvec256__get_quirk( ++ this, a_key); ++ } ++ ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_base__hasher_bitvec256__set_quirk( ++ this, a_key, a_value); ++ } ++ ++ inline wuffs_base__empty_struct ++ update( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_base__hasher_bitvec256__update( ++ this, a_x); ++ } ++ ++ inline wuffs_base__bitvec256 ++ update_bitvec256( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_base__hasher_bitvec256__update_bitvec256( ++ this, a_x); ++ } ++ ++#endif // __cplusplus ++}; // struct wuffs_base__hasher_bitvec256__struct ++ ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++// -------- ++ + extern const char wuffs_base__image_decoder__vtable_name[]; + + typedef struct wuffs_base__image_decoder__func_ptrs__struct { +@@ -6225,8 +6610,6 @@ typedef struct wuffs_base__image_decoder__func_ptrs__struct { + uint64_t (*get_quirk)( + const void* self, + uint32_t a_key); +- uint64_t (*history_retain_length)( +- const void* self); + uint32_t (*num_animation_loops)( + const void* self); + uint64_t (*num_decoded_frame_configs)( +@@ -6291,11 +6674,6 @@ wuffs_base__image_decoder__get_quirk( + const wuffs_base__image_decoder* self, + uint32_t a_key); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__image_decoder__history_retain_length( +- const wuffs_base__image_decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint32_t + wuffs_base__image_decoder__num_animation_loops( +@@ -6398,11 +6776,6 @@ struct wuffs_base__image_decoder__struct { + this, a_key); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_base__image_decoder__history_retain_length(this); +- } +- + inline uint32_t + num_animation_loops() const { + return wuffs_base__image_decoder__num_animation_loops(this); +@@ -6466,11 +6839,11 @@ struct wuffs_base__image_decoder__struct { + extern const char wuffs_base__io_transformer__vtable_name[]; + + typedef struct wuffs_base__io_transformer__func_ptrs__struct { ++ wuffs_base__optional_u63 (*dst_history_retain_length)( ++ const void* self); + uint64_t (*get_quirk)( + const void* self, + uint32_t a_key); +- uint64_t (*history_retain_length)( +- const void* self); + wuffs_base__status (*set_quirk)( + void* self, + uint32_t a_key, +@@ -6486,17 +6859,17 @@ typedef struct wuffs_base__io_transformer__func_ptrs__struct { + + typedef struct wuffs_base__io_transformer__struct wuffs_base__io_transformer; + ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_base__io_transformer__dst_history_retain_length( ++ const wuffs_base__io_transformer* self); ++ + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t + wuffs_base__io_transformer__get_quirk( + const wuffs_base__io_transformer* self, + uint32_t a_key); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__io_transformer__history_retain_length( +- const wuffs_base__io_transformer* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status + wuffs_base__io_transformer__set_quirk( +@@ -6531,6 +6904,11 @@ struct wuffs_base__io_transformer__struct { + using unique_ptr = std::unique_ptr; + #endif + ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_base__io_transformer__dst_history_retain_length(this); ++ } ++ + inline uint64_t + get_quirk( + uint32_t a_key) const { +@@ -6538,11 +6916,6 @@ struct wuffs_base__io_transformer__struct { + this, a_key); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_base__io_transformer__history_retain_length(this); +- } +- + inline wuffs_base__status + set_quirk( + uint32_t a_key, +@@ -6583,8 +6956,6 @@ typedef struct wuffs_base__token_decoder__func_ptrs__struct { + uint64_t (*get_quirk)( + const void* self, + uint32_t a_key); +- uint64_t (*history_retain_length)( +- const void* self); + wuffs_base__status (*set_quirk)( + void* self, + uint32_t a_key, +@@ -6609,11 +6980,6 @@ wuffs_base__token_decoder__get_quirk( + const wuffs_base__token_decoder* self, + uint32_t a_key); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__token_decoder__history_retain_length( +- const wuffs_base__token_decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status + wuffs_base__token_decoder__set_quirk( +@@ -6656,11 +7022,6 @@ struct wuffs_base__token_decoder__struct { + this, a_key); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_base__token_decoder__history_retain_length(this); +- } +- + inline wuffs_base__status + set_quirk( + uint32_t a_key, +@@ -6918,9 +7279,7 @@ extern const char wuffs_bmp__error__unsupported_bmp_file[]; + + // ---------------- Public Consts + +-#define WUFFS_BMP__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 +- +-#define WUFFS_BMP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_BMP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + + // ---------------- Struct Declarations + +@@ -7053,11 +7412,6 @@ wuffs_bmp__decoder__tell_me_more( + wuffs_base__more_information* a_minfo, + wuffs_base__io_buffer* a_src); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_bmp__decoder__history_retain_length( +- const wuffs_bmp__decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 + wuffs_bmp__decoder__workbuf_len( +@@ -7116,14 +7470,14 @@ struct wuffs_bmp__decoder__struct { + bool f_rle_padded; + wuffs_base__pixel_swizzler f_swizzler; + +- uint32_t p_decode_image_config[1]; +- uint32_t p_do_decode_image_config[1]; +- uint32_t p_decode_frame_config[1]; +- uint32_t p_do_decode_frame_config[1]; +- uint32_t p_decode_frame[1]; +- uint32_t p_do_decode_frame[1]; +- uint32_t p_tell_me_more[1]; +- uint32_t p_read_palette[1]; ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; ++ uint32_t p_tell_me_more; ++ uint32_t p_read_palette; + } private_impl; + + struct { +@@ -7132,14 +7486,14 @@ struct wuffs_bmp__decoder__struct { + + struct { + uint64_t scratch; +- } s_do_decode_image_config[1]; ++ } s_do_decode_image_config; + struct { + uint64_t scratch; +- } s_do_decode_frame[1]; ++ } s_do_decode_frame; + struct { + uint32_t v_i; + uint64_t scratch; +- } s_read_palette[1]; ++ } s_read_palette; + } private_data; + + #ifdef __cplusplus +@@ -7283,11 +7637,6 @@ struct wuffs_bmp__decoder__struct { + return wuffs_bmp__decoder__tell_me_more(this, a_dst, a_minfo, a_src); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_bmp__decoder__history_retain_length(this); +- } +- + inline wuffs_base__range_ii_u64 + workbuf_len() const { + return wuffs_bmp__decoder__workbuf_len(this); +@@ -7316,9 +7665,9 @@ extern const char wuffs_bzip2__error__unsupported_block_randomization[]; + + // ---------------- Public Consts + +-#define WUFFS_BZIP2__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_BZIP2__DECODER_DST_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0u + +-#define WUFFS_BZIP2__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_BZIP2__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + + // ---------------- Struct Declarations + +@@ -7386,8 +7735,8 @@ wuffs_bzip2__decoder__set_quirk( + uint64_t a_value); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_bzip2__decoder__history_retain_length( ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_bzip2__decoder__dst_history_retain_length( + const wuffs_bzip2__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE +@@ -7452,12 +7801,12 @@ struct wuffs_bzip2__decoder__struct { + uint32_t f_num_sections; + uint32_t f_code_lengths_bitmask; + +- uint32_t p_transform_io[1]; +- uint32_t p_do_transform_io[1]; +- uint32_t p_prepare_block[1]; +- uint32_t p_read_code_lengths[1]; +- uint32_t p_flush_slow[1]; +- uint32_t p_decode_huffman_slow[1]; ++ uint32_t p_transform_io; ++ uint32_t p_do_transform_io; ++ uint32_t p_prepare_block; ++ uint32_t p_read_code_lengths; ++ uint32_t p_flush_slow; ++ uint32_t p_decode_huffman_slow; + } private_impl; + + struct { +@@ -7474,15 +7823,15 @@ struct wuffs_bzip2__decoder__struct { + uint32_t v_i; + uint64_t v_tag; + uint32_t v_final_checksum_want; +- } s_do_transform_io[1]; ++ } s_do_transform_io; + struct { + uint32_t v_i; + uint32_t v_selector; +- } s_prepare_block[1]; ++ } s_prepare_block; + struct { + uint32_t v_i; + uint32_t v_code_length; +- } s_read_code_lengths[1]; ++ } s_read_code_lengths; + struct { + uint32_t v_flush_pointer; + uint32_t v_flush_repeat_count; +@@ -7491,10 +7840,10 @@ struct wuffs_bzip2__decoder__struct { + uint32_t v_block_size; + uint8_t v_curr; + uint64_t scratch; +- } s_flush_slow[1]; ++ } s_flush_slow; + struct { + uint32_t v_node_index; +- } s_decode_huffman_slow[1]; ++ } s_decode_huffman_slow; + } private_data; + + #ifdef __cplusplus +@@ -7572,9 +7921,9 @@ struct wuffs_bzip2__decoder__struct { + return wuffs_bzip2__decoder__set_quirk(this, a_key, a_value); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_bzip2__decoder__history_retain_length(this); ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_bzip2__decoder__dst_history_retain_length(this); + } + + inline wuffs_base__range_ii_u64 +@@ -7606,25 +7955,23 @@ extern const char wuffs_cbor__error__unsupported_recursion_depth[]; + + // ---------------- Public Consts + +-#define WUFFS_CBOR__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_CBOR__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + +-#define WUFFS_CBOR__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_CBOR__DECODER_DEPTH_MAX_INCL 1024u + +-#define WUFFS_CBOR__DECODER_DEPTH_MAX_INCL 1024 ++#define WUFFS_CBOR__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 2u + +-#define WUFFS_CBOR__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 2 ++#define WUFFS_CBOR__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 9u + +-#define WUFFS_CBOR__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 9 ++#define WUFFS_CBOR__TOKEN_VALUE_MAJOR 787997u + +-#define WUFFS_CBOR__TOKEN_VALUE_MAJOR 787997 ++#define WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK 262143u + +-#define WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK 262143 ++#define WUFFS_CBOR__TOKEN_VALUE_MINOR__MINUS_1_MINUS_X 16777216u + +-#define WUFFS_CBOR__TOKEN_VALUE_MINOR__MINUS_1_MINUS_X 16777216 ++#define WUFFS_CBOR__TOKEN_VALUE_MINOR__SIMPLE_VALUE 8388608u + +-#define WUFFS_CBOR__TOKEN_VALUE_MINOR__SIMPLE_VALUE 8388608 +- +-#define WUFFS_CBOR__TOKEN_VALUE_MINOR__TAG 4194304 ++#define WUFFS_CBOR__TOKEN_VALUE_MINOR__TAG 4194304u + + // ---------------- Struct Declarations + +@@ -7691,11 +8038,6 @@ wuffs_cbor__decoder__set_quirk( + uint32_t a_key, + uint64_t a_value); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_cbor__decoder__history_retain_length( +- const wuffs_cbor__decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 + wuffs_cbor__decoder__workbuf_len( +@@ -7738,7 +8080,7 @@ struct wuffs_cbor__decoder__struct { + + bool f_end_of_data; + +- uint32_t p_decode_tokens[1]; ++ uint32_t p_decode_tokens; + } private_impl; + + struct { +@@ -7750,7 +8092,7 @@ struct wuffs_cbor__decoder__struct { + uint32_t v_depth; + bool v_tagged; + uint8_t v_indefinite_string_major_type; +- } s_decode_tokens[1]; ++ } s_decode_tokens; + } private_data; + + #ifdef __cplusplus +@@ -7828,11 +8170,6 @@ struct wuffs_cbor__decoder__struct { + return wuffs_cbor__decoder__set_quirk(this, a_key, a_value); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_cbor__decoder__history_retain_length(this); +- } +- + inline wuffs_base__range_ii_u64 + workbuf_len() const { + return wuffs_cbor__decoder__workbuf_len(this); +@@ -8074,6 +8411,227 @@ struct wuffs_crc32__ieee_hasher__struct { + + #endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32) || defined(WUFFS_NONMONOLITHIC) + ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC64) || defined(WUFFS_NONMONOLITHIC) ++ ++// ---------------- Status Codes ++ ++// ---------------- Public Consts ++ ++// ---------------- Struct Declarations ++ ++typedef struct wuffs_crc64__ecma_hasher__struct wuffs_crc64__ecma_hasher; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++// ---------------- Public Initializer Prototypes ++ ++// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self, ++// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)". ++// ++// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version. ++// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_crc64__ecma_hasher__initialize( ++ wuffs_crc64__ecma_hasher* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options); ++ ++size_t ++sizeof__wuffs_crc64__ecma_hasher(void); ++ ++// ---------------- Allocs ++ ++// These functions allocate and initialize Wuffs structs. They return NULL if ++// memory allocation fails. If they return non-NULL, there is no need to call ++// wuffs_foo__bar__initialize, but the caller is responsible for eventually ++// calling free on the returned pointer. That pointer is effectively a C++ ++// std::unique_ptr. ++ ++wuffs_crc64__ecma_hasher* ++wuffs_crc64__ecma_hasher__alloc(void); ++ ++static inline wuffs_base__hasher_u64* ++wuffs_crc64__ecma_hasher__alloc_as__wuffs_base__hasher_u64(void) { ++ return (wuffs_base__hasher_u64*)(wuffs_crc64__ecma_hasher__alloc()); ++} ++ ++// ---------------- Upcasts ++ ++static inline wuffs_base__hasher_u64* ++wuffs_crc64__ecma_hasher__upcast_as__wuffs_base__hasher_u64( ++ wuffs_crc64__ecma_hasher* p) { ++ return (wuffs_base__hasher_u64*)p; ++} ++ ++// ---------------- Public Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_crc64__ecma_hasher__get_quirk( ++ const wuffs_crc64__ecma_hasher* self, ++ uint32_t a_key); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_crc64__ecma_hasher__set_quirk( ++ wuffs_crc64__ecma_hasher* self, ++ uint32_t a_key, ++ uint64_t a_value); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_crc64__ecma_hasher__update( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_crc64__ecma_hasher__update_u64( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_crc64__ecma_hasher__checksum_u64( ++ const wuffs_crc64__ecma_hasher* self); ++ ++#ifdef __cplusplus ++} // extern "C" ++#endif ++ ++// ---------------- Struct Definitions ++ ++// These structs' fields, and the sizeof them, are private implementation ++// details that aren't guaranteed to be stable across Wuffs versions. ++// ++// See https://en.wikipedia.org/wiki/Opaque_pointer#C ++ ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++struct wuffs_crc64__ecma_hasher__struct { ++ // Do not access the private_impl's or private_data's fields directly. There ++ // is no API/ABI compatibility or safety guarantee if you do so. Instead, use ++ // the wuffs_foo__bar__baz functions. ++ // ++ // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct ++ // can be stack allocated when WUFFS_IMPLEMENTATION is defined. ++ ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable vtable_for__wuffs_base__hasher_u64; ++ wuffs_base__vtable null_vtable; ++ ++ uint64_t f_state; ++ ++ wuffs_base__empty_struct (*choosy_up)( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x); ++ } private_impl; ++ ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; ++ ++ // On failure, the alloc_etc functions return nullptr. They don't throw. ++ ++ static inline unique_ptr ++ alloc() { ++ return unique_ptr(wuffs_crc64__ecma_hasher__alloc()); ++ } ++ ++ static inline wuffs_base__hasher_u64::unique_ptr ++ alloc_as__wuffs_base__hasher_u64() { ++ return wuffs_base__hasher_u64::unique_ptr( ++ wuffs_crc64__ecma_hasher__alloc_as__wuffs_base__hasher_u64()); ++ } ++#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ ++#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ // Disallow constructing or copying an object via standard C++ mechanisms, ++ // e.g. the "new" operator, as this struct is intentionally opaque. Its total ++ // size and field layout is not part of the public, stable, memory-safe API. ++ // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and ++ // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as ++ // their first argument) rather than tweaking bar.private_impl.qux fields. ++ // ++ // In C, we can just leave wuffs_foo__bar as an incomplete type (unless ++ // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in ++ // order to provide convenience methods. These forward on "this", so that you ++ // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". ++ wuffs_crc64__ecma_hasher__struct() = delete; ++ wuffs_crc64__ecma_hasher__struct(const wuffs_crc64__ecma_hasher__struct&) = delete; ++ wuffs_crc64__ecma_hasher__struct& operator=( ++ const wuffs_crc64__ecma_hasher__struct&) = delete; ++#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ ++#if !defined(WUFFS_IMPLEMENTATION) ++ // As above, the size of the struct is not part of the public API, and unless ++ // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap ++ // allocated, not stack allocated. Its size is not intended to be known at ++ // compile time, but it is unfortunately divulged as a side effect of ++ // defining C++ convenience methods. Use "sizeof__T()", calling the function, ++ // instead of "sizeof T", invoking the operator. To make the two values ++ // different, so that passing the latter will be rejected by the initialize ++ // function, we add an arbitrary amount of dead weight. ++ uint8_t dead_weight[123000000]; // 123 MB. ++#endif // !defined(WUFFS_IMPLEMENTATION) ++ ++ inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++ initialize( ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options) { ++ return wuffs_crc64__ecma_hasher__initialize( ++ this, sizeof_star_self, wuffs_version, options); ++ } ++ ++ inline wuffs_base__hasher_u64* ++ upcast_as__wuffs_base__hasher_u64() { ++ return (wuffs_base__hasher_u64*)this; ++ } ++ ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_crc64__ecma_hasher__get_quirk(this, a_key); ++ } ++ ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_crc64__ecma_hasher__set_quirk(this, a_key, a_value); ++ } ++ ++ inline wuffs_base__empty_struct ++ update( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_crc64__ecma_hasher__update(this, a_x); ++ } ++ ++ inline uint64_t ++ update_u64( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_crc64__ecma_hasher__update_u64(this, a_x); ++ } ++ ++ inline uint64_t ++ checksum_u64() const { ++ return wuffs_crc64__ecma_hasher__checksum_u64(this); ++ } ++ ++#endif // __cplusplus ++}; // struct wuffs_crc64__ecma_hasher__struct ++ ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC64) || defined(WUFFS_NONMONOLITHIC) ++ + #if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE) || defined(WUFFS_NONMONOLITHIC) + + // ---------------- Status Codes +@@ -8095,9 +8653,9 @@ extern const char wuffs_deflate__error__truncated_input[]; + + // ---------------- Public Consts + +-#define WUFFS_DEFLATE__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_DEFLATE__DECODER_DST_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0u + +-#define WUFFS_DEFLATE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1 ++#define WUFFS_DEFLATE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1u + + // ---------------- Struct Declarations + +@@ -8171,8 +8729,8 @@ wuffs_deflate__decoder__set_quirk( + uint64_t a_value); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_deflate__decoder__history_retain_length( ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_deflate__decoder__dst_history_retain_length( + const wuffs_deflate__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE +@@ -8222,16 +8780,16 @@ struct wuffs_deflate__decoder__struct { + uint32_t f_n_huffs_bits[2]; + bool f_end_of_block; + +- uint32_t p_transform_io[1]; +- uint32_t p_do_transform_io[1]; +- uint32_t p_decode_blocks[1]; +- uint32_t p_decode_uncompressed[1]; +- uint32_t p_init_dynamic_huffman[1]; ++ uint32_t p_transform_io; ++ uint32_t p_do_transform_io; ++ uint32_t p_decode_blocks; ++ uint32_t p_decode_uncompressed; ++ uint32_t p_init_dynamic_huffman; + wuffs_base__status (*choosy_decode_huffman_fast64)( + wuffs_deflate__decoder* self, + wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src); +- uint32_t p_decode_huffman_slow[1]; ++ uint32_t p_decode_huffman_slow; + } private_impl; + + struct { +@@ -8241,11 +8799,11 @@ struct wuffs_deflate__decoder__struct { + + struct { + uint32_t v_final; +- } s_decode_blocks[1]; ++ } s_decode_blocks; + struct { + uint32_t v_length; + uint64_t scratch; +- } s_decode_uncompressed[1]; ++ } s_decode_uncompressed; + struct { + uint32_t v_bits; + uint32_t v_n_bits; +@@ -8257,7 +8815,7 @@ struct wuffs_deflate__decoder__struct { + uint32_t v_n_extra_bits; + uint8_t v_rep_symbol; + uint32_t v_rep_count; +- } s_init_dynamic_huffman[1]; ++ } s_init_dynamic_huffman; + struct { + uint32_t v_bits; + uint32_t v_n_bits; +@@ -8269,7 +8827,7 @@ struct wuffs_deflate__decoder__struct { + uint32_t v_length; + uint32_t v_dist_minus_1; + uint64_t scratch; +- } s_decode_huffman_slow[1]; ++ } s_decode_huffman_slow; + } private_data; + + #ifdef __cplusplus +@@ -8353,9 +8911,9 @@ struct wuffs_deflate__decoder__struct { + return wuffs_deflate__decoder__set_quirk(this, a_key, a_value); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_deflate__decoder__history_retain_length(this); ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_deflate__decoder__dst_history_retain_length(this); + } + + inline wuffs_base__range_ii_u64 +@@ -8393,23 +8951,21 @@ extern const char wuffs_gif__error__truncated_input[]; + + // ---------------- Public Consts + +-#define WUFFS_GIF__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_GIF__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + +-#define WUFFS_GIF__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_GIF__QUIRK_DELAY_NUM_DECODED_FRAMES 1041635328u + +-#define WUFFS_GIF__QUIRK_DELAY_NUM_DECODED_FRAMES 1041635328 ++#define WUFFS_GIF__QUIRK_FIRST_FRAME_LOCAL_PALETTE_MEANS_BLACK_BACKGROUND 1041635329u + +-#define WUFFS_GIF__QUIRK_FIRST_FRAME_LOCAL_PALETTE_MEANS_BLACK_BACKGROUND 1041635329 ++#define WUFFS_GIF__QUIRK_HONOR_BACKGROUND_COLOR 1041635330u + +-#define WUFFS_GIF__QUIRK_HONOR_BACKGROUND_COLOR 1041635330 ++#define WUFFS_GIF__QUIRK_IGNORE_TOO_MUCH_PIXEL_DATA 1041635331u + +-#define WUFFS_GIF__QUIRK_IGNORE_TOO_MUCH_PIXEL_DATA 1041635331 ++#define WUFFS_GIF__QUIRK_IMAGE_BOUNDS_ARE_STRICT 1041635332u + +-#define WUFFS_GIF__QUIRK_IMAGE_BOUNDS_ARE_STRICT 1041635332 ++#define WUFFS_GIF__QUIRK_REJECT_EMPTY_FRAME 1041635333u + +-#define WUFFS_GIF__QUIRK_REJECT_EMPTY_FRAME 1041635333 +- +-#define WUFFS_GIF__QUIRK_REJECT_EMPTY_PALETTE 1041635334 ++#define WUFFS_GIF__QUIRK_REJECT_EMPTY_PALETTE 1041635334u + + // ---------------- Struct Declarations + +@@ -8518,11 +9074,6 @@ WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 + wuffs_gif__decoder__frame_dirty_rect( + const wuffs_gif__decoder* self); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_gif__decoder__history_retain_length( +- const wuffs_gif__decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 + wuffs_gif__decoder__workbuf_len( +@@ -8627,25 +9178,25 @@ struct wuffs_gif__decoder__struct { + uint32_t f_lzw_read_from_return_value; + uint16_t f_lzw_prefixes[4096]; + +- uint32_t p_decode_image_config[1]; +- uint32_t p_do_decode_image_config[1]; +- uint32_t p_tell_me_more[1]; +- uint32_t p_do_tell_me_more[1]; +- uint32_t p_decode_frame_config[1]; +- uint32_t p_do_decode_frame_config[1]; +- uint32_t p_skip_frame[1]; +- uint32_t p_decode_frame[1]; +- uint32_t p_do_decode_frame[1]; +- uint32_t p_decode_up_to_id_part1[1]; +- uint32_t p_decode_header[1]; +- uint32_t p_decode_lsd[1]; +- uint32_t p_decode_extension[1]; +- uint32_t p_skip_blocks[1]; +- uint32_t p_decode_ae[1]; +- uint32_t p_decode_gc[1]; +- uint32_t p_decode_id_part0[1]; +- uint32_t p_decode_id_part1[1]; +- uint32_t p_decode_id_part2[1]; ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_tell_me_more; ++ uint32_t p_do_tell_me_more; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_skip_frame; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; ++ uint32_t p_decode_up_to_id_part1; ++ uint32_t p_decode_header; ++ uint32_t p_decode_lsd; ++ uint32_t p_decode_extension; ++ uint32_t p_skip_blocks; ++ uint32_t p_decode_ae; ++ uint32_t p_decode_gc; ++ uint32_t p_decode_id_part0; ++ uint32_t p_decode_id_part1; ++ uint32_t p_decode_id_part2; + } private_impl; + + struct { +@@ -8658,24 +9209,23 @@ struct wuffs_gif__decoder__struct { + + struct { + uint32_t v_background_color; +- } s_do_decode_frame_config[1]; ++ } s_do_decode_frame_config; + struct { + uint64_t scratch; +- } s_skip_frame[1]; ++ } s_skip_frame; + struct { +- uint8_t v_c[6]; +- uint32_t v_i; +- } s_decode_header[1]; ++ uint64_t scratch; ++ } s_decode_header; + struct { + uint8_t v_flags; + uint8_t v_background_color_index; + uint32_t v_num_palette_entries; + uint32_t v_i; + uint64_t scratch; +- } s_decode_lsd[1]; ++ } s_decode_lsd; + struct { + uint64_t scratch; +- } s_skip_blocks[1]; ++ } s_skip_blocks; + struct { + uint8_t v_block_size; + bool v_is_animexts; +@@ -8683,24 +9233,24 @@ struct wuffs_gif__decoder__struct { + bool v_is_iccp; + bool v_is_xmp; + uint64_t scratch; +- } s_decode_ae[1]; ++ } s_decode_ae; + struct { + uint64_t scratch; +- } s_decode_gc[1]; ++ } s_decode_gc; + struct { + uint64_t scratch; +- } s_decode_id_part0[1]; ++ } s_decode_id_part0; + struct { + uint8_t v_which_palette; + uint32_t v_num_palette_entries; + uint32_t v_i; + uint64_t scratch; +- } s_decode_id_part1[1]; ++ } s_decode_id_part1; + struct { + uint64_t v_block_size; + bool v_need_block_size; + uint64_t scratch; +- } s_decode_id_part2[1]; ++ } s_decode_id_part2; + } private_data; + + #ifdef __cplusplus +@@ -8820,11 +9370,6 @@ struct wuffs_gif__decoder__struct { + return wuffs_gif__decoder__frame_dirty_rect(this); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_gif__decoder__history_retain_length(this); +- } +- + inline wuffs_base__range_ii_u64 + workbuf_len() const { + return wuffs_gif__decoder__workbuf_len(this); +@@ -8873,9 +9418,9 @@ extern const char wuffs_gzip__error__truncated_input[]; + + // ---------------- Public Consts + +-#define WUFFS_GZIP__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_GZIP__DECODER_DST_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0u + +-#define WUFFS_GZIP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1 ++#define WUFFS_GZIP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1u + + // ---------------- Struct Declarations + +@@ -8943,8 +9488,8 @@ wuffs_gzip__decoder__set_quirk( + uint64_t a_value); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_gzip__decoder__history_retain_length( ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_gzip__decoder__dst_history_retain_length( + const wuffs_gzip__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE +@@ -8989,8 +9534,8 @@ struct wuffs_gzip__decoder__struct { + + bool f_ignore_checksum; + +- uint32_t p_transform_io[1]; +- uint32_t p_do_transform_io[1]; ++ uint32_t p_transform_io; ++ uint32_t p_do_transform_io; + } private_impl; + + struct { +@@ -8999,11 +9544,11 @@ struct wuffs_gzip__decoder__struct { + + struct { + uint8_t v_flags; +- uint32_t v_checksum_got; +- uint32_t v_decoded_length_got; ++ uint32_t v_checksum_have; ++ uint32_t v_decoded_length_have; + uint32_t v_checksum_want; + uint64_t scratch; +- } s_do_transform_io[1]; ++ } s_do_transform_io; + } private_data; + + #ifdef __cplusplus +@@ -9081,9 +9626,9 @@ struct wuffs_gzip__decoder__struct { + return wuffs_gzip__decoder__set_quirk(this, a_key, a_value); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_gzip__decoder__history_retain_length(this); ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_gzip__decoder__dst_history_retain_length(this); + } + + inline wuffs_base__range_ii_u64 +@@ -9117,8 +9662,10 @@ extern const char wuffs_jpeg__error__bad_sof_marker[]; + extern const char wuffs_jpeg__error__bad_sos_marker[]; + extern const char wuffs_jpeg__error__bad_header[]; + extern const char wuffs_jpeg__error__bad_marker[]; ++extern const char wuffs_jpeg__error__bad_scan_count[]; + extern const char wuffs_jpeg__error__missing_huffman_table[]; + extern const char wuffs_jpeg__error__missing_quantization_table[]; ++extern const char wuffs_jpeg__error__rejected_progressive_jpeg[]; + extern const char wuffs_jpeg__error__truncated_input[]; + extern const char wuffs_jpeg__error__unsupported_arithmetic_coding[]; + extern const char wuffs_jpeg__error__unsupported_color_model[]; +@@ -9134,9 +9681,9 @@ extern const char wuffs_jpeg__error__unsupported_scan_count[]; + + // ---------------- Public Consts + +-#define WUFFS_JPEG__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_JPEG__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 51552191232u + +-#define WUFFS_JPEG__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 51552191232 ++#define WUFFS_JPEG__QUIRK_REJECT_PROGRESSIVE_JPEGS 1220532224u + + // ---------------- Struct Declarations + +@@ -9269,11 +9816,6 @@ wuffs_jpeg__decoder__tell_me_more( + wuffs_base__more_information* a_minfo, + wuffs_base__io_buffer* a_src); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_jpeg__decoder__history_retain_length( +- const wuffs_jpeg__decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 + wuffs_jpeg__decoder__workbuf_len( +@@ -9368,6 +9910,13 @@ struct wuffs_jpeg__decoder__struct { + uint32_t f_bitstream_ri; + uint32_t f_bitstream_wi; + bool f_bitstream_is_closed; ++ bool f_expect_multiple_scans; ++ bool f_use_lower_quality; ++ bool f_reject_progressive_jpegs; ++ bool f_swizzle_immediately; ++ wuffs_base__status f_swizzle_immediately_status; ++ uint32_t f_swizzle_immediately_b_offsets[10]; ++ uint32_t f_swizzle_immediately_c_offsets[5]; + uint32_t f_bitstream_padding; + uint16_t f_quant_tables[4][64]; + uint16_t f_saved_quant_tables[4][64]; +@@ -9381,28 +9930,29 @@ struct wuffs_jpeg__decoder__struct { + wuffs_base__slice_u8 a_dst_buffer, + uint64_t a_dst_stride, + uint32_t a_q); +- uint32_t p_decode_image_config[1]; +- uint32_t p_do_decode_image_config[1]; +- uint32_t p_decode_dqt[1]; +- uint32_t p_decode_dri[1]; +- uint32_t p_decode_appn[1]; +- uint32_t p_decode_sof[1]; +- uint32_t p_decode_frame_config[1]; +- uint32_t p_do_decode_frame_config[1]; +- uint32_t p_decode_frame[1]; +- uint32_t p_do_decode_frame[1]; +- uint32_t p_decode_dht[1]; +- uint32_t p_decode_sos[1]; +- uint32_t p_prepare_scan[1]; ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_decode_dqt; ++ uint32_t p_decode_dri; ++ uint32_t p_decode_appn; ++ uint32_t p_decode_sof; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; ++ uint32_t p_decode_dht; ++ uint32_t p_decode_sos; ++ uint32_t p_prepare_scan; + wuffs_base__empty_struct (*choosy_load_mcu_blocks_for_single_component)( + wuffs_jpeg__decoder* self, + uint32_t a_mx, + uint32_t a_my, + wuffs_base__slice_u8 a_workbuf, + uint32_t a_csel); +- uint32_t p_skip_past_the_next_restart_marker[1]; ++ uint32_t p_skip_past_the_next_restart_marker; + uint32_t (*choosy_decode_mcu)( + wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, + wuffs_base__slice_u8 a_workbuf, + uint32_t a_mx, + uint32_t a_my); +@@ -9411,6 +9961,7 @@ struct wuffs_jpeg__decoder__struct { + struct { + uint8_t f_bitstream_buffer[2048]; + uint16_t f_mcu_blocks[10][64]; ++ uint8_t f_swizzle_immediately_buffer[640]; + uint8_t f_swizzle_ycck_scratch_buffer_2k[2048]; + uint8_t f_dht_temp_counts[16]; + uint8_t f_dht_temp_bit_lengths[256]; +@@ -9420,38 +9971,38 @@ struct wuffs_jpeg__decoder__struct { + struct { + uint8_t v_marker; + uint64_t scratch; +- } s_do_decode_image_config[1]; ++ } s_do_decode_image_config; + struct { + uint8_t v_q; + uint32_t v_i; +- } s_decode_dqt[1]; ++ } s_decode_dqt; + struct { + uint64_t scratch; +- } s_decode_dri[1]; ++ } s_decode_dri; + struct { + uint64_t scratch; +- } s_decode_appn[1]; ++ } s_decode_appn; + struct { + uint32_t v_i; + uint64_t scratch; +- } s_decode_sof[1]; ++ } s_decode_sof; + struct { + uint8_t v_marker; + uint64_t scratch; +- } s_do_decode_frame[1]; ++ } s_do_decode_frame; + struct { + uint8_t v_tc4_th; + uint32_t v_total_count; + uint32_t v_i; +- } s_decode_dht[1]; ++ } s_decode_dht; + struct { + uint32_t v_my; + uint32_t v_mx; +- } s_decode_sos[1]; ++ } s_decode_sos; + struct { + uint32_t v_i; + uint64_t scratch; +- } s_prepare_scan[1]; ++ } s_prepare_scan; + } private_data; + + #ifdef __cplusplus +@@ -9595,11 +10146,6 @@ struct wuffs_jpeg__decoder__struct { + return wuffs_jpeg__decoder__tell_me_more(this, a_dst, a_minfo, a_src); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_jpeg__decoder__history_retain_length(this); +- } +- + inline wuffs_base__range_ii_u64 + workbuf_len() const { + return wuffs_jpeg__decoder__workbuf_len(this); +@@ -9627,55 +10173,53 @@ extern const char wuffs_json__error__unsupported_recursion_depth[]; + + // ---------------- Public Consts + +-#define WUFFS_JSON__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 +- +-#define WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + +-#define WUFFS_JSON__DECODER_DEPTH_MAX_INCL 1024 ++#define WUFFS_JSON__DECODER_DEPTH_MAX_INCL 1024u + +-#define WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 1 ++#define WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 1u + +-#define WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 100 ++#define WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 100u + +-#define WUFFS_JSON__QUIRK_ALLOW_ASCII_CONTROL_CODES 1225364480 ++#define WUFFS_JSON__QUIRK_ALLOW_ASCII_CONTROL_CODES 1225364480u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A 1225364481 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A 1225364481u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U 1225364482 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U 1225364482u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_E 1225364483 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_E 1225364483u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_NEW_LINE 1225364484 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_NEW_LINE 1225364484u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_QUESTION_MARK 1225364485 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_QUESTION_MARK 1225364485u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_SINGLE_QUOTE 1225364486 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_SINGLE_QUOTE 1225364486u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V 1225364487 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V 1225364487u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X_AS_CODE_POINTS 1225364489 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X_AS_CODE_POINTS 1225364489u + +-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO 1225364490 ++#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO 1225364490u + +-#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK 1225364491 ++#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK 1225364491u + +-#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE 1225364492 ++#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE 1225364492u + +-#define WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA 1225364493 ++#define WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA 1225364493u + +-#define WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS 1225364494 ++#define WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS 1225364494u + +-#define WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR 1225364495 ++#define WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR 1225364495u + +-#define WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK 1225364496 ++#define WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK 1225364496u + +-#define WUFFS_JSON__QUIRK_ALLOW_TRAILING_FILLER 1225364497 ++#define WUFFS_JSON__QUIRK_ALLOW_TRAILING_FILLER 1225364497u + +-#define WUFFS_JSON__QUIRK_EXPECT_TRAILING_NEW_LINE_OR_EOF 1225364498 ++#define WUFFS_JSON__QUIRK_EXPECT_TRAILING_NEW_LINE_OR_EOF 1225364498u + +-#define WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_N_TILDE_R_TILDE_T 1225364499 ++#define WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_N_TILDE_R_TILDE_T 1225364499u + +-#define WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE 1225364500 ++#define WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE 1225364500u + + // ---------------- Struct Declarations + +@@ -9742,11 +10286,6 @@ wuffs_json__decoder__set_quirk( + uint32_t a_key, + uint64_t a_value); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_json__decoder__history_retain_length( +- const wuffs_json__decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 + wuffs_json__decoder__workbuf_len( +@@ -9794,11 +10333,11 @@ struct wuffs_json__decoder__struct { + uint8_t f_trailer_stop; + uint8_t f_comment_type; + +- uint32_t p_decode_tokens[1]; +- uint32_t p_decode_leading[1]; +- uint32_t p_decode_comment[1]; +- uint32_t p_decode_inf_nan[1]; +- uint32_t p_decode_trailer[1]; ++ uint32_t p_decode_tokens; ++ uint32_t p_decode_leading; ++ uint32_t p_decode_comment; ++ uint32_t p_decode_inf_nan; ++ uint32_t p_decode_trailer; + } private_impl; + + struct { +@@ -9808,7 +10347,7 @@ struct wuffs_json__decoder__struct { + uint32_t v_depth; + uint32_t v_expect; + uint32_t v_expect_after_value; +- } s_decode_tokens[1]; ++ } s_decode_tokens; + } private_data; + + #ifdef __cplusplus +@@ -9886,11 +10425,6 @@ struct wuffs_json__decoder__struct { + return wuffs_json__decoder__set_quirk(this, a_key, a_value); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_json__decoder__history_retain_length(this); +- } +- + inline wuffs_base__range_ii_u64 + workbuf_len() const { + return wuffs_json__decoder__workbuf_len(this); +@@ -9911,24 +10445,33 @@ struct wuffs_json__decoder__struct { + + #endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON) || defined(WUFFS_NONMONOLITHIC) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) || defined(WUFFS_NONMONOLITHIC) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZMA) || defined(WUFFS_NONMONOLITHIC) + + // ---------------- Status Codes + +-extern const char wuffs_lzw__error__bad_code[]; +-extern const char wuffs_lzw__error__truncated_input[]; ++extern const char wuffs_lzma__error__bad_lzma2_header[]; ++extern const char wuffs_lzma__error__bad_bitstream_trailer[]; ++extern const char wuffs_lzma__error__bad_code[]; ++extern const char wuffs_lzma__error__bad_decoded_length[]; ++extern const char wuffs_lzma__error__bad_distance[]; ++extern const char wuffs_lzma__error__bad_header[]; ++extern const char wuffs_lzma__error__truncated_input[]; ++extern const char wuffs_lzma__error__unsupported_decoded_length[]; ++extern const char wuffs_lzma__error__unsupported_properties[]; + + // ---------------- Public Consts + +-#define WUFFS_LZW__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_LZMA__DECODER_DST_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0u + +-#define WUFFS_LZW__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_LZMA__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 4294967568u + +-#define WUFFS_LZW__QUIRK_LITERAL_WIDTH_PLUS_ONE 1348378624 ++#define WUFFS_LZMA__QUIRK_ALLOW_NON_ZERO_INITIAL_BYTE 1348001792u ++ ++#define WUFFS_LZMA__QUIRK_FORMAT_EXTENSION 1348001793u + + // ---------------- Struct Declarations + +-typedef struct wuffs_lzw__decoder__struct wuffs_lzw__decoder; ++typedef struct wuffs_lzma__decoder__struct wuffs_lzma__decoder; + + #ifdef __cplusplus + extern "C" { +@@ -9943,14 +10486,14 @@ extern "C" { + // Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_lzw__decoder__initialize( +- wuffs_lzw__decoder* self, ++wuffs_lzma__decoder__initialize( ++ wuffs_lzma__decoder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options); + + size_t +-sizeof__wuffs_lzw__decoder(void); ++sizeof__wuffs_lzma__decoder(void); + + // ---------------- Allocs + +@@ -9960,19 +10503,19 @@ sizeof__wuffs_lzw__decoder(void); + // calling free on the returned pointer. That pointer is effectively a C++ + // std::unique_ptr. + +-wuffs_lzw__decoder* +-wuffs_lzw__decoder__alloc(void); ++wuffs_lzma__decoder* ++wuffs_lzma__decoder__alloc(void); + + static inline wuffs_base__io_transformer* +-wuffs_lzw__decoder__alloc_as__wuffs_base__io_transformer(void) { +- return (wuffs_base__io_transformer*)(wuffs_lzw__decoder__alloc()); ++wuffs_lzma__decoder__alloc_as__wuffs_base__io_transformer(void) { ++ return (wuffs_base__io_transformer*)(wuffs_lzma__decoder__alloc()); + } + + // ---------------- Upcasts + + static inline wuffs_base__io_transformer* +-wuffs_lzw__decoder__upcast_as__wuffs_base__io_transformer( +- wuffs_lzw__decoder* p) { ++wuffs_lzma__decoder__upcast_as__wuffs_base__io_transformer( ++ wuffs_lzma__decoder* p) { + return (wuffs_base__io_transformer*)p; + } + +@@ -9980,40 +10523,35 @@ wuffs_lzw__decoder__upcast_as__wuffs_base__io_transformer( + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_lzw__decoder__get_quirk( +- const wuffs_lzw__decoder* self, ++wuffs_lzma__decoder__get_quirk( ++ const wuffs_lzma__decoder* self, + uint32_t a_key); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_lzw__decoder__set_quirk( +- wuffs_lzw__decoder* self, ++wuffs_lzma__decoder__set_quirk( ++ wuffs_lzma__decoder* self, + uint32_t a_key, + uint64_t a_value); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_lzw__decoder__history_retain_length( +- const wuffs_lzw__decoder* self); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_lzma__decoder__dst_history_retain_length( ++ const wuffs_lzma__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_lzw__decoder__workbuf_len( +- const wuffs_lzw__decoder* self); ++wuffs_lzma__decoder__workbuf_len( ++ const wuffs_lzma__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_lzw__decoder__transform_io( +- wuffs_lzw__decoder* self, ++wuffs_lzma__decoder__transform_io( ++ wuffs_lzma__decoder* self, + wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src, + wuffs_base__slice_u8 a_workbuf); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8 +-wuffs_lzw__decoder__flush( +- wuffs_lzw__decoder* self); +- + #ifdef __cplusplus + } // extern "C" + #endif +@@ -10027,7 +10565,7 @@ wuffs_lzw__decoder__flush( + + #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-struct wuffs_lzw__decoder__struct { ++struct wuffs_lzma__decoder__struct { + // Do not access the private_impl's or private_data's fields directly. There + // is no API/ABI compatibility or safety guarantee if you do so. Instead, use + // the wuffs_foo__bar__baz functions. +@@ -10041,45 +10579,113 @@ struct wuffs_lzw__decoder__struct { + wuffs_base__vtable vtable_for__wuffs_base__io_transformer; + wuffs_base__vtable null_vtable; + +- uint32_t f_pending_literal_width_plus_one; +- uint32_t f_literal_width; +- uint32_t f_clear_code; +- uint32_t f_end_code; +- uint32_t f_save_code; +- uint32_t f_prev_code; +- uint32_t f_width; +- uint32_t f_bits; +- uint32_t f_n_bits; +- uint32_t f_output_ri; +- uint32_t f_output_wi; +- uint32_t f_read_from_return_value; +- uint16_t f_prefixes[4096]; +- +- uint32_t p_transform_io[1]; +- uint32_t p_write_to[1]; ++ uint32_t f_lc; ++ uint32_t f_lp; ++ uint32_t f_pb; ++ uint32_t f_format_extension; ++ uint32_t f_dict_size; ++ uint32_t f_dict_workbuf_index; ++ uint32_t f_dict_seen; ++ uint64_t f_decoded_length; ++ uint64_t f_lzma2_encoded_length_have; ++ uint64_t f_lzma2_encoded_length_want; ++ bool f_lzma2_need_prob_reset; ++ bool f_lzma2_need_properties; ++ bool f_lzma2_need_dict_reset; ++ bool f_prev_lzma2_chunk_was_uncompressed; ++ bool f_allow_non_zero_initial_byte; ++ bool f_end_of_chunk; ++ uint8_t f_stashed_bytes[2]; ++ uint32_t f_stashed_bits; ++ uint32_t f_stashed_range; ++ uint32_t f_stashed_state; ++ uint32_t f_stashed_rep0; ++ uint32_t f_stashed_rep1; ++ uint32_t f_stashed_rep2; ++ uint32_t f_stashed_rep3; ++ uint64_t f_stashed_pos; ++ uint64_t f_stashed_pos_end; ++ ++ uint32_t p_decode_bitstream_slow; ++ uint32_t p_transform_io; ++ uint32_t p_do_transform_io; ++ uint32_t p_decode_bitstream; ++ uint32_t p_update_stashed_bytes; ++ uint32_t p_decode_optional_end_of_stream; + } private_impl; + + struct { +- uint8_t f_suffixes[4096][8]; +- uint16_t f_lm1s[4096]; +- uint8_t f_output[8199]; ++ uint16_t f_probs_ao00[192]; ++ uint16_t f_probs_ao20[12]; ++ uint16_t f_probs_ao40[12]; ++ uint16_t f_probs_ao41[192]; ++ uint16_t f_probs_ao60[12]; ++ uint16_t f_probs_ao63[12]; ++ uint16_t f_probs_match_len_low[16][8]; ++ uint16_t f_probs_match_len_mid[16][8]; ++ uint16_t f_probs_match_len_high[1][256]; ++ uint16_t f_probs_longrep_len_low[16][8]; ++ uint16_t f_probs_longrep_len_mid[16][8]; ++ uint16_t f_probs_longrep_len_high[1][256]; ++ uint16_t f_probs_slot[4][64]; ++ uint16_t f_probs_small_dist[128]; ++ uint16_t f_probs_large_dist[16]; ++ uint16_t f_probs_lit[16][768]; ++ ++ struct { ++ uint32_t v_bits; ++ uint32_t v_range; ++ uint32_t v_state; ++ uint32_t v_rep0; ++ uint32_t v_rep1; ++ uint32_t v_rep2; ++ uint32_t v_rep3; ++ uint32_t v_rep; ++ uint64_t v_pos; ++ uint64_t v_pos_end; ++ uint32_t v_lc; ++ uint64_t v_lp_mask; ++ uint64_t v_pb_mask; ++ uint32_t v_tree_node; ++ uint8_t v_prev_byte; ++ uint32_t v_match_byte; ++ uint32_t v_len_state; ++ uint32_t v_slot; ++ uint32_t v_len; ++ uint32_t v_lanl_offset; ++ uint32_t v_num_extra_bits; ++ uint32_t v_dist_extra_bits; ++ uint32_t v_i; ++ uint32_t v_index_lit; ++ uint32_t v_index_len; ++ uint32_t v_index_small_dist_base; ++ uint32_t v_index_small_dist_extra; ++ uint32_t v_index_large_dist; ++ uint32_t v_dist; ++ uint64_t scratch; ++ } s_decode_bitstream_slow; ++ struct { ++ uint8_t v_header_byte; ++ uint32_t v_length; ++ uint64_t scratch; ++ } s_do_transform_io; + } private_data; + + #ifdef __cplusplus + #if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) +- using unique_ptr = std::unique_ptr; ++ using unique_ptr = std::unique_ptr; + + // On failure, the alloc_etc functions return nullptr. They don't throw. + + static inline unique_ptr + alloc() { +- return unique_ptr(wuffs_lzw__decoder__alloc()); ++ return unique_ptr(wuffs_lzma__decoder__alloc()); + } + + static inline wuffs_base__io_transformer::unique_ptr + alloc_as__wuffs_base__io_transformer() { + return wuffs_base__io_transformer::unique_ptr( +- wuffs_lzw__decoder__alloc_as__wuffs_base__io_transformer()); ++ wuffs_lzma__decoder__alloc_as__wuffs_base__io_transformer()); + } + #endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +@@ -10095,10 +10701,10 @@ struct wuffs_lzw__decoder__struct { + // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in + // order to provide convenience methods. These forward on "this", so that you + // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". +- wuffs_lzw__decoder__struct() = delete; +- wuffs_lzw__decoder__struct(const wuffs_lzw__decoder__struct&) = delete; +- wuffs_lzw__decoder__struct& operator=( +- const wuffs_lzw__decoder__struct&) = delete; ++ wuffs_lzma__decoder__struct() = delete; ++ wuffs_lzma__decoder__struct(const wuffs_lzma__decoder__struct&) = delete; ++ wuffs_lzma__decoder__struct& operator=( ++ const wuffs_lzma__decoder__struct&) = delete; + #endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + + #if !defined(WUFFS_IMPLEMENTATION) +@@ -10118,7 +10724,7 @@ struct wuffs_lzw__decoder__struct { + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options) { +- return wuffs_lzw__decoder__initialize( ++ return wuffs_lzma__decoder__initialize( + this, sizeof_star_self, wuffs_version, options); + } + +@@ -10130,24 +10736,24 @@ struct wuffs_lzw__decoder__struct { + inline uint64_t + get_quirk( + uint32_t a_key) const { +- return wuffs_lzw__decoder__get_quirk(this, a_key); ++ return wuffs_lzma__decoder__get_quirk(this, a_key); + } + + inline wuffs_base__status + set_quirk( + uint32_t a_key, + uint64_t a_value) { +- return wuffs_lzw__decoder__set_quirk(this, a_key, a_value); ++ return wuffs_lzma__decoder__set_quirk(this, a_key, a_value); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_lzw__decoder__history_retain_length(this); ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_lzma__decoder__dst_history_retain_length(this); + } + + inline wuffs_base__range_ii_u64 + workbuf_len() const { +- return wuffs_lzw__decoder__workbuf_len(this); ++ return wuffs_lzma__decoder__workbuf_len(this); + } + + inline wuffs_base__status +@@ -10155,38 +10761,34 @@ struct wuffs_lzw__decoder__struct { + wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src, + wuffs_base__slice_u8 a_workbuf) { +- return wuffs_lzw__decoder__transform_io(this, a_dst, a_src, a_workbuf); +- } +- +- inline wuffs_base__slice_u8 +- flush() { +- return wuffs_lzw__decoder__flush(this); ++ return wuffs_lzma__decoder__transform_io(this, a_dst, a_src, a_workbuf); + } + + #endif // __cplusplus +-}; // struct wuffs_lzw__decoder__struct ++}; // struct wuffs_lzma__decoder__struct + + #endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) || defined(WUFFS_NONMONOLITHIC) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZMA) || defined(WUFFS_NONMONOLITHIC) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NETPBM) || defined(WUFFS_NONMONOLITHIC) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZIP) || defined(WUFFS_NONMONOLITHIC) + + // ---------------- Status Codes + +-extern const char wuffs_netpbm__error__bad_header[]; +-extern const char wuffs_netpbm__error__truncated_input[]; +-extern const char wuffs_netpbm__error__unsupported_netpbm_file[]; ++extern const char wuffs_lzip__error__bad_checksum[]; ++extern const char wuffs_lzip__error__bad_footer[]; ++extern const char wuffs_lzip__error__bad_header[]; ++extern const char wuffs_lzip__error__truncated_input[]; + + // ---------------- Public Consts + +-#define WUFFS_NETPBM__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_LZIP__DECODER_DST_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0u + +-#define WUFFS_NETPBM__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_LZIP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 4294967568u + + // ---------------- Struct Declarations + +-typedef struct wuffs_netpbm__decoder__struct wuffs_netpbm__decoder; ++typedef struct wuffs_lzip__decoder__struct wuffs_lzip__decoder; + + #ifdef __cplusplus + extern "C" { +@@ -10201,14 +10803,14 @@ extern "C" { + // Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_netpbm__decoder__initialize( +- wuffs_netpbm__decoder* self, ++wuffs_lzip__decoder__initialize( ++ wuffs_lzip__decoder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options); + + size_t +-sizeof__wuffs_netpbm__decoder(void); ++sizeof__wuffs_lzip__decoder(void); + + // ---------------- Allocs + +@@ -10218,112 +10820,54 @@ sizeof__wuffs_netpbm__decoder(void); + // calling free on the returned pointer. That pointer is effectively a C++ + // std::unique_ptr. + +-wuffs_netpbm__decoder* +-wuffs_netpbm__decoder__alloc(void); ++wuffs_lzip__decoder* ++wuffs_lzip__decoder__alloc(void); + +-static inline wuffs_base__image_decoder* +-wuffs_netpbm__decoder__alloc_as__wuffs_base__image_decoder(void) { +- return (wuffs_base__image_decoder*)(wuffs_netpbm__decoder__alloc()); ++static inline wuffs_base__io_transformer* ++wuffs_lzip__decoder__alloc_as__wuffs_base__io_transformer(void) { ++ return (wuffs_base__io_transformer*)(wuffs_lzip__decoder__alloc()); + } + + // ---------------- Upcasts + +-static inline wuffs_base__image_decoder* +-wuffs_netpbm__decoder__upcast_as__wuffs_base__image_decoder( +- wuffs_netpbm__decoder* p) { +- return (wuffs_base__image_decoder*)p; ++static inline wuffs_base__io_transformer* ++wuffs_lzip__decoder__upcast_as__wuffs_base__io_transformer( ++ wuffs_lzip__decoder* p) { ++ return (wuffs_base__io_transformer*)p; + } + + // ---------------- Public Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_netpbm__decoder__get_quirk( +- const wuffs_netpbm__decoder* self, ++wuffs_lzip__decoder__get_quirk( ++ const wuffs_lzip__decoder* self, + uint32_t a_key); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__set_quirk( +- wuffs_netpbm__decoder* self, ++wuffs_lzip__decoder__set_quirk( ++ wuffs_lzip__decoder* self, + uint32_t a_key, + uint64_t a_value); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__decode_image_config( +- wuffs_netpbm__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__decode_frame_config( +- wuffs_netpbm__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__decode_frame( +- wuffs_netpbm__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_netpbm__decoder__frame_dirty_rect( +- const wuffs_netpbm__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_netpbm__decoder__num_animation_loops( +- const wuffs_netpbm__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_netpbm__decoder__num_decoded_frame_configs( +- const wuffs_netpbm__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_netpbm__decoder__num_decoded_frames( +- const wuffs_netpbm__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__restart_frame( +- wuffs_netpbm__decoder* self, +- uint64_t a_index, +- uint64_t a_io_position); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_lzip__decoder__dst_history_retain_length( ++ const wuffs_lzip__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_netpbm__decoder__set_report_metadata( +- wuffs_netpbm__decoder* self, +- uint32_t a_fourcc, +- bool a_report); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_lzip__decoder__workbuf_len( ++ const wuffs_lzip__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__tell_me_more( +- wuffs_netpbm__decoder* self, ++wuffs_lzip__decoder__transform_io( ++ wuffs_lzip__decoder* self, + wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_netpbm__decoder__history_retain_length( +- const wuffs_netpbm__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_netpbm__decoder__workbuf_len( +- const wuffs_netpbm__decoder* self); ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); + + #ifdef __cplusplus + } // extern "C" +@@ -10338,7 +10882,7 @@ wuffs_netpbm__decoder__workbuf_len( + + #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-struct wuffs_netpbm__decoder__struct { ++struct wuffs_lzip__decoder__struct { + // Do not access the private_impl's or private_data's fields directly. There + // is no API/ABI compatibility or safety guarantee if you do so. Instead, use + // the wuffs_foo__bar__baz functions. +@@ -10349,42 +10893,41 @@ struct wuffs_netpbm__decoder__struct { + struct { + uint32_t magic; + uint32_t active_coroutine; +- wuffs_base__vtable vtable_for__wuffs_base__image_decoder; ++ wuffs_base__vtable vtable_for__wuffs_base__io_transformer; + wuffs_base__vtable null_vtable; + +- uint32_t f_pixfmt; +- uint32_t f_width; +- uint32_t f_height; +- uint32_t f_max_value; +- uint8_t f_call_sequence; +- uint64_t f_frame_config_io_position; +- uint32_t f_dst_x; +- uint32_t f_dst_y; +- wuffs_base__pixel_swizzler f_swizzler; ++ bool f_ignore_checksum; ++ uint64_t f_dsize_have; ++ uint64_t f_ssize_have; + +- uint32_t p_decode_image_config[1]; +- uint32_t p_do_decode_image_config[1]; +- uint32_t p_decode_frame_config[1]; +- uint32_t p_do_decode_frame_config[1]; +- uint32_t p_decode_frame[1]; +- uint32_t p_do_decode_frame[1]; ++ uint32_t p_transform_io; ++ uint32_t p_do_transform_io; + } private_impl; + ++ struct { ++ wuffs_crc32__ieee_hasher f_crc32; ++ wuffs_lzma__decoder f_lzma; ++ ++ struct { ++ uint64_t scratch; ++ } s_do_transform_io; ++ } private_data; ++ + #ifdef __cplusplus + #if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) +- using unique_ptr = std::unique_ptr; ++ using unique_ptr = std::unique_ptr; + + // On failure, the alloc_etc functions return nullptr. They don't throw. + + static inline unique_ptr + alloc() { +- return unique_ptr(wuffs_netpbm__decoder__alloc()); ++ return unique_ptr(wuffs_lzip__decoder__alloc()); + } + +- static inline wuffs_base__image_decoder::unique_ptr +- alloc_as__wuffs_base__image_decoder() { +- return wuffs_base__image_decoder::unique_ptr( +- wuffs_netpbm__decoder__alloc_as__wuffs_base__image_decoder()); ++ static inline wuffs_base__io_transformer::unique_ptr ++ alloc_as__wuffs_base__io_transformer() { ++ return wuffs_base__io_transformer::unique_ptr( ++ wuffs_lzip__decoder__alloc_as__wuffs_base__io_transformer()); + } + #endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +@@ -10400,10 +10943,10 @@ struct wuffs_netpbm__decoder__struct { + // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in + // order to provide convenience methods. These forward on "this", so that you + // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". +- wuffs_netpbm__decoder__struct() = delete; +- wuffs_netpbm__decoder__struct(const wuffs_netpbm__decoder__struct&) = delete; +- wuffs_netpbm__decoder__struct& operator=( +- const wuffs_netpbm__decoder__struct&) = delete; ++ wuffs_lzip__decoder__struct() = delete; ++ wuffs_lzip__decoder__struct(const wuffs_lzip__decoder__struct&) = delete; ++ wuffs_lzip__decoder__struct& operator=( ++ const wuffs_lzip__decoder__struct&) = delete; + #endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + + #if !defined(WUFFS_IMPLEMENTATION) +@@ -10423,128 +10966,327 @@ struct wuffs_netpbm__decoder__struct { + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options) { +- return wuffs_netpbm__decoder__initialize( ++ return wuffs_lzip__decoder__initialize( + this, sizeof_star_self, wuffs_version, options); + } + +- inline wuffs_base__image_decoder* +- upcast_as__wuffs_base__image_decoder() { +- return (wuffs_base__image_decoder*)this; ++ inline wuffs_base__io_transformer* ++ upcast_as__wuffs_base__io_transformer() { ++ return (wuffs_base__io_transformer*)this; + } + + inline uint64_t + get_quirk( + uint32_t a_key) const { +- return wuffs_netpbm__decoder__get_quirk(this, a_key); ++ return wuffs_lzip__decoder__get_quirk(this, a_key); + } + + inline wuffs_base__status + set_quirk( + uint32_t a_key, + uint64_t a_value) { +- return wuffs_netpbm__decoder__set_quirk(this, a_key, a_value); ++ return wuffs_lzip__decoder__set_quirk(this, a_key, a_value); + } + +- inline wuffs_base__status +- decode_image_config( +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- return wuffs_netpbm__decoder__decode_image_config(this, a_dst, a_src); ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_lzip__decoder__dst_history_retain_length(this); + } + +- inline wuffs_base__status +- decode_frame_config( +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- return wuffs_netpbm__decoder__decode_frame_config(this, a_dst, a_src); ++ inline wuffs_base__range_ii_u64 ++ workbuf_len() const { ++ return wuffs_lzip__decoder__workbuf_len(this); + } + + inline wuffs_base__status +- decode_frame( +- wuffs_base__pixel_buffer* a_dst, ++ transform_io( ++ wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- return wuffs_netpbm__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); +- } +- +- inline wuffs_base__rect_ie_u32 +- frame_dirty_rect() const { +- return wuffs_netpbm__decoder__frame_dirty_rect(this); ++ wuffs_base__slice_u8 a_workbuf) { ++ return wuffs_lzip__decoder__transform_io(this, a_dst, a_src, a_workbuf); + } + +- inline uint32_t +- num_animation_loops() const { +- return wuffs_netpbm__decoder__num_animation_loops(this); +- } ++#endif // __cplusplus ++}; // struct wuffs_lzip__decoder__struct + +- inline uint64_t +- num_decoded_frame_configs() const { +- return wuffs_netpbm__decoder__num_decoded_frame_configs(this); +- } ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +- inline uint64_t +- num_decoded_frames() const { +- return wuffs_netpbm__decoder__num_decoded_frames(this); +- } ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZIP) || defined(WUFFS_NONMONOLITHIC) + +- inline wuffs_base__status +- restart_frame( +- uint64_t a_index, +- uint64_t a_io_position) { +- return wuffs_netpbm__decoder__restart_frame(this, a_index, a_io_position); +- } ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) || defined(WUFFS_NONMONOLITHIC) + +- inline wuffs_base__empty_struct +- set_report_metadata( +- uint32_t a_fourcc, +- bool a_report) { +- return wuffs_netpbm__decoder__set_report_metadata(this, a_fourcc, a_report); +- } ++// ---------------- Status Codes + +- inline wuffs_base__status +- tell_me_more( +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- return wuffs_netpbm__decoder__tell_me_more(this, a_dst, a_minfo, a_src); +- } ++extern const char wuffs_lzw__error__bad_code[]; ++extern const char wuffs_lzw__error__truncated_input[]; + +- inline uint64_t +- history_retain_length() const { +- return wuffs_netpbm__decoder__history_retain_length(this); +- } ++// ---------------- Public Consts + +- inline wuffs_base__range_ii_u64 +- workbuf_len() const { +- return wuffs_netpbm__decoder__workbuf_len(this); +- } ++#define WUFFS_LZW__DECODER_DST_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0u + +-#endif // __cplusplus +-}; // struct wuffs_netpbm__decoder__struct ++#define WUFFS_LZW__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + +-#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++#define WUFFS_LZW__QUIRK_LITERAL_WIDTH_PLUS_ONE 1348378624u + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NETPBM) || defined(WUFFS_NONMONOLITHIC) ++// ---------------- Struct Declarations + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) || defined(WUFFS_NONMONOLITHIC) ++typedef struct wuffs_lzw__decoder__struct wuffs_lzw__decoder; + +-// ---------------- Status Codes ++#ifdef __cplusplus ++extern "C" { ++#endif + +-extern const char wuffs_nie__error__bad_header[]; +-extern const char wuffs_nie__error__truncated_input[]; +-extern const char wuffs_nie__error__unsupported_nie_file[]; ++// ---------------- Public Initializer Prototypes + +-// ---------------- Public Consts ++// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self, ++// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)". ++// ++// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version. ++// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_lzw__decoder__initialize( ++ wuffs_lzw__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options); ++ ++size_t ++sizeof__wuffs_lzw__decoder(void); ++ ++// ---------------- Allocs ++ ++// These functions allocate and initialize Wuffs structs. They return NULL if ++// memory allocation fails. If they return non-NULL, there is no need to call ++// wuffs_foo__bar__initialize, but the caller is responsible for eventually ++// calling free on the returned pointer. That pointer is effectively a C++ ++// std::unique_ptr. ++ ++wuffs_lzw__decoder* ++wuffs_lzw__decoder__alloc(void); ++ ++static inline wuffs_base__io_transformer* ++wuffs_lzw__decoder__alloc_as__wuffs_base__io_transformer(void) { ++ return (wuffs_base__io_transformer*)(wuffs_lzw__decoder__alloc()); ++} ++ ++// ---------------- Upcasts ++ ++static inline wuffs_base__io_transformer* ++wuffs_lzw__decoder__upcast_as__wuffs_base__io_transformer( ++ wuffs_lzw__decoder* p) { ++ return (wuffs_base__io_transformer*)p; ++} ++ ++// ---------------- Public Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_lzw__decoder__get_quirk( ++ const wuffs_lzw__decoder* self, ++ uint32_t a_key); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_lzw__decoder__set_quirk( ++ wuffs_lzw__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_lzw__decoder__dst_history_retain_length( ++ const wuffs_lzw__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_lzw__decoder__workbuf_len( ++ const wuffs_lzw__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_lzw__decoder__transform_io( ++ wuffs_lzw__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8 ++wuffs_lzw__decoder__flush( ++ wuffs_lzw__decoder* self); ++ ++#ifdef __cplusplus ++} // extern "C" ++#endif ++ ++// ---------------- Struct Definitions ++ ++// These structs' fields, and the sizeof them, are private implementation ++// details that aren't guaranteed to be stable across Wuffs versions. ++// ++// See https://en.wikipedia.org/wiki/Opaque_pointer#C ++ ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++struct wuffs_lzw__decoder__struct { ++ // Do not access the private_impl's or private_data's fields directly. There ++ // is no API/ABI compatibility or safety guarantee if you do so. Instead, use ++ // the wuffs_foo__bar__baz functions. ++ // ++ // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct ++ // can be stack allocated when WUFFS_IMPLEMENTATION is defined. ++ ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable vtable_for__wuffs_base__io_transformer; ++ wuffs_base__vtable null_vtable; ++ ++ uint32_t f_pending_literal_width_plus_one; ++ uint32_t f_literal_width; ++ uint32_t f_clear_code; ++ uint32_t f_end_code; ++ uint32_t f_save_code; ++ uint32_t f_prev_code; ++ uint32_t f_width; ++ uint32_t f_bits; ++ uint32_t f_n_bits; ++ uint32_t f_output_ri; ++ uint32_t f_output_wi; ++ uint32_t f_read_from_return_value; ++ uint16_t f_prefixes[4096]; ++ ++ uint32_t p_transform_io; ++ uint32_t p_write_to; ++ } private_impl; ++ ++ struct { ++ uint8_t f_suffixes[4096][8]; ++ uint16_t f_lm1s[4096]; ++ uint8_t f_output[8199]; ++ } private_data; ++ ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; ++ ++ // On failure, the alloc_etc functions return nullptr. They don't throw. ++ ++ static inline unique_ptr ++ alloc() { ++ return unique_ptr(wuffs_lzw__decoder__alloc()); ++ } ++ ++ static inline wuffs_base__io_transformer::unique_ptr ++ alloc_as__wuffs_base__io_transformer() { ++ return wuffs_base__io_transformer::unique_ptr( ++ wuffs_lzw__decoder__alloc_as__wuffs_base__io_transformer()); ++ } ++#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ ++#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ // Disallow constructing or copying an object via standard C++ mechanisms, ++ // e.g. the "new" operator, as this struct is intentionally opaque. Its total ++ // size and field layout is not part of the public, stable, memory-safe API. ++ // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and ++ // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as ++ // their first argument) rather than tweaking bar.private_impl.qux fields. ++ // ++ // In C, we can just leave wuffs_foo__bar as an incomplete type (unless ++ // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in ++ // order to provide convenience methods. These forward on "this", so that you ++ // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". ++ wuffs_lzw__decoder__struct() = delete; ++ wuffs_lzw__decoder__struct(const wuffs_lzw__decoder__struct&) = delete; ++ wuffs_lzw__decoder__struct& operator=( ++ const wuffs_lzw__decoder__struct&) = delete; ++#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ ++#if !defined(WUFFS_IMPLEMENTATION) ++ // As above, the size of the struct is not part of the public API, and unless ++ // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap ++ // allocated, not stack allocated. Its size is not intended to be known at ++ // compile time, but it is unfortunately divulged as a side effect of ++ // defining C++ convenience methods. Use "sizeof__T()", calling the function, ++ // instead of "sizeof T", invoking the operator. To make the two values ++ // different, so that passing the latter will be rejected by the initialize ++ // function, we add an arbitrary amount of dead weight. ++ uint8_t dead_weight[123000000]; // 123 MB. ++#endif // !defined(WUFFS_IMPLEMENTATION) ++ ++ inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++ initialize( ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options) { ++ return wuffs_lzw__decoder__initialize( ++ this, sizeof_star_self, wuffs_version, options); ++ } ++ ++ inline wuffs_base__io_transformer* ++ upcast_as__wuffs_base__io_transformer() { ++ return (wuffs_base__io_transformer*)this; ++ } ++ ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_lzw__decoder__get_quirk(this, a_key); ++ } ++ ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_lzw__decoder__set_quirk(this, a_key, a_value); ++ } ++ ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_lzw__decoder__dst_history_retain_length(this); ++ } ++ ++ inline wuffs_base__range_ii_u64 ++ workbuf_len() const { ++ return wuffs_lzw__decoder__workbuf_len(this); ++ } ++ ++ inline wuffs_base__status ++ transform_io( ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ return wuffs_lzw__decoder__transform_io(this, a_dst, a_src, a_workbuf); ++ } ++ ++ inline wuffs_base__slice_u8 ++ flush() { ++ return wuffs_lzw__decoder__flush(this); ++ } ++ ++#endif // __cplusplus ++}; // struct wuffs_lzw__decoder__struct ++ ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) || defined(WUFFS_NONMONOLITHIC) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NETPBM) || defined(WUFFS_NONMONOLITHIC) ++ ++// ---------------- Status Codes ++ ++extern const char wuffs_netpbm__error__bad_header[]; ++extern const char wuffs_netpbm__error__truncated_input[]; ++extern const char wuffs_netpbm__error__unsupported_netpbm_file[]; + +-#define WUFFS_NIE__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++// ---------------- Public Consts + +-#define WUFFS_NIE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_NETPBM__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + + // ---------------- Struct Declarations + +-typedef struct wuffs_nie__decoder__struct wuffs_nie__decoder; ++typedef struct wuffs_netpbm__decoder__struct wuffs_netpbm__decoder; + + #ifdef __cplusplus + extern "C" { +@@ -10559,14 +11301,14 @@ extern "C" { + // Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_nie__decoder__initialize( +- wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__initialize( ++ wuffs_netpbm__decoder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options); + + size_t +-sizeof__wuffs_nie__decoder(void); ++sizeof__wuffs_netpbm__decoder(void); + + // ---------------- Allocs + +@@ -10576,19 +11318,19 @@ sizeof__wuffs_nie__decoder(void); + // calling free on the returned pointer. That pointer is effectively a C++ + // std::unique_ptr. + +-wuffs_nie__decoder* +-wuffs_nie__decoder__alloc(void); ++wuffs_netpbm__decoder* ++wuffs_netpbm__decoder__alloc(void); + + static inline wuffs_base__image_decoder* +-wuffs_nie__decoder__alloc_as__wuffs_base__image_decoder(void) { +- return (wuffs_base__image_decoder*)(wuffs_nie__decoder__alloc()); ++wuffs_netpbm__decoder__alloc_as__wuffs_base__image_decoder(void) { ++ return (wuffs_base__image_decoder*)(wuffs_netpbm__decoder__alloc()); + } + + // ---------------- Upcasts + + static inline wuffs_base__image_decoder* +-wuffs_nie__decoder__upcast_as__wuffs_base__image_decoder( +- wuffs_nie__decoder* p) { ++wuffs_netpbm__decoder__upcast_as__wuffs_base__image_decoder( ++ wuffs_netpbm__decoder* p) { + return (wuffs_base__image_decoder*)p; + } + +@@ -10596,35 +11338,35 @@ wuffs_nie__decoder__upcast_as__wuffs_base__image_decoder( + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_nie__decoder__get_quirk( +- const wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__get_quirk( ++ const wuffs_netpbm__decoder* self, + uint32_t a_key); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__set_quirk( +- wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__set_quirk( ++ wuffs_netpbm__decoder* self, + uint32_t a_key, + uint64_t a_value); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__decode_image_config( +- wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__decode_image_config( ++ wuffs_netpbm__decoder* self, + wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__decode_frame_config( +- wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__decode_frame_config( ++ wuffs_netpbm__decoder* self, + wuffs_base__frame_config* a_dst, + wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__decode_frame( +- wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__decode_frame( ++ wuffs_netpbm__decoder* self, + wuffs_base__pixel_buffer* a_dst, + wuffs_base__io_buffer* a_src, + wuffs_base__pixel_blend a_blend, +@@ -10633,55 +11375,50 @@ wuffs_nie__decoder__decode_frame( + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_nie__decoder__frame_dirty_rect( +- const wuffs_nie__decoder* self); ++wuffs_netpbm__decoder__frame_dirty_rect( ++ const wuffs_netpbm__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_nie__decoder__num_animation_loops( +- const wuffs_nie__decoder* self); ++wuffs_netpbm__decoder__num_animation_loops( ++ const wuffs_netpbm__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_nie__decoder__num_decoded_frame_configs( +- const wuffs_nie__decoder* self); ++wuffs_netpbm__decoder__num_decoded_frame_configs( ++ const wuffs_netpbm__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_nie__decoder__num_decoded_frames( +- const wuffs_nie__decoder* self); ++wuffs_netpbm__decoder__num_decoded_frames( ++ const wuffs_netpbm__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__restart_frame( +- wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__restart_frame( ++ wuffs_netpbm__decoder* self, + uint64_t a_index, + uint64_t a_io_position); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_nie__decoder__set_report_metadata( +- wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__set_report_metadata( ++ wuffs_netpbm__decoder* self, + uint32_t a_fourcc, + bool a_report); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__tell_me_more( +- wuffs_nie__decoder* self, ++wuffs_netpbm__decoder__tell_me_more( ++ wuffs_netpbm__decoder* self, + wuffs_base__io_buffer* a_dst, + wuffs_base__more_information* a_minfo, + wuffs_base__io_buffer* a_src); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_nie__decoder__history_retain_length( +- const wuffs_nie__decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_nie__decoder__workbuf_len( +- const wuffs_nie__decoder* self); ++wuffs_netpbm__decoder__workbuf_len( ++ const wuffs_netpbm__decoder* self); + + #ifdef __cplusplus + } // extern "C" +@@ -10696,7 +11433,7 @@ wuffs_nie__decoder__workbuf_len( + + #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-struct wuffs_nie__decoder__struct { ++struct wuffs_netpbm__decoder__struct { + // Do not access the private_impl's or private_data's fields directly. There + // is no API/ABI compatibility or safety guarantee if you do so. Instead, use + // the wuffs_foo__bar__baz functions. +@@ -10713,40 +11450,36 @@ struct wuffs_nie__decoder__struct { + uint32_t f_pixfmt; + uint32_t f_width; + uint32_t f_height; ++ uint32_t f_max_value; + uint8_t f_call_sequence; ++ uint64_t f_frame_config_io_position; + uint32_t f_dst_x; + uint32_t f_dst_y; + wuffs_base__pixel_swizzler f_swizzler; + +- uint32_t p_decode_image_config[1]; +- uint32_t p_do_decode_image_config[1]; +- uint32_t p_decode_frame_config[1]; +- uint32_t p_do_decode_frame_config[1]; +- uint32_t p_decode_frame[1]; +- uint32_t p_do_decode_frame[1]; ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; + } private_impl; + +- struct { +- struct { +- uint64_t scratch; +- } s_do_decode_image_config[1]; +- } private_data; +- + #ifdef __cplusplus + #if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) +- using unique_ptr = std::unique_ptr; ++ using unique_ptr = std::unique_ptr; + + // On failure, the alloc_etc functions return nullptr. They don't throw. + + static inline unique_ptr + alloc() { +- return unique_ptr(wuffs_nie__decoder__alloc()); ++ return unique_ptr(wuffs_netpbm__decoder__alloc()); + } + + static inline wuffs_base__image_decoder::unique_ptr + alloc_as__wuffs_base__image_decoder() { + return wuffs_base__image_decoder::unique_ptr( +- wuffs_nie__decoder__alloc_as__wuffs_base__image_decoder()); ++ wuffs_netpbm__decoder__alloc_as__wuffs_base__image_decoder()); + } + #endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +@@ -10762,10 +11495,10 @@ struct wuffs_nie__decoder__struct { + // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in + // order to provide convenience methods. These forward on "this", so that you + // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". +- wuffs_nie__decoder__struct() = delete; +- wuffs_nie__decoder__struct(const wuffs_nie__decoder__struct&) = delete; +- wuffs_nie__decoder__struct& operator=( +- const wuffs_nie__decoder__struct&) = delete; ++ wuffs_netpbm__decoder__struct() = delete; ++ wuffs_netpbm__decoder__struct(const wuffs_netpbm__decoder__struct&) = delete; ++ wuffs_netpbm__decoder__struct& operator=( ++ const wuffs_netpbm__decoder__struct&) = delete; + #endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + + #if !defined(WUFFS_IMPLEMENTATION) +@@ -10785,7 +11518,7 @@ struct wuffs_nie__decoder__struct { + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options) { +- return wuffs_nie__decoder__initialize( ++ return wuffs_netpbm__decoder__initialize( + this, sizeof_star_self, wuffs_version, options); + } + +@@ -10797,28 +11530,28 @@ struct wuffs_nie__decoder__struct { + inline uint64_t + get_quirk( + uint32_t a_key) const { +- return wuffs_nie__decoder__get_quirk(this, a_key); ++ return wuffs_netpbm__decoder__get_quirk(this, a_key); + } + + inline wuffs_base__status + set_quirk( + uint32_t a_key, + uint64_t a_value) { +- return wuffs_nie__decoder__set_quirk(this, a_key, a_value); ++ return wuffs_netpbm__decoder__set_quirk(this, a_key, a_value); + } + + inline wuffs_base__status + decode_image_config( + wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { +- return wuffs_nie__decoder__decode_image_config(this, a_dst, a_src); ++ return wuffs_netpbm__decoder__decode_image_config(this, a_dst, a_src); + } + + inline wuffs_base__status + decode_frame_config( + wuffs_base__frame_config* a_dst, + wuffs_base__io_buffer* a_src) { +- return wuffs_nie__decoder__decode_frame_config(this, a_dst, a_src); ++ return wuffs_netpbm__decoder__decode_frame_config(this, a_dst, a_src); + } + + inline wuffs_base__status +@@ -10828,41 +11561,41 @@ struct wuffs_nie__decoder__struct { + wuffs_base__pixel_blend a_blend, + wuffs_base__slice_u8 a_workbuf, + wuffs_base__decode_frame_options* a_opts) { +- return wuffs_nie__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); ++ return wuffs_netpbm__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); + } + + inline wuffs_base__rect_ie_u32 + frame_dirty_rect() const { +- return wuffs_nie__decoder__frame_dirty_rect(this); ++ return wuffs_netpbm__decoder__frame_dirty_rect(this); + } + + inline uint32_t + num_animation_loops() const { +- return wuffs_nie__decoder__num_animation_loops(this); ++ return wuffs_netpbm__decoder__num_animation_loops(this); + } + + inline uint64_t + num_decoded_frame_configs() const { +- return wuffs_nie__decoder__num_decoded_frame_configs(this); ++ return wuffs_netpbm__decoder__num_decoded_frame_configs(this); + } + + inline uint64_t + num_decoded_frames() const { +- return wuffs_nie__decoder__num_decoded_frames(this); ++ return wuffs_netpbm__decoder__num_decoded_frames(this); + } + + inline wuffs_base__status + restart_frame( + uint64_t a_index, + uint64_t a_io_position) { +- return wuffs_nie__decoder__restart_frame(this, a_index, a_io_position); ++ return wuffs_netpbm__decoder__restart_frame(this, a_index, a_io_position); + } + + inline wuffs_base__empty_struct + set_report_metadata( + uint32_t a_fourcc, + bool a_report) { +- return wuffs_nie__decoder__set_report_metadata(this, a_fourcc, a_report); ++ return wuffs_netpbm__decoder__set_report_metadata(this, a_fourcc, a_report); + } + + inline wuffs_base__status +@@ -10870,49 +11603,36 @@ struct wuffs_nie__decoder__struct { + wuffs_base__io_buffer* a_dst, + wuffs_base__more_information* a_minfo, + wuffs_base__io_buffer* a_src) { +- return wuffs_nie__decoder__tell_me_more(this, a_dst, a_minfo, a_src); +- } +- +- inline uint64_t +- history_retain_length() const { +- return wuffs_nie__decoder__history_retain_length(this); ++ return wuffs_netpbm__decoder__tell_me_more(this, a_dst, a_minfo, a_src); + } + + inline wuffs_base__range_ii_u64 + workbuf_len() const { +- return wuffs_nie__decoder__workbuf_len(this); ++ return wuffs_netpbm__decoder__workbuf_len(this); + } + + #endif // __cplusplus +-}; // struct wuffs_nie__decoder__struct ++}; // struct wuffs_netpbm__decoder__struct + + #endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) || defined(WUFFS_NONMONOLITHIC) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NETPBM) || defined(WUFFS_NONMONOLITHIC) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB) || defined(WUFFS_NONMONOLITHIC) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) || defined(WUFFS_NONMONOLITHIC) + + // ---------------- Status Codes + +-extern const char wuffs_zlib__note__dictionary_required[]; +-extern const char wuffs_zlib__error__bad_checksum[]; +-extern const char wuffs_zlib__error__bad_compression_method[]; +-extern const char wuffs_zlib__error__bad_compression_window_size[]; +-extern const char wuffs_zlib__error__bad_parity_check[]; +-extern const char wuffs_zlib__error__incorrect_dictionary[]; +-extern const char wuffs_zlib__error__truncated_input[]; ++extern const char wuffs_nie__error__bad_header[]; ++extern const char wuffs_nie__error__truncated_input[]; ++extern const char wuffs_nie__error__unsupported_nie_file[]; + + // ---------------- Public Consts + +-#define WUFFS_ZLIB__QUIRK_JUST_RAW_DEFLATE 2113790976 +- +-#define WUFFS_ZLIB__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 +- +-#define WUFFS_ZLIB__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1 ++#define WUFFS_NIE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + + // ---------------- Struct Declarations + +-typedef struct wuffs_zlib__decoder__struct wuffs_zlib__decoder; ++typedef struct wuffs_nie__decoder__struct wuffs_nie__decoder; + + #ifdef __cplusplus + extern "C" { +@@ -10927,14 +11647,14 @@ extern "C" { + // Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_zlib__decoder__initialize( +- wuffs_zlib__decoder* self, ++wuffs_nie__decoder__initialize( ++ wuffs_nie__decoder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options); + + size_t +-sizeof__wuffs_zlib__decoder(void); ++sizeof__wuffs_nie__decoder(void); + + // ---------------- Allocs + +@@ -10944,65 +11664,107 @@ sizeof__wuffs_zlib__decoder(void); + // calling free on the returned pointer. That pointer is effectively a C++ + // std::unique_ptr. + +-wuffs_zlib__decoder* +-wuffs_zlib__decoder__alloc(void); ++wuffs_nie__decoder* ++wuffs_nie__decoder__alloc(void); + +-static inline wuffs_base__io_transformer* +-wuffs_zlib__decoder__alloc_as__wuffs_base__io_transformer(void) { +- return (wuffs_base__io_transformer*)(wuffs_zlib__decoder__alloc()); ++static inline wuffs_base__image_decoder* ++wuffs_nie__decoder__alloc_as__wuffs_base__image_decoder(void) { ++ return (wuffs_base__image_decoder*)(wuffs_nie__decoder__alloc()); + } + + // ---------------- Upcasts + +-static inline wuffs_base__io_transformer* +-wuffs_zlib__decoder__upcast_as__wuffs_base__io_transformer( +- wuffs_zlib__decoder* p) { +- return (wuffs_base__io_transformer*)p; ++static inline wuffs_base__image_decoder* ++wuffs_nie__decoder__upcast_as__wuffs_base__image_decoder( ++ wuffs_nie__decoder* p) { ++ return (wuffs_base__image_decoder*)p; + } + + // ---------------- Public Function Prototypes + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_zlib__decoder__dictionary_id( +- const wuffs_zlib__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_zlib__decoder__add_dictionary( +- wuffs_zlib__decoder* self, +- wuffs_base__slice_u8 a_dict); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_zlib__decoder__get_quirk( +- const wuffs_zlib__decoder* self, ++wuffs_nie__decoder__get_quirk( ++ const wuffs_nie__decoder* self, + uint32_t a_key); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_zlib__decoder__set_quirk( +- wuffs_zlib__decoder* self, ++wuffs_nie__decoder__set_quirk( ++ wuffs_nie__decoder* self, + uint32_t a_key, + uint64_t a_value); + ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__decode_image_config( ++ wuffs_nie__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__decode_frame_config( ++ wuffs_nie__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__decode_frame( ++ wuffs_nie__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_nie__decoder__frame_dirty_rect( ++ const wuffs_nie__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_nie__decoder__num_animation_loops( ++ const wuffs_nie__decoder* self); ++ + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_zlib__decoder__history_retain_length( +- const wuffs_zlib__decoder* self); ++wuffs_nie__decoder__num_decoded_frame_configs( ++ const wuffs_nie__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_zlib__decoder__workbuf_len( +- const wuffs_zlib__decoder* self); ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_nie__decoder__num_decoded_frames( ++ const wuffs_nie__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_zlib__decoder__transform_io( +- wuffs_zlib__decoder* self, ++wuffs_nie__decoder__restart_frame( ++ wuffs_nie__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_nie__decoder__set_report_metadata( ++ wuffs_nie__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__tell_me_more( ++ wuffs_nie__decoder* self, + wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf); ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_nie__decoder__workbuf_len( ++ const wuffs_nie__decoder* self); + + #ifdef __cplusplus + } // extern "C" +@@ -11017,7 +11779,7 @@ wuffs_zlib__decoder__transform_io( + + #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-struct wuffs_zlib__decoder__struct { ++struct wuffs_nie__decoder__struct { + // Do not access the private_impl's or private_data's fields directly. There + // is no API/ABI compatibility or safety guarantee if you do so. Instead, use + // the wuffs_foo__bar__baz functions. +@@ -11028,20 +11790,336 @@ struct wuffs_zlib__decoder__struct { + struct { + uint32_t magic; + uint32_t active_coroutine; +- wuffs_base__vtable vtable_for__wuffs_base__io_transformer; ++ wuffs_base__vtable vtable_for__wuffs_base__image_decoder; + wuffs_base__vtable null_vtable; + +- bool f_bad_call_sequence; +- bool f_header_complete; ++ uint32_t f_pixfmt; ++ uint32_t f_width; ++ uint32_t f_height; ++ uint8_t f_call_sequence; ++ uint32_t f_dst_x; ++ uint32_t f_dst_y; ++ wuffs_base__pixel_swizzler f_swizzler; ++ ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; ++ } private_impl; ++ ++ struct { ++ struct { ++ uint64_t scratch; ++ } s_do_decode_image_config; ++ } private_data; ++ ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; ++ ++ // On failure, the alloc_etc functions return nullptr. They don't throw. ++ ++ static inline unique_ptr ++ alloc() { ++ return unique_ptr(wuffs_nie__decoder__alloc()); ++ } ++ ++ static inline wuffs_base__image_decoder::unique_ptr ++ alloc_as__wuffs_base__image_decoder() { ++ return wuffs_base__image_decoder::unique_ptr( ++ wuffs_nie__decoder__alloc_as__wuffs_base__image_decoder()); ++ } ++#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ ++#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ // Disallow constructing or copying an object via standard C++ mechanisms, ++ // e.g. the "new" operator, as this struct is intentionally opaque. Its total ++ // size and field layout is not part of the public, stable, memory-safe API. ++ // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and ++ // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as ++ // their first argument) rather than tweaking bar.private_impl.qux fields. ++ // ++ // In C, we can just leave wuffs_foo__bar as an incomplete type (unless ++ // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in ++ // order to provide convenience methods. These forward on "this", so that you ++ // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". ++ wuffs_nie__decoder__struct() = delete; ++ wuffs_nie__decoder__struct(const wuffs_nie__decoder__struct&) = delete; ++ wuffs_nie__decoder__struct& operator=( ++ const wuffs_nie__decoder__struct&) = delete; ++#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ ++#if !defined(WUFFS_IMPLEMENTATION) ++ // As above, the size of the struct is not part of the public API, and unless ++ // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap ++ // allocated, not stack allocated. Its size is not intended to be known at ++ // compile time, but it is unfortunately divulged as a side effect of ++ // defining C++ convenience methods. Use "sizeof__T()", calling the function, ++ // instead of "sizeof T", invoking the operator. To make the two values ++ // different, so that passing the latter will be rejected by the initialize ++ // function, we add an arbitrary amount of dead weight. ++ uint8_t dead_weight[123000000]; // 123 MB. ++#endif // !defined(WUFFS_IMPLEMENTATION) ++ ++ inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++ initialize( ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options) { ++ return wuffs_nie__decoder__initialize( ++ this, sizeof_star_self, wuffs_version, options); ++ } ++ ++ inline wuffs_base__image_decoder* ++ upcast_as__wuffs_base__image_decoder() { ++ return (wuffs_base__image_decoder*)this; ++ } ++ ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_nie__decoder__get_quirk(this, a_key); ++ } ++ ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_nie__decoder__set_quirk(this, a_key, a_value); ++ } ++ ++ inline wuffs_base__status ++ decode_image_config( ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_nie__decoder__decode_image_config(this, a_dst, a_src); ++ } ++ ++ inline wuffs_base__status ++ decode_frame_config( ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_nie__decoder__decode_frame_config(this, a_dst, a_src); ++ } ++ ++ inline wuffs_base__status ++ decode_frame( ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ return wuffs_nie__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); ++ } ++ ++ inline wuffs_base__rect_ie_u32 ++ frame_dirty_rect() const { ++ return wuffs_nie__decoder__frame_dirty_rect(this); ++ } ++ ++ inline uint32_t ++ num_animation_loops() const { ++ return wuffs_nie__decoder__num_animation_loops(this); ++ } ++ ++ inline uint64_t ++ num_decoded_frame_configs() const { ++ return wuffs_nie__decoder__num_decoded_frame_configs(this); ++ } ++ ++ inline uint64_t ++ num_decoded_frames() const { ++ return wuffs_nie__decoder__num_decoded_frames(this); ++ } ++ ++ inline wuffs_base__status ++ restart_frame( ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ return wuffs_nie__decoder__restart_frame(this, a_index, a_io_position); ++ } ++ ++ inline wuffs_base__empty_struct ++ set_report_metadata( ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_nie__decoder__set_report_metadata(this, a_fourcc, a_report); ++ } ++ ++ inline wuffs_base__status ++ tell_me_more( ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_nie__decoder__tell_me_more(this, a_dst, a_minfo, a_src); ++ } ++ ++ inline wuffs_base__range_ii_u64 ++ workbuf_len() const { ++ return wuffs_nie__decoder__workbuf_len(this); ++ } ++ ++#endif // __cplusplus ++}; // struct wuffs_nie__decoder__struct ++ ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) || defined(WUFFS_NONMONOLITHIC) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB) || defined(WUFFS_NONMONOLITHIC) ++ ++// ---------------- Status Codes ++ ++extern const char wuffs_zlib__note__dictionary_required[]; ++extern const char wuffs_zlib__error__bad_checksum[]; ++extern const char wuffs_zlib__error__bad_compression_method[]; ++extern const char wuffs_zlib__error__bad_compression_window_size[]; ++extern const char wuffs_zlib__error__bad_parity_check[]; ++extern const char wuffs_zlib__error__incorrect_dictionary[]; ++extern const char wuffs_zlib__error__truncated_input[]; ++ ++// ---------------- Public Consts ++ ++#define WUFFS_ZLIB__QUIRK_JUST_RAW_DEFLATE 2113790976u ++ ++#define WUFFS_ZLIB__DECODER_DST_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0u ++ ++#define WUFFS_ZLIB__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1u ++ ++// ---------------- Struct Declarations ++ ++typedef struct wuffs_zlib__decoder__struct wuffs_zlib__decoder; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++// ---------------- Public Initializer Prototypes ++ ++// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self, ++// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)". ++// ++// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version. ++// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_zlib__decoder__initialize( ++ wuffs_zlib__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options); ++ ++size_t ++sizeof__wuffs_zlib__decoder(void); ++ ++// ---------------- Allocs ++ ++// These functions allocate and initialize Wuffs structs. They return NULL if ++// memory allocation fails. If they return non-NULL, there is no need to call ++// wuffs_foo__bar__initialize, but the caller is responsible for eventually ++// calling free on the returned pointer. That pointer is effectively a C++ ++// std::unique_ptr. ++ ++wuffs_zlib__decoder* ++wuffs_zlib__decoder__alloc(void); ++ ++static inline wuffs_base__io_transformer* ++wuffs_zlib__decoder__alloc_as__wuffs_base__io_transformer(void) { ++ return (wuffs_base__io_transformer*)(wuffs_zlib__decoder__alloc()); ++} ++ ++// ---------------- Upcasts ++ ++static inline wuffs_base__io_transformer* ++wuffs_zlib__decoder__upcast_as__wuffs_base__io_transformer( ++ wuffs_zlib__decoder* p) { ++ return (wuffs_base__io_transformer*)p; ++} ++ ++// ---------------- Public Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_zlib__decoder__dictionary_id( ++ const wuffs_zlib__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_zlib__decoder__add_dictionary( ++ wuffs_zlib__decoder* self, ++ wuffs_base__slice_u8 a_dict); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_zlib__decoder__get_quirk( ++ const wuffs_zlib__decoder* self, ++ uint32_t a_key); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_zlib__decoder__set_quirk( ++ wuffs_zlib__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_zlib__decoder__dst_history_retain_length( ++ const wuffs_zlib__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_zlib__decoder__workbuf_len( ++ const wuffs_zlib__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_zlib__decoder__transform_io( ++ wuffs_zlib__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++#ifdef __cplusplus ++} // extern "C" ++#endif ++ ++// ---------------- Struct Definitions ++ ++// These structs' fields, and the sizeof them, are private implementation ++// details that aren't guaranteed to be stable across Wuffs versions. ++// ++// See https://en.wikipedia.org/wiki/Opaque_pointer#C ++ ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++struct wuffs_zlib__decoder__struct { ++ // Do not access the private_impl's or private_data's fields directly. There ++ // is no API/ABI compatibility or safety guarantee if you do so. Instead, use ++ // the wuffs_foo__bar__baz functions. ++ // ++ // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct ++ // can be stack allocated when WUFFS_IMPLEMENTATION is defined. ++ ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable vtable_for__wuffs_base__io_transformer; ++ wuffs_base__vtable null_vtable; ++ ++ bool f_bad_call_sequence; ++ bool f_header_complete; + bool f_got_dictionary; + bool f_want_dictionary; + bool f_quirks[1]; + bool f_ignore_checksum; +- uint32_t f_dict_id_got; ++ uint32_t f_dict_id_have; + uint32_t f_dict_id_want; + +- uint32_t p_transform_io[1]; +- uint32_t p_do_transform_io[1]; ++ uint32_t p_transform_io; ++ uint32_t p_do_transform_io; + } private_impl; + + struct { +@@ -11050,9 +12128,9 @@ struct wuffs_zlib__decoder__struct { + wuffs_deflate__decoder f_flate; + + struct { +- uint32_t v_checksum_got; ++ uint32_t v_checksum_have; + uint64_t scratch; +- } s_do_transform_io[1]; ++ } s_do_transform_io; + } private_data; + + #ifdef __cplusplus +@@ -11141,9 +12219,9 @@ struct wuffs_zlib__decoder__struct { + return wuffs_zlib__decoder__set_quirk(this, a_key, a_value); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_zlib__decoder__history_retain_length(this); ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_zlib__decoder__dst_history_retain_length(this); + } + + inline wuffs_base__range_ii_u64 +@@ -11184,11 +12262,9 @@ extern const char wuffs_png__error__unsupported_png_file[]; + + // ---------------- Public Consts + +-#define WUFFS_PNG__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 ++#define WUFFS_PNG__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 2251799562027015u + +-#define WUFFS_PNG__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 2251799562027015 +- +-#define WUFFS_PNG__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 8 ++#define WUFFS_PNG__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 8u + + // ---------------- Struct Declarations + +@@ -11321,11 +12397,6 @@ wuffs_png__decoder__tell_me_more( + wuffs_base__more_information* a_minfo, + wuffs_base__io_buffer* a_src); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_png__decoder__history_retain_length( +- const wuffs_png__decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 + wuffs_png__decoder__workbuf_len( +@@ -11438,26 +12509,26 @@ struct wuffs_png__decoder__struct { + wuffs_png__decoder* self, + wuffs_base__slice_u8 a_curr, + wuffs_base__slice_u8 a_prev); +- uint32_t p_decode_image_config[1]; +- uint32_t p_do_decode_image_config[1]; +- uint32_t p_decode_ihdr[1]; +- uint32_t p_decode_other_chunk[1]; +- uint32_t p_decode_actl[1]; +- uint32_t p_decode_chrm[1]; +- uint32_t p_decode_fctl[1]; +- uint32_t p_decode_gama[1]; +- uint32_t p_decode_iccp[1]; +- uint32_t p_decode_plte[1]; +- uint32_t p_decode_srgb[1]; +- uint32_t p_decode_trns[1]; +- uint32_t p_decode_frame_config[1]; +- uint32_t p_do_decode_frame_config[1]; +- uint32_t p_skip_frame[1]; +- uint32_t p_decode_frame[1]; +- uint32_t p_do_decode_frame[1]; +- uint32_t p_decode_pass[1]; +- uint32_t p_tell_me_more[1]; +- uint32_t p_do_tell_me_more[1]; ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_decode_ihdr; ++ uint32_t p_decode_other_chunk; ++ uint32_t p_decode_actl; ++ uint32_t p_decode_chrm; ++ uint32_t p_decode_fctl; ++ uint32_t p_decode_gama; ++ uint32_t p_decode_iccp; ++ uint32_t p_decode_plte; ++ uint32_t p_decode_srgb; ++ uint32_t p_decode_trns; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_skip_frame; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; ++ uint32_t p_decode_pass; ++ uint32_t p_tell_me_more; ++ uint32_t p_do_tell_me_more; + wuffs_base__status (*choosy_filter_and_swizzle)( + wuffs_png__decoder* self, + wuffs_base__pixel_buffer* a_dst, +@@ -11473,54 +12544,54 @@ struct wuffs_png__decoder__struct { + struct { + uint32_t v_checksum_have; + uint64_t scratch; +- } s_do_decode_image_config[1]; ++ } s_do_decode_image_config; + struct { + uint64_t scratch; +- } s_decode_ihdr[1]; ++ } s_decode_ihdr; + struct { + uint64_t scratch; +- } s_decode_other_chunk[1]; ++ } s_decode_other_chunk; + struct { + uint64_t scratch; +- } s_decode_actl[1]; ++ } s_decode_actl; + struct { + uint64_t scratch; +- } s_decode_chrm[1]; ++ } s_decode_chrm; + struct { + uint32_t v_x0; + uint32_t v_x1; + uint32_t v_y1; + uint64_t scratch; +- } s_decode_fctl[1]; ++ } s_decode_fctl; + struct { + uint64_t scratch; +- } s_decode_gama[1]; ++ } s_decode_gama; + struct { + uint32_t v_num_entries; + uint32_t v_i; + uint64_t scratch; +- } s_decode_plte[1]; ++ } s_decode_plte; + struct { + uint32_t v_i; + uint32_t v_n; + uint64_t scratch; +- } s_decode_trns[1]; ++ } s_decode_trns; + struct { + uint64_t scratch; +- } s_do_decode_frame_config[1]; ++ } s_do_decode_frame_config; + struct { + uint64_t scratch; +- } s_skip_frame[1]; ++ } s_skip_frame; + struct { + uint64_t scratch; +- } s_do_decode_frame[1]; ++ } s_do_decode_frame; + struct { + uint64_t scratch; +- } s_decode_pass[1]; ++ } s_decode_pass; + struct { + wuffs_base__status v_zlib_status; + uint64_t scratch; +- } s_do_tell_me_more[1]; ++ } s_do_tell_me_more; + } private_data; + + #ifdef __cplusplus +@@ -11664,11 +12735,6 @@ struct wuffs_png__decoder__struct { + return wuffs_png__decoder__tell_me_more(this, a_dst, a_minfo, a_src); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_png__decoder__history_retain_length(this); +- } +- + inline wuffs_base__range_ii_u64 + workbuf_len() const { + return wuffs_png__decoder__workbuf_len(this); +@@ -11681,24 +12747,21 @@ struct wuffs_png__decoder__struct { + + #endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG) || defined(WUFFS_NONMONOLITHIC) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) || defined(WUFFS_NONMONOLITHIC) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__QOI) || defined(WUFFS_NONMONOLITHIC) + + // ---------------- Status Codes + +-extern const char wuffs_tga__error__bad_header[]; +-extern const char wuffs_tga__error__bad_run_length_encoding[]; +-extern const char wuffs_tga__error__truncated_input[]; +-extern const char wuffs_tga__error__unsupported_tga_file[]; ++extern const char wuffs_qoi__error__bad_footer[]; ++extern const char wuffs_qoi__error__bad_header[]; ++extern const char wuffs_qoi__error__truncated_input[]; + + // ---------------- Public Consts + +-#define WUFFS_TGA__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 +- +-#define WUFFS_TGA__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 ++#define WUFFS_QOI__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + + // ---------------- Struct Declarations + +-typedef struct wuffs_tga__decoder__struct wuffs_tga__decoder; ++typedef struct wuffs_qoi__decoder__struct wuffs_qoi__decoder; + + #ifdef __cplusplus + extern "C" { +@@ -11713,14 +12776,14 @@ extern "C" { + // Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_tga__decoder__initialize( +- wuffs_tga__decoder* self, ++wuffs_qoi__decoder__initialize( ++ wuffs_qoi__decoder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options); + + size_t +-sizeof__wuffs_tga__decoder(void); ++sizeof__wuffs_qoi__decoder(void); + + // ---------------- Allocs + +@@ -11730,19 +12793,19 @@ sizeof__wuffs_tga__decoder(void); + // calling free on the returned pointer. That pointer is effectively a C++ + // std::unique_ptr. + +-wuffs_tga__decoder* +-wuffs_tga__decoder__alloc(void); ++wuffs_qoi__decoder* ++wuffs_qoi__decoder__alloc(void); + + static inline wuffs_base__image_decoder* +-wuffs_tga__decoder__alloc_as__wuffs_base__image_decoder(void) { +- return (wuffs_base__image_decoder*)(wuffs_tga__decoder__alloc()); ++wuffs_qoi__decoder__alloc_as__wuffs_base__image_decoder(void) { ++ return (wuffs_base__image_decoder*)(wuffs_qoi__decoder__alloc()); + } + + // ---------------- Upcasts + + static inline wuffs_base__image_decoder* +-wuffs_tga__decoder__upcast_as__wuffs_base__image_decoder( +- wuffs_tga__decoder* p) { ++wuffs_qoi__decoder__upcast_as__wuffs_base__image_decoder( ++ wuffs_qoi__decoder* p) { + return (wuffs_base__image_decoder*)p; + } + +@@ -11750,35 +12813,35 @@ wuffs_tga__decoder__upcast_as__wuffs_base__image_decoder( + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_tga__decoder__get_quirk( +- const wuffs_tga__decoder* self, ++wuffs_qoi__decoder__get_quirk( ++ const wuffs_qoi__decoder* self, + uint32_t a_key); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__set_quirk( +- wuffs_tga__decoder* self, ++wuffs_qoi__decoder__set_quirk( ++ wuffs_qoi__decoder* self, + uint32_t a_key, + uint64_t a_value); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__decode_image_config( +- wuffs_tga__decoder* self, ++wuffs_qoi__decoder__decode_image_config( ++ wuffs_qoi__decoder* self, + wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__decode_frame_config( +- wuffs_tga__decoder* self, ++wuffs_qoi__decoder__decode_frame_config( ++ wuffs_qoi__decoder* self, + wuffs_base__frame_config* a_dst, + wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__decode_frame( +- wuffs_tga__decoder* self, ++wuffs_qoi__decoder__decode_frame( ++ wuffs_qoi__decoder* self, + wuffs_base__pixel_buffer* a_dst, + wuffs_base__io_buffer* a_src, + wuffs_base__pixel_blend a_blend, +@@ -11787,55 +12850,50 @@ wuffs_tga__decoder__decode_frame( + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_tga__decoder__frame_dirty_rect( +- const wuffs_tga__decoder* self); ++wuffs_qoi__decoder__frame_dirty_rect( ++ const wuffs_qoi__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_tga__decoder__num_animation_loops( +- const wuffs_tga__decoder* self); ++wuffs_qoi__decoder__num_animation_loops( ++ const wuffs_qoi__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_tga__decoder__num_decoded_frame_configs( +- const wuffs_tga__decoder* self); ++wuffs_qoi__decoder__num_decoded_frame_configs( ++ const wuffs_qoi__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_tga__decoder__num_decoded_frames( +- const wuffs_tga__decoder* self); ++wuffs_qoi__decoder__num_decoded_frames( ++ const wuffs_qoi__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__restart_frame( +- wuffs_tga__decoder* self, ++wuffs_qoi__decoder__restart_frame( ++ wuffs_qoi__decoder* self, + uint64_t a_index, + uint64_t a_io_position); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_tga__decoder__set_report_metadata( +- wuffs_tga__decoder* self, ++wuffs_qoi__decoder__set_report_metadata( ++ wuffs_qoi__decoder* self, + uint32_t a_fourcc, + bool a_report); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__tell_me_more( +- wuffs_tga__decoder* self, ++wuffs_qoi__decoder__tell_me_more( ++ wuffs_qoi__decoder* self, + wuffs_base__io_buffer* a_dst, + wuffs_base__more_information* a_minfo, + wuffs_base__io_buffer* a_src); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_tga__decoder__history_retain_length( +- const wuffs_tga__decoder* self); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_tga__decoder__workbuf_len( +- const wuffs_tga__decoder* self); ++wuffs_qoi__decoder__workbuf_len( ++ const wuffs_qoi__decoder* self); + + #ifdef __cplusplus + } // extern "C" +@@ -11850,7 +12908,7 @@ wuffs_tga__decoder__workbuf_len( + + #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-struct wuffs_tga__decoder__struct { ++struct wuffs_qoi__decoder__struct { + // Do not access the private_impl's or private_data's fields directly. There + // is no API/ABI compatibility or safety guarantee if you do so. Instead, use + // the wuffs_foo__bar__baz functions. +@@ -11864,69 +12922,58 @@ struct wuffs_tga__decoder__struct { + wuffs_base__vtable vtable_for__wuffs_base__image_decoder; + wuffs_base__vtable null_vtable; + ++ uint32_t f_pixfmt; + uint32_t f_width; + uint32_t f_height; ++ uint64_t f_remaining_pixels_times_4; + uint8_t f_call_sequence; +- uint8_t f_header_id_length; +- uint8_t f_header_color_map_type; +- uint8_t f_header_image_type; +- uint16_t f_header_color_map_first_entry_index; +- uint16_t f_header_color_map_length; +- uint8_t f_header_color_map_entry_size; +- uint8_t f_header_pixel_depth; +- uint8_t f_header_image_descriptor; +- bool f_opaque; +- uint32_t f_scratch_bytes_per_pixel; +- uint32_t f_src_bytes_per_pixel; +- uint32_t f_src_pixfmt; +- uint64_t f_frame_config_io_position; ++ uint32_t f_buffer_index; ++ uint32_t f_dst_x; ++ uint32_t f_dst_y; + wuffs_base__pixel_swizzler f_swizzler; + +- uint32_t p_decode_image_config[1]; +- uint32_t p_do_decode_image_config[1]; +- uint32_t p_decode_frame_config[1]; +- uint32_t p_do_decode_frame_config[1]; +- uint32_t p_decode_frame[1]; +- uint32_t p_do_decode_frame[1]; ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; ++ uint32_t p_from_src_to_buffer; + } private_impl; + + struct { +- uint8_t f_dst_palette[1024]; +- uint8_t f_src_palette[1024]; +- uint8_t f_scratch[4]; ++ uint8_t f_pixel[4]; ++ uint8_t f_cache[256]; ++ uint8_t f_buffer[8196]; + + struct { +- uint32_t v_i; + uint64_t scratch; +- } s_do_decode_image_config[1]; ++ } s_do_decode_image_config; + struct { +- uint64_t v_dst_bytes_per_pixel; +- uint32_t v_dst_x; +- uint32_t v_dst_y; +- uint64_t v_mark; +- uint32_t v_num_pixels32; +- uint32_t v_lit_length; +- uint32_t v_run_length; +- uint64_t v_num_dst_bytes; + uint64_t scratch; +- } s_do_decode_frame[1]; ++ } s_do_decode_frame; ++ struct { ++ uint8_t v_dg; ++ uint32_t v_bi; ++ uint32_t v_bk; ++ } s_from_src_to_buffer; + } private_data; + + #ifdef __cplusplus + #if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) +- using unique_ptr = std::unique_ptr; ++ using unique_ptr = std::unique_ptr; + + // On failure, the alloc_etc functions return nullptr. They don't throw. + + static inline unique_ptr + alloc() { +- return unique_ptr(wuffs_tga__decoder__alloc()); ++ return unique_ptr(wuffs_qoi__decoder__alloc()); + } + + static inline wuffs_base__image_decoder::unique_ptr + alloc_as__wuffs_base__image_decoder() { + return wuffs_base__image_decoder::unique_ptr( +- wuffs_tga__decoder__alloc_as__wuffs_base__image_decoder()); ++ wuffs_qoi__decoder__alloc_as__wuffs_base__image_decoder()); + } + #endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +@@ -11942,10 +12989,10 @@ struct wuffs_tga__decoder__struct { + // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in + // order to provide convenience methods. These forward on "this", so that you + // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". +- wuffs_tga__decoder__struct() = delete; +- wuffs_tga__decoder__struct(const wuffs_tga__decoder__struct&) = delete; +- wuffs_tga__decoder__struct& operator=( +- const wuffs_tga__decoder__struct&) = delete; ++ wuffs_qoi__decoder__struct() = delete; ++ wuffs_qoi__decoder__struct(const wuffs_qoi__decoder__struct&) = delete; ++ wuffs_qoi__decoder__struct& operator=( ++ const wuffs_qoi__decoder__struct&) = delete; + #endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + + #if !defined(WUFFS_IMPLEMENTATION) +@@ -11965,7 +13012,7 @@ struct wuffs_tga__decoder__struct { + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options) { +- return wuffs_tga__decoder__initialize( ++ return wuffs_qoi__decoder__initialize( + this, sizeof_star_self, wuffs_version, options); + } + +@@ -11977,28 +13024,28 @@ struct wuffs_tga__decoder__struct { + inline uint64_t + get_quirk( + uint32_t a_key) const { +- return wuffs_tga__decoder__get_quirk(this, a_key); ++ return wuffs_qoi__decoder__get_quirk(this, a_key); + } + + inline wuffs_base__status + set_quirk( + uint32_t a_key, + uint64_t a_value) { +- return wuffs_tga__decoder__set_quirk(this, a_key, a_value); ++ return wuffs_qoi__decoder__set_quirk(this, a_key, a_value); + } + + inline wuffs_base__status + decode_image_config( + wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { +- return wuffs_tga__decoder__decode_image_config(this, a_dst, a_src); ++ return wuffs_qoi__decoder__decode_image_config(this, a_dst, a_src); + } + + inline wuffs_base__status + decode_frame_config( + wuffs_base__frame_config* a_dst, + wuffs_base__io_buffer* a_src) { +- return wuffs_tga__decoder__decode_frame_config(this, a_dst, a_src); ++ return wuffs_qoi__decoder__decode_frame_config(this, a_dst, a_src); + } + + inline wuffs_base__status +@@ -12008,41 +13055,41 @@ struct wuffs_tga__decoder__struct { + wuffs_base__pixel_blend a_blend, + wuffs_base__slice_u8 a_workbuf, + wuffs_base__decode_frame_options* a_opts) { +- return wuffs_tga__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); ++ return wuffs_qoi__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); + } + + inline wuffs_base__rect_ie_u32 + frame_dirty_rect() const { +- return wuffs_tga__decoder__frame_dirty_rect(this); ++ return wuffs_qoi__decoder__frame_dirty_rect(this); + } + + inline uint32_t + num_animation_loops() const { +- return wuffs_tga__decoder__num_animation_loops(this); ++ return wuffs_qoi__decoder__num_animation_loops(this); + } + + inline uint64_t + num_decoded_frame_configs() const { +- return wuffs_tga__decoder__num_decoded_frame_configs(this); ++ return wuffs_qoi__decoder__num_decoded_frame_configs(this); + } + + inline uint64_t + num_decoded_frames() const { +- return wuffs_tga__decoder__num_decoded_frames(this); ++ return wuffs_qoi__decoder__num_decoded_frames(this); + } + + inline wuffs_base__status + restart_frame( + uint64_t a_index, + uint64_t a_io_position) { +- return wuffs_tga__decoder__restart_frame(this, a_index, a_io_position); ++ return wuffs_qoi__decoder__restart_frame(this, a_index, a_io_position); + } + + inline wuffs_base__empty_struct + set_report_metadata( + uint32_t a_fourcc, + bool a_report) { +- return wuffs_tga__decoder__set_report_metadata(this, a_fourcc, a_report); ++ return wuffs_qoi__decoder__set_report_metadata(this, a_fourcc, a_report); + } + + inline wuffs_base__status +@@ -12050,42 +13097,30 @@ struct wuffs_tga__decoder__struct { + wuffs_base__io_buffer* a_dst, + wuffs_base__more_information* a_minfo, + wuffs_base__io_buffer* a_src) { +- return wuffs_tga__decoder__tell_me_more(this, a_dst, a_minfo, a_src); +- } +- +- inline uint64_t +- history_retain_length() const { +- return wuffs_tga__decoder__history_retain_length(this); ++ return wuffs_qoi__decoder__tell_me_more(this, a_dst, a_minfo, a_src); + } + + inline wuffs_base__range_ii_u64 + workbuf_len() const { +- return wuffs_tga__decoder__workbuf_len(this); ++ return wuffs_qoi__decoder__workbuf_len(this); + } + + #endif // __cplusplus +-}; // struct wuffs_tga__decoder__struct ++}; // struct wuffs_qoi__decoder__struct + + #endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) || defined(WUFFS_NONMONOLITHIC) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__QOI) || defined(WUFFS_NONMONOLITHIC) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) || defined(WUFFS_NONMONOLITHIC) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__SHA256) || defined(WUFFS_NONMONOLITHIC) + + // ---------------- Status Codes + +-extern const char wuffs_wbmp__error__bad_header[]; +-extern const char wuffs_wbmp__error__truncated_input[]; +- + // ---------------- Public Consts + +-#define WUFFS_WBMP__DECODER_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0 +- +-#define WUFFS_WBMP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0 +- + // ---------------- Struct Declarations + +-typedef struct wuffs_wbmp__decoder__struct wuffs_wbmp__decoder; ++typedef struct wuffs_sha256__hasher__struct wuffs_sha256__hasher; + + #ifdef __cplusplus + extern "C" { +@@ -12100,14 +13135,14 @@ extern "C" { + // Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_wbmp__decoder__initialize( +- wuffs_wbmp__decoder* self, ++wuffs_sha256__hasher__initialize( ++ wuffs_sha256__hasher* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options); + + size_t +-sizeof__wuffs_wbmp__decoder(void); ++sizeof__wuffs_sha256__hasher(void); + + // ---------------- Allocs + +@@ -12117,112 +13152,53 @@ sizeof__wuffs_wbmp__decoder(void); + // calling free on the returned pointer. That pointer is effectively a C++ + // std::unique_ptr. + +-wuffs_wbmp__decoder* +-wuffs_wbmp__decoder__alloc(void); ++wuffs_sha256__hasher* ++wuffs_sha256__hasher__alloc(void); + +-static inline wuffs_base__image_decoder* +-wuffs_wbmp__decoder__alloc_as__wuffs_base__image_decoder(void) { +- return (wuffs_base__image_decoder*)(wuffs_wbmp__decoder__alloc()); ++static inline wuffs_base__hasher_bitvec256* ++wuffs_sha256__hasher__alloc_as__wuffs_base__hasher_bitvec256(void) { ++ return (wuffs_base__hasher_bitvec256*)(wuffs_sha256__hasher__alloc()); + } + + // ---------------- Upcasts + +-static inline wuffs_base__image_decoder* +-wuffs_wbmp__decoder__upcast_as__wuffs_base__image_decoder( +- wuffs_wbmp__decoder* p) { +- return (wuffs_base__image_decoder*)p; ++static inline wuffs_base__hasher_bitvec256* ++wuffs_sha256__hasher__upcast_as__wuffs_base__hasher_bitvec256( ++ wuffs_sha256__hasher* p) { ++ return (wuffs_base__hasher_bitvec256*)p; + } + + // ---------------- Public Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_wbmp__decoder__get_quirk( +- const wuffs_wbmp__decoder* self, ++wuffs_sha256__hasher__get_quirk( ++ const wuffs_sha256__hasher* self, + uint32_t a_key); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__set_quirk( +- wuffs_wbmp__decoder* self, ++wuffs_sha256__hasher__set_quirk( ++ wuffs_sha256__hasher* self, + uint32_t a_key, + uint64_t a_value); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__decode_image_config( +- wuffs_wbmp__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__decode_frame_config( +- wuffs_wbmp__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__decode_frame( +- wuffs_wbmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_wbmp__decoder__frame_dirty_rect( +- const wuffs_wbmp__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_wbmp__decoder__num_animation_loops( +- const wuffs_wbmp__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_wbmp__decoder__num_decoded_frame_configs( +- const wuffs_wbmp__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_wbmp__decoder__num_decoded_frames( +- const wuffs_wbmp__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__restart_frame( +- wuffs_wbmp__decoder* self, +- uint64_t a_index, +- uint64_t a_io_position); +- + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_wbmp__decoder__set_report_metadata( +- wuffs_wbmp__decoder* self, +- uint32_t a_fourcc, +- bool a_report); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__tell_me_more( +- wuffs_wbmp__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src); ++wuffs_sha256__hasher__update( ++ wuffs_sha256__hasher* self, ++ wuffs_base__slice_u8 a_x); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_wbmp__decoder__history_retain_length( +- const wuffs_wbmp__decoder* self); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__bitvec256 ++wuffs_sha256__hasher__update_bitvec256( ++ wuffs_sha256__hasher* self, ++ wuffs_base__slice_u8 a_x); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_wbmp__decoder__workbuf_len( +- const wuffs_wbmp__decoder* self); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__bitvec256 ++wuffs_sha256__hasher__checksum_bitvec256( ++ const wuffs_sha256__hasher* self); + + #ifdef __cplusplus + } // extern "C" +@@ -12237,7 +13213,7 @@ wuffs_wbmp__decoder__workbuf_len( + + #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-struct wuffs_wbmp__decoder__struct { ++struct wuffs_sha256__hasher__struct { + // Do not access the private_impl's or private_data's fields directly. There + // is no API/ABI compatibility or safety guarantee if you do so. Instead, use + // the wuffs_foo__bar__baz functions. +@@ -12248,52 +13224,41 @@ struct wuffs_wbmp__decoder__struct { + struct { + uint32_t magic; + uint32_t active_coroutine; +- wuffs_base__vtable vtable_for__wuffs_base__image_decoder; ++ wuffs_base__vtable vtable_for__wuffs_base__hasher_bitvec256; + wuffs_base__vtable null_vtable; + +- uint32_t f_width; +- uint32_t f_height; +- uint8_t f_call_sequence; +- uint64_t f_frame_config_io_position; +- wuffs_base__pixel_swizzler f_swizzler; +- +- uint32_t p_decode_image_config[1]; +- uint32_t p_do_decode_image_config[1]; +- uint32_t p_decode_frame_config[1]; +- uint32_t p_do_decode_frame_config[1]; +- uint32_t p_decode_frame[1]; +- uint32_t p_do_decode_frame[1]; ++ uint64_t f_length_modulo_u64; ++ bool f_length_overflows_u64; ++ uint8_t f_padding0; ++ uint8_t f_padding1; ++ uint8_t f_padding2; ++ uint32_t f_buf_len; ++ uint8_t f_buf_data[64]; ++ uint32_t f_h0; ++ uint32_t f_h1; ++ uint32_t f_h2; ++ uint32_t f_h3; ++ uint32_t f_h4; ++ uint32_t f_h5; ++ uint32_t f_h6; ++ uint32_t f_h7; + } private_impl; + +- struct { +- struct { +- uint32_t v_i; +- uint32_t v_p; +- } s_do_decode_image_config[1]; +- struct { +- uint64_t v_dst_bytes_per_pixel; +- uint32_t v_dst_x; +- uint32_t v_dst_y; +- uint8_t v_src[1]; +- uint8_t v_c; +- } s_do_decode_frame[1]; +- } private_data; +- + #ifdef __cplusplus + #if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) +- using unique_ptr = std::unique_ptr; ++ using unique_ptr = std::unique_ptr; + + // On failure, the alloc_etc functions return nullptr. They don't throw. + + static inline unique_ptr + alloc() { +- return unique_ptr(wuffs_wbmp__decoder__alloc()); ++ return unique_ptr(wuffs_sha256__hasher__alloc()); + } + +- static inline wuffs_base__image_decoder::unique_ptr +- alloc_as__wuffs_base__image_decoder() { +- return wuffs_base__image_decoder::unique_ptr( +- wuffs_wbmp__decoder__alloc_as__wuffs_base__image_decoder()); ++ static inline wuffs_base__hasher_bitvec256::unique_ptr ++ alloc_as__wuffs_base__hasher_bitvec256() { ++ return wuffs_base__hasher_bitvec256::unique_ptr( ++ wuffs_sha256__hasher__alloc_as__wuffs_base__hasher_bitvec256()); + } + #endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +@@ -12309,10 +13274,10 @@ struct wuffs_wbmp__decoder__struct { + // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in + // order to provide convenience methods. These forward on "this", so that you + // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". +- wuffs_wbmp__decoder__struct() = delete; +- wuffs_wbmp__decoder__struct(const wuffs_wbmp__decoder__struct&) = delete; +- wuffs_wbmp__decoder__struct& operator=( +- const wuffs_wbmp__decoder__struct&) = delete; ++ wuffs_sha256__hasher__struct() = delete; ++ wuffs_sha256__hasher__struct(const wuffs_sha256__hasher__struct&) = delete; ++ wuffs_sha256__hasher__struct& operator=( ++ const wuffs_sha256__hasher__struct&) = delete; + #endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + + #if !defined(WUFFS_IMPLEMENTATION) +@@ -12332,120 +13297,68 @@ struct wuffs_wbmp__decoder__struct { + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options) { +- return wuffs_wbmp__decoder__initialize( ++ return wuffs_sha256__hasher__initialize( + this, sizeof_star_self, wuffs_version, options); + } + +- inline wuffs_base__image_decoder* +- upcast_as__wuffs_base__image_decoder() { +- return (wuffs_base__image_decoder*)this; ++ inline wuffs_base__hasher_bitvec256* ++ upcast_as__wuffs_base__hasher_bitvec256() { ++ return (wuffs_base__hasher_bitvec256*)this; + } + + inline uint64_t + get_quirk( + uint32_t a_key) const { +- return wuffs_wbmp__decoder__get_quirk(this, a_key); ++ return wuffs_sha256__hasher__get_quirk(this, a_key); + } + + inline wuffs_base__status + set_quirk( + uint32_t a_key, + uint64_t a_value) { +- return wuffs_wbmp__decoder__set_quirk(this, a_key, a_value); +- } +- +- inline wuffs_base__status +- decode_image_config( +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- return wuffs_wbmp__decoder__decode_image_config(this, a_dst, a_src); +- } +- +- inline wuffs_base__status +- decode_frame_config( +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- return wuffs_wbmp__decoder__decode_frame_config(this, a_dst, a_src); +- } +- +- inline wuffs_base__status +- decode_frame( +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- return wuffs_wbmp__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); +- } +- +- inline wuffs_base__rect_ie_u32 +- frame_dirty_rect() const { +- return wuffs_wbmp__decoder__frame_dirty_rect(this); +- } +- +- inline uint32_t +- num_animation_loops() const { +- return wuffs_wbmp__decoder__num_animation_loops(this); +- } +- +- inline uint64_t +- num_decoded_frame_configs() const { +- return wuffs_wbmp__decoder__num_decoded_frame_configs(this); +- } +- +- inline uint64_t +- num_decoded_frames() const { +- return wuffs_wbmp__decoder__num_decoded_frames(this); +- } +- +- inline wuffs_base__status +- restart_frame( +- uint64_t a_index, +- uint64_t a_io_position) { +- return wuffs_wbmp__decoder__restart_frame(this, a_index, a_io_position); ++ return wuffs_sha256__hasher__set_quirk(this, a_key, a_value); + } + + inline wuffs_base__empty_struct +- set_report_metadata( +- uint32_t a_fourcc, +- bool a_report) { +- return wuffs_wbmp__decoder__set_report_metadata(this, a_fourcc, a_report); +- } +- +- inline wuffs_base__status +- tell_me_more( +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- return wuffs_wbmp__decoder__tell_me_more(this, a_dst, a_minfo, a_src); ++ update( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_sha256__hasher__update(this, a_x); + } + +- inline uint64_t +- history_retain_length() const { +- return wuffs_wbmp__decoder__history_retain_length(this); ++ inline wuffs_base__bitvec256 ++ update_bitvec256( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_sha256__hasher__update_bitvec256(this, a_x); + } + +- inline wuffs_base__range_ii_u64 +- workbuf_len() const { +- return wuffs_wbmp__decoder__workbuf_len(this); ++ inline wuffs_base__bitvec256 ++ checksum_bitvec256() const { ++ return wuffs_sha256__hasher__checksum_bitvec256(this); + } + + #endif // __cplusplus +-}; // struct wuffs_wbmp__decoder__struct ++}; // struct wuffs_sha256__hasher__struct + + #endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) || defined(WUFFS_NONMONOLITHIC) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__SHA256) || defined(WUFFS_NONMONOLITHIC) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH32) || defined(WUFFS_NONMONOLITHIC) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) || defined(WUFFS_NONMONOLITHIC) + + // ---------------- Status Codes + ++extern const char wuffs_tga__error__bad_header[]; ++extern const char wuffs_tga__error__bad_run_length_encoding[]; ++extern const char wuffs_tga__error__truncated_input[]; ++extern const char wuffs_tga__error__unsupported_tga_file[]; ++ + // ---------------- Public Consts + ++#define WUFFS_TGA__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u ++ + // ---------------- Struct Declarations + +-typedef struct wuffs_xxhash32__hasher__struct wuffs_xxhash32__hasher; ++typedef struct wuffs_tga__decoder__struct wuffs_tga__decoder; + + #ifdef __cplusplus + extern "C" { +@@ -12460,14 +13373,14 @@ extern "C" { + // Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_xxhash32__hasher__initialize( +- wuffs_xxhash32__hasher* self, ++wuffs_tga__decoder__initialize( ++ wuffs_tga__decoder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options); + + size_t +-sizeof__wuffs_xxhash32__hasher(void); ++sizeof__wuffs_tga__decoder(void); + + // ---------------- Allocs + +@@ -12477,53 +13390,107 @@ sizeof__wuffs_xxhash32__hasher(void); + // calling free on the returned pointer. That pointer is effectively a C++ + // std::unique_ptr. + +-wuffs_xxhash32__hasher* +-wuffs_xxhash32__hasher__alloc(void); ++wuffs_tga__decoder* ++wuffs_tga__decoder__alloc(void); + +-static inline wuffs_base__hasher_u32* +-wuffs_xxhash32__hasher__alloc_as__wuffs_base__hasher_u32(void) { +- return (wuffs_base__hasher_u32*)(wuffs_xxhash32__hasher__alloc()); ++static inline wuffs_base__image_decoder* ++wuffs_tga__decoder__alloc_as__wuffs_base__image_decoder(void) { ++ return (wuffs_base__image_decoder*)(wuffs_tga__decoder__alloc()); + } + + // ---------------- Upcasts + +-static inline wuffs_base__hasher_u32* +-wuffs_xxhash32__hasher__upcast_as__wuffs_base__hasher_u32( +- wuffs_xxhash32__hasher* p) { +- return (wuffs_base__hasher_u32*)p; ++static inline wuffs_base__image_decoder* ++wuffs_tga__decoder__upcast_as__wuffs_base__image_decoder( ++ wuffs_tga__decoder* p) { ++ return (wuffs_base__image_decoder*)p; + } + + // ---------------- Public Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_xxhash32__hasher__get_quirk( +- const wuffs_xxhash32__hasher* self, ++wuffs_tga__decoder__get_quirk( ++ const wuffs_tga__decoder* self, + uint32_t a_key); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_xxhash32__hasher__set_quirk( +- wuffs_xxhash32__hasher* self, ++wuffs_tga__decoder__set_quirk( ++ wuffs_tga__decoder* self, + uint32_t a_key, + uint64_t a_value); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_xxhash32__hasher__update( +- wuffs_xxhash32__hasher* self, +- wuffs_base__slice_u8 a_x); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__decode_image_config( ++ wuffs_tga__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_xxhash32__hasher__update_u32( +- wuffs_xxhash32__hasher* self, +- wuffs_base__slice_u8 a_x); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__decode_frame_config( ++ wuffs_tga__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__decode_frame( ++ wuffs_tga__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_tga__decoder__frame_dirty_rect( ++ const wuffs_tga__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_xxhash32__hasher__checksum_u32( +- const wuffs_xxhash32__hasher* self); ++wuffs_tga__decoder__num_animation_loops( ++ const wuffs_tga__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_tga__decoder__num_decoded_frame_configs( ++ const wuffs_tga__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_tga__decoder__num_decoded_frames( ++ const wuffs_tga__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__restart_frame( ++ wuffs_tga__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_tga__decoder__set_report_metadata( ++ wuffs_tga__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__tell_me_more( ++ wuffs_tga__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_tga__decoder__workbuf_len( ++ const wuffs_tga__decoder* self); + + #ifdef __cplusplus + } // extern "C" +@@ -12538,7 +13505,7 @@ wuffs_xxhash32__hasher__checksum_u32( + + #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-struct wuffs_xxhash32__hasher__struct { ++struct wuffs_tga__decoder__struct { + // Do not access the private_impl's or private_data's fields directly. There + // is no API/ABI compatibility or safety guarantee if you do so. Instead, use + // the wuffs_foo__bar__baz functions. +@@ -12549,36 +13516,72 @@ struct wuffs_xxhash32__hasher__struct { + struct { + uint32_t magic; + uint32_t active_coroutine; +- wuffs_base__vtable vtable_for__wuffs_base__hasher_u32; ++ wuffs_base__vtable vtable_for__wuffs_base__image_decoder; + wuffs_base__vtable null_vtable; + +- uint32_t f_length_modulo_u32; +- bool f_length_overflows_u32; +- uint8_t f_padding0; +- uint8_t f_padding1; +- uint8_t f_buf_len; +- uint8_t f_buf_data[16]; +- uint32_t f_v0; +- uint32_t f_v1; +- uint32_t f_v2; +- uint32_t f_v3; ++ uint32_t f_width; ++ uint32_t f_height; ++ uint8_t f_call_sequence; ++ uint8_t f_header_id_length; ++ uint8_t f_header_color_map_type; ++ uint8_t f_header_image_type; ++ uint16_t f_header_color_map_first_entry_index; ++ uint16_t f_header_color_map_length; ++ uint8_t f_header_color_map_entry_size; ++ uint8_t f_header_pixel_depth; ++ uint8_t f_header_image_descriptor; ++ bool f_opaque; ++ uint32_t f_scratch_bytes_per_pixel; ++ uint32_t f_src_bytes_per_pixel; ++ uint32_t f_src_pixfmt; ++ uint64_t f_frame_config_io_position; ++ wuffs_base__pixel_swizzler f_swizzler; ++ ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; + } private_impl; + ++ struct { ++ uint8_t f_dst_palette[1024]; ++ uint8_t f_src_palette[1024]; ++ uint8_t f_scratch[4]; ++ ++ struct { ++ uint32_t v_i; ++ uint64_t scratch; ++ } s_do_decode_image_config; ++ struct { ++ uint64_t v_dst_bytes_per_pixel; ++ uint32_t v_dst_x; ++ uint32_t v_dst_y; ++ uint64_t v_mark; ++ uint32_t v_num_pixels32; ++ uint32_t v_lit_length; ++ uint32_t v_run_length; ++ uint64_t v_num_dst_bytes; ++ uint64_t scratch; ++ } s_do_decode_frame; ++ } private_data; ++ + #ifdef __cplusplus + #if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) +- using unique_ptr = std::unique_ptr; ++ using unique_ptr = std::unique_ptr; + + // On failure, the alloc_etc functions return nullptr. They don't throw. + + static inline unique_ptr + alloc() { +- return unique_ptr(wuffs_xxhash32__hasher__alloc()); ++ return unique_ptr(wuffs_tga__decoder__alloc()); + } + +- static inline wuffs_base__hasher_u32::unique_ptr +- alloc_as__wuffs_base__hasher_u32() { +- return wuffs_base__hasher_u32::unique_ptr( +- wuffs_xxhash32__hasher__alloc_as__wuffs_base__hasher_u32()); ++ static inline wuffs_base__image_decoder::unique_ptr ++ alloc_as__wuffs_base__image_decoder() { ++ return wuffs_base__image_decoder::unique_ptr( ++ wuffs_tga__decoder__alloc_as__wuffs_base__image_decoder()); + } + #endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +@@ -12594,10 +13597,10 @@ struct wuffs_xxhash32__hasher__struct { + // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in + // order to provide convenience methods. These forward on "this", so that you + // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". +- wuffs_xxhash32__hasher__struct() = delete; +- wuffs_xxhash32__hasher__struct(const wuffs_xxhash32__hasher__struct&) = delete; +- wuffs_xxhash32__hasher__struct& operator=( +- const wuffs_xxhash32__hasher__struct&) = delete; ++ wuffs_tga__decoder__struct() = delete; ++ wuffs_tga__decoder__struct(const wuffs_tga__decoder__struct&) = delete; ++ wuffs_tga__decoder__struct& operator=( ++ const wuffs_tga__decoder__struct&) = delete; + #endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + + #if !defined(WUFFS_IMPLEMENTATION) +@@ -12617,53 +13620,107 @@ struct wuffs_xxhash32__hasher__struct { + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options) { +- return wuffs_xxhash32__hasher__initialize( ++ return wuffs_tga__decoder__initialize( + this, sizeof_star_self, wuffs_version, options); + } + +- inline wuffs_base__hasher_u32* +- upcast_as__wuffs_base__hasher_u32() { +- return (wuffs_base__hasher_u32*)this; ++ inline wuffs_base__image_decoder* ++ upcast_as__wuffs_base__image_decoder() { ++ return (wuffs_base__image_decoder*)this; + } + + inline uint64_t + get_quirk( + uint32_t a_key) const { +- return wuffs_xxhash32__hasher__get_quirk(this, a_key); ++ return wuffs_tga__decoder__get_quirk(this, a_key); + } + + inline wuffs_base__status + set_quirk( + uint32_t a_key, + uint64_t a_value) { +- return wuffs_xxhash32__hasher__set_quirk(this, a_key, a_value); ++ return wuffs_tga__decoder__set_quirk(this, a_key, a_value); + } + +- inline wuffs_base__empty_struct +- update( +- wuffs_base__slice_u8 a_x) { +- return wuffs_xxhash32__hasher__update(this, a_x); ++ inline wuffs_base__status ++ decode_image_config( ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_tga__decoder__decode_image_config(this, a_dst, a_src); + } + +- inline uint32_t +- update_u32( +- wuffs_base__slice_u8 a_x) { +- return wuffs_xxhash32__hasher__update_u32(this, a_x); ++ inline wuffs_base__status ++ decode_frame_config( ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_tga__decoder__decode_frame_config(this, a_dst, a_src); ++ } ++ ++ inline wuffs_base__status ++ decode_frame( ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ return wuffs_tga__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); ++ } ++ ++ inline wuffs_base__rect_ie_u32 ++ frame_dirty_rect() const { ++ return wuffs_tga__decoder__frame_dirty_rect(this); + } + + inline uint32_t +- checksum_u32() const { +- return wuffs_xxhash32__hasher__checksum_u32(this); ++ num_animation_loops() const { ++ return wuffs_tga__decoder__num_animation_loops(this); ++ } ++ ++ inline uint64_t ++ num_decoded_frame_configs() const { ++ return wuffs_tga__decoder__num_decoded_frame_configs(this); ++ } ++ ++ inline uint64_t ++ num_decoded_frames() const { ++ return wuffs_tga__decoder__num_decoded_frames(this); ++ } ++ ++ inline wuffs_base__status ++ restart_frame( ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ return wuffs_tga__decoder__restart_frame(this, a_index, a_io_position); ++ } ++ ++ inline wuffs_base__empty_struct ++ set_report_metadata( ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_tga__decoder__set_report_metadata(this, a_fourcc, a_report); ++ } ++ ++ inline wuffs_base__status ++ tell_me_more( ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_tga__decoder__tell_me_more(this, a_dst, a_minfo, a_src); ++ } ++ ++ inline wuffs_base__range_ii_u64 ++ workbuf_len() const { ++ return wuffs_tga__decoder__workbuf_len(this); + } + + #endif // __cplusplus +-}; // struct wuffs_xxhash32__hasher__struct ++}; // struct wuffs_tga__decoder__struct + + #endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH32) || defined(WUFFS_NONMONOLITHIC) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) || defined(WUFFS_NONMONOLITHIC) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH64) || defined(WUFFS_NONMONOLITHIC) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__VP8) || defined(WUFFS_NONMONOLITHIC) + + // ---------------- Status Codes + +@@ -12671,7 +13728,7 @@ struct wuffs_xxhash32__hasher__struct { + + // ---------------- Struct Declarations + +-typedef struct wuffs_xxhash64__hasher__struct wuffs_xxhash64__hasher; ++typedef struct wuffs_vp8__placeholder__struct wuffs_vp8__placeholder; + + #ifdef __cplusplus + extern "C" { +@@ -12686,14 +13743,14 @@ extern "C" { + // Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_xxhash64__hasher__initialize( +- wuffs_xxhash64__hasher* self, ++wuffs_vp8__placeholder__initialize( ++ wuffs_vp8__placeholder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options); + + size_t +-sizeof__wuffs_xxhash64__hasher(void); ++sizeof__wuffs_vp8__placeholder(void); + + // ---------------- Allocs + +@@ -12703,54 +13760,13 @@ sizeof__wuffs_xxhash64__hasher(void); + // calling free on the returned pointer. That pointer is effectively a C++ + // std::unique_ptr. + +-wuffs_xxhash64__hasher* +-wuffs_xxhash64__hasher__alloc(void); +- +-static inline wuffs_base__hasher_u64* +-wuffs_xxhash64__hasher__alloc_as__wuffs_base__hasher_u64(void) { +- return (wuffs_base__hasher_u64*)(wuffs_xxhash64__hasher__alloc()); +-} ++wuffs_vp8__placeholder* ++wuffs_vp8__placeholder__alloc(void); + + // ---------------- Upcasts + +-static inline wuffs_base__hasher_u64* +-wuffs_xxhash64__hasher__upcast_as__wuffs_base__hasher_u64( +- wuffs_xxhash64__hasher* p) { +- return (wuffs_base__hasher_u64*)p; +-} +- + // ---------------- Public Function Prototypes + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_xxhash64__hasher__get_quirk( +- const wuffs_xxhash64__hasher* self, +- uint32_t a_key); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_xxhash64__hasher__set_quirk( +- wuffs_xxhash64__hasher* self, +- uint32_t a_key, +- uint64_t a_value); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_xxhash64__hasher__update( +- wuffs_xxhash64__hasher* self, +- wuffs_base__slice_u8 a_x); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_xxhash64__hasher__update_u64( +- wuffs_xxhash64__hasher* self, +- wuffs_base__slice_u8 a_x); +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_xxhash64__hasher__checksum_u64( +- const wuffs_xxhash64__hasher* self); +- + #ifdef __cplusplus + } // extern "C" + #endif +@@ -12764,7 +13780,7 @@ wuffs_xxhash64__hasher__checksum_u64( + + #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-struct wuffs_xxhash64__hasher__struct { ++struct wuffs_vp8__placeholder__struct { + // Do not access the private_impl's or private_data's fields directly. There + // is no API/ABI compatibility or safety guarantee if you do so. Instead, use + // the wuffs_foo__bar__baz functions. +@@ -12775,37 +13791,20 @@ struct wuffs_xxhash64__hasher__struct { + struct { + uint32_t magic; + uint32_t active_coroutine; +- wuffs_base__vtable vtable_for__wuffs_base__hasher_u64; + wuffs_base__vtable null_vtable; + +- uint64_t f_length_modulo_u64; +- bool f_length_overflows_u64; +- uint8_t f_padding0; +- uint8_t f_padding1; +- uint8_t f_padding2; +- uint32_t f_buf_len; +- uint8_t f_buf_data[32]; +- uint64_t f_v0; +- uint64_t f_v1; +- uint64_t f_v2; +- uint64_t f_v3; ++ uint32_t f_placeholder; + } private_impl; + + #ifdef __cplusplus + #if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) +- using unique_ptr = std::unique_ptr; ++ using unique_ptr = std::unique_ptr; + + // On failure, the alloc_etc functions return nullptr. They don't throw. + + static inline unique_ptr + alloc() { +- return unique_ptr(wuffs_xxhash64__hasher__alloc()); +- } +- +- static inline wuffs_base__hasher_u64::unique_ptr +- alloc_as__wuffs_base__hasher_u64() { +- return wuffs_base__hasher_u64::unique_ptr( +- wuffs_xxhash64__hasher__alloc_as__wuffs_base__hasher_u64()); ++ return unique_ptr(wuffs_vp8__placeholder__alloc()); + } + #endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +@@ -12821,10 +13820,10 @@ struct wuffs_xxhash64__hasher__struct { + // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in + // order to provide convenience methods. These forward on "this", so that you + // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". +- wuffs_xxhash64__hasher__struct() = delete; +- wuffs_xxhash64__hasher__struct(const wuffs_xxhash64__hasher__struct&) = delete; +- wuffs_xxhash64__hasher__struct& operator=( +- const wuffs_xxhash64__hasher__struct&) = delete; ++ wuffs_vp8__placeholder__struct() = delete; ++ wuffs_vp8__placeholder__struct(const wuffs_vp8__placeholder__struct&) = delete; ++ wuffs_vp8__placeholder__struct& operator=( ++ const wuffs_vp8__placeholder__struct&) = delete; + #endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + + #if !defined(WUFFS_IMPLEMENTATION) +@@ -12844,9372 +13843,9377 @@ struct wuffs_xxhash64__hasher__struct { + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options) { +- return wuffs_xxhash64__hasher__initialize( ++ return wuffs_vp8__placeholder__initialize( + this, sizeof_star_self, wuffs_version, options); + } + +- inline wuffs_base__hasher_u64* +- upcast_as__wuffs_base__hasher_u64() { +- return (wuffs_base__hasher_u64*)this; +- } ++#endif // __cplusplus ++}; // struct wuffs_vp8__placeholder__struct + +- inline uint64_t +- get_quirk( +- uint32_t a_key) const { +- return wuffs_xxhash64__hasher__get_quirk(this, a_key); +- } ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +- inline wuffs_base__status +- set_quirk( +- uint32_t a_key, +- uint64_t a_value) { +- return wuffs_xxhash64__hasher__set_quirk(this, a_key, a_value); +- } ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__VP8) || defined(WUFFS_NONMONOLITHIC) + +- inline wuffs_base__empty_struct +- update( +- wuffs_base__slice_u8 a_x) { +- return wuffs_xxhash64__hasher__update(this, a_x); +- } ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) || defined(WUFFS_NONMONOLITHIC) + +- inline uint64_t +- update_u64( +- wuffs_base__slice_u8 a_x) { +- return wuffs_xxhash64__hasher__update_u64(this, a_x); +- } ++// ---------------- Status Codes + +- inline uint64_t +- checksum_u64() const { +- return wuffs_xxhash64__hasher__checksum_u64(this); +- } ++extern const char wuffs_wbmp__error__bad_header[]; ++extern const char wuffs_wbmp__error__truncated_input[]; + +-#endif // __cplusplus +-}; // struct wuffs_xxhash64__hasher__struct ++// ---------------- Public Consts + +-#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++#define WUFFS_WBMP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH64) || defined(WUFFS_NONMONOLITHIC) ++// ---------------- Struct Declarations + +-#if defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++typedef struct wuffs_wbmp__decoder__struct wuffs_wbmp__decoder; + +-// ---------------- Auxiliary - Base ++#ifdef __cplusplus ++extern "C" { ++#endif + +-// Auxiliary code is discussed at +-// https://github.com/google/wuffs/blob/main/doc/note/auxiliary-code.md ++// ---------------- Public Initializer Prototypes + +-#include ++// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self, ++// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)". ++// ++// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version. ++// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + +-#include ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_wbmp__decoder__initialize( ++ wuffs_wbmp__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options); + +-namespace wuffs_aux { ++size_t ++sizeof__wuffs_wbmp__decoder(void); + +-using IOBuffer = wuffs_base__io_buffer; ++// ---------------- Allocs + +-// MemOwner represents ownership of some memory. Dynamically allocated memory +-// (e.g. from malloc or new) is typically paired with free or delete, invoked +-// when the std::unique_ptr is destroyed. Statically allocated memory might use +-// MemOwner(nullptr, &free), even if that statically allocated memory is not +-// nullptr, since calling free(nullptr) is a no-op. +-using MemOwner = std::unique_ptr; ++// These functions allocate and initialize Wuffs structs. They return NULL if ++// memory allocation fails. If they return non-NULL, there is no need to call ++// wuffs_foo__bar__initialize, but the caller is responsible for eventually ++// calling free on the returned pointer. That pointer is effectively a C++ ++// std::unique_ptr. + +-namespace sync_io { ++wuffs_wbmp__decoder* ++wuffs_wbmp__decoder__alloc(void); + +-// -------- ++static inline wuffs_base__image_decoder* ++wuffs_wbmp__decoder__alloc_as__wuffs_base__image_decoder(void) { ++ return (wuffs_base__image_decoder*)(wuffs_wbmp__decoder__alloc()); ++} + +-// DynIOBuffer is an IOBuffer that is backed by a dynamically sized byte array. +-// It owns that backing array and will free it in its destructor. +-// +-// The array size can be explicitly extended (by calling the grow method) but, +-// unlike a C++ std::vector, there is no implicit extension (e.g. by calling +-// std::vector::insert) and its maximum size is capped by the max_incl +-// constructor argument. +-// +-// It contains an IOBuffer-typed field whose reader side provides access to +-// previously written bytes and whose writer side provides access to the +-// allocated but not-yet-written-to slack space. For Go programmers, this slack +-// space is roughly analogous to the s[len(s):cap(s)] space of a slice s. +-class DynIOBuffer { +- public: +- enum GrowResult { +- OK = 0, +- FailedMaxInclExceeded = 1, +- FailedOutOfMemory = 2, +- }; ++// ---------------- Upcasts + +- // m_buf holds the dynamically sized byte array and its read/write indexes: +- // - m_buf.meta.wi is roughly analogous to a Go slice's length. +- // - m_buf.data.len is roughly analogous to a Go slice's capacity. It is +- // also equal to the m_buf.data.ptr malloc/realloc size. +- // +- // Users should not modify the m_buf.data.ptr or m_buf.data.len fields (as +- // they are conceptually private to this class), but they can modify the +- // bytes referenced by that pointer-length pair (e.g. compactions). +- IOBuffer m_buf; ++static inline wuffs_base__image_decoder* ++wuffs_wbmp__decoder__upcast_as__wuffs_base__image_decoder( ++ wuffs_wbmp__decoder* p) { ++ return (wuffs_base__image_decoder*)p; ++} + +- // m_max_incl is an inclusive upper bound on the backing array size. +- const uint64_t m_max_incl; ++// ---------------- Public Function Prototypes + +- // Constructor and destructor. +- explicit DynIOBuffer(uint64_t max_incl); +- ~DynIOBuffer(); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_wbmp__decoder__get_quirk( ++ const wuffs_wbmp__decoder* self, ++ uint32_t a_key); + +- // Drop frees the byte array and resets m_buf. The DynIOBuffer can still be +- // used after a drop call. It just restarts from zero. +- void drop(); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__set_quirk( ++ wuffs_wbmp__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value); + +- // grow ensures that the byte array size is at least min_incl and at most +- // max_incl. It returns FailedMaxInclExceeded if that would require +- // allocating more than max_incl bytes, including the case where (min_incl > +- // max_incl). It returns FailedOutOfMemory if memory allocation failed. +- GrowResult grow(uint64_t min_incl); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__decode_image_config( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- private: +- // Delete the copy and assign constructors. +- DynIOBuffer(const DynIOBuffer&) = delete; +- DynIOBuffer& operator=(const DynIOBuffer&) = delete; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__decode_frame_config( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- static uint64_t round_up(uint64_t min_incl, uint64_t max_incl); +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__decode_frame( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); + +-// -------- ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_wbmp__decoder__frame_dirty_rect( ++ const wuffs_wbmp__decoder* self); + +-class Input { +- public: +- virtual ~Input(); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_wbmp__decoder__num_animation_loops( ++ const wuffs_wbmp__decoder* self); + +- virtual IOBuffer* BringsItsOwnIOBuffer(); +- virtual std::string CopyIn(IOBuffer* dst, uint64_t history_retain_length) = 0; +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_wbmp__decoder__num_decoded_frame_configs( ++ const wuffs_wbmp__decoder* self); + +-// -------- ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_wbmp__decoder__num_decoded_frames( ++ const wuffs_wbmp__decoder* self); + +-// FileInput is an Input that reads from a file source. +-// +-// It does not take responsibility for closing the file when done. +-class FileInput : public Input { +- public: +- FileInput(FILE* f); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__restart_frame( ++ wuffs_wbmp__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position); + +- virtual std::string CopyIn(IOBuffer* dst, uint64_t history_retain_length); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_wbmp__decoder__set_report_metadata( ++ wuffs_wbmp__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report); + +- private: +- FILE* m_f; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__tell_me_more( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src); + +- // Delete the copy and assign constructors. +- FileInput(const FileInput&) = delete; +- FileInput& operator=(const FileInput&) = delete; +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_wbmp__decoder__workbuf_len( ++ const wuffs_wbmp__decoder* self); + +-// -------- ++#ifdef __cplusplus ++} // extern "C" ++#endif + +-// MemoryInput is an Input that reads from an in-memory source. ++// ---------------- Struct Definitions ++ ++// These structs' fields, and the sizeof them, are private implementation ++// details that aren't guaranteed to be stable across Wuffs versions. + // +-// It does not take responsibility for freeing the memory when done. +-class MemoryInput : public Input { +- public: +- MemoryInput(const char* ptr, size_t len); +- MemoryInput(const uint8_t* ptr, size_t len); ++// See https://en.wikipedia.org/wiki/Opaque_pointer#C + +- virtual IOBuffer* BringsItsOwnIOBuffer(); +- virtual std::string CopyIn(IOBuffer* dst, uint64_t history_retain_length); ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +- private: +- IOBuffer m_io; ++struct wuffs_wbmp__decoder__struct { ++ // Do not access the private_impl's or private_data's fields directly. There ++ // is no API/ABI compatibility or safety guarantee if you do so. Instead, use ++ // the wuffs_foo__bar__baz functions. ++ // ++ // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct ++ // can be stack allocated when WUFFS_IMPLEMENTATION is defined. + +- // Delete the copy and assign constructors. +- MemoryInput(const MemoryInput&) = delete; +- MemoryInput& operator=(const MemoryInput&) = delete; +-}; ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable vtable_for__wuffs_base__image_decoder; ++ wuffs_base__vtable null_vtable; + +-// -------- ++ uint32_t f_width; ++ uint32_t f_height; ++ uint8_t f_call_sequence; ++ uint64_t f_frame_config_io_position; ++ wuffs_base__pixel_swizzler f_swizzler; + +-} // namespace sync_io ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; ++ } private_impl; + +-} // namespace wuffs_aux ++ struct { ++ struct { ++ uint32_t v_i; ++ uint32_t v_p; ++ } s_do_decode_image_config; ++ struct { ++ uint64_t v_dst_bytes_per_pixel; ++ uint32_t v_dst_x; ++ uint32_t v_dst_y; ++ uint8_t v_src[1]; ++ uint8_t v_c8; ++ } s_do_decode_frame; ++ } private_data; + +-// ---------------- Auxiliary - CBOR ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; + +-namespace wuffs_aux { ++ // On failure, the alloc_etc functions return nullptr. They don't throw. + +-struct DecodeCborResult { +- DecodeCborResult(std::string&& error_message0, uint64_t cursor_position0); ++ static inline unique_ptr ++ alloc() { ++ return unique_ptr(wuffs_wbmp__decoder__alloc()); ++ } + +- std::string error_message; +- uint64_t cursor_position; +-}; ++ static inline wuffs_base__image_decoder::unique_ptr ++ alloc_as__wuffs_base__image_decoder() { ++ return wuffs_base__image_decoder::unique_ptr( ++ wuffs_wbmp__decoder__alloc_as__wuffs_base__image_decoder()); ++ } ++#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +-class DecodeCborCallbacks { +- public: +- virtual ~DecodeCborCallbacks(); ++#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ // Disallow constructing or copying an object via standard C++ mechanisms, ++ // e.g. the "new" operator, as this struct is intentionally opaque. Its total ++ // size and field layout is not part of the public, stable, memory-safe API. ++ // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and ++ // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as ++ // their first argument) rather than tweaking bar.private_impl.qux fields. ++ // ++ // In C, we can just leave wuffs_foo__bar as an incomplete type (unless ++ // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in ++ // order to provide convenience methods. These forward on "this", so that you ++ // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". ++ wuffs_wbmp__decoder__struct() = delete; ++ wuffs_wbmp__decoder__struct(const wuffs_wbmp__decoder__struct&) = delete; ++ wuffs_wbmp__decoder__struct& operator=( ++ const wuffs_wbmp__decoder__struct&) = delete; ++#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + +- // AppendXxx are called for leaf nodes: literals, numbers, strings, etc. ++#if !defined(WUFFS_IMPLEMENTATION) ++ // As above, the size of the struct is not part of the public API, and unless ++ // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap ++ // allocated, not stack allocated. Its size is not intended to be known at ++ // compile time, but it is unfortunately divulged as a side effect of ++ // defining C++ convenience methods. Use "sizeof__T()", calling the function, ++ // instead of "sizeof T", invoking the operator. To make the two values ++ // different, so that passing the latter will be rejected by the initialize ++ // function, we add an arbitrary amount of dead weight. ++ uint8_t dead_weight[123000000]; // 123 MB. ++#endif // !defined(WUFFS_IMPLEMENTATION) + +- virtual std::string AppendNull() = 0; +- virtual std::string AppendUndefined() = 0; +- virtual std::string AppendBool(bool val) = 0; +- virtual std::string AppendF64(double val) = 0; +- virtual std::string AppendI64(int64_t val) = 0; +- virtual std::string AppendU64(uint64_t val) = 0; +- virtual std::string AppendByteString(std::string&& val) = 0; +- virtual std::string AppendTextString(std::string&& val) = 0; +- virtual std::string AppendMinus1MinusX(uint64_t val) = 0; +- virtual std::string AppendCborSimpleValue(uint8_t val) = 0; +- virtual std::string AppendCborTag(uint64_t val) = 0; ++ inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++ initialize( ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options) { ++ return wuffs_wbmp__decoder__initialize( ++ this, sizeof_star_self, wuffs_version, options); ++ } + +- // Push and Pop are called for container nodes: CBOR arrays (lists) and CBOR +- // maps (dictionaries). +- // +- // The flags bits combine exactly one of: +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT +- // and exactly one of: +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT ++ inline wuffs_base__image_decoder* ++ upcast_as__wuffs_base__image_decoder() { ++ return (wuffs_base__image_decoder*)this; ++ } + +- virtual std::string Push(uint32_t flags) = 0; +- virtual std::string Pop(uint32_t flags) = 0; ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_wbmp__decoder__get_quirk(this, a_key); ++ } + +- // Done is always the last Callback method called by DecodeCbor, whether or +- // not parsing the input as CBOR encountered an error. Even when successful, +- // trailing data may remain in input and buffer. +- // +- // Do not keep a reference to buffer or buffer.data.ptr after Done returns, +- // as DecodeCbor may then de-allocate the backing array. +- // +- // The default Done implementation is a no-op. +- virtual void // +- Done(DecodeCborResult& result, sync_io::Input& input, IOBuffer& buffer); +-}; ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_wbmp__decoder__set_quirk(this, a_key, a_value); ++ } + +-// The FooArgBar types add structure to Foo's optional arguments. They wrap +-// inner representations for several reasons: +-// - It provides a home for the DefaultValue static method, for Foo callers +-// that want to override some but not all optional arguments. +-// - It provides the "Bar" name at Foo call sites, which can help self- +-// document Foo calls with many arguemnts. +-// - It provides some type safety against accidentally transposing or omitting +-// adjacent fundamentally-numeric-typed optional arguments. ++ inline wuffs_base__status ++ decode_image_config( ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_wbmp__decoder__decode_image_config(this, a_dst, a_src); ++ } + +-// DecodeCborArgQuirks wraps an optional argument to DecodeCbor. +-struct DecodeCborArgQuirks { +- explicit DecodeCborArgQuirks(wuffs_base__slice_u32 repr0); +- explicit DecodeCborArgQuirks(uint32_t* ptr, size_t len); ++ inline wuffs_base__status ++ decode_frame_config( ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_wbmp__decoder__decode_frame_config(this, a_dst, a_src); ++ } + +- // DefaultValue returns an empty slice. +- static DecodeCborArgQuirks DefaultValue(); ++ inline wuffs_base__status ++ decode_frame( ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ return wuffs_wbmp__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); ++ } + +- wuffs_base__slice_u32 repr; +-}; ++ inline wuffs_base__rect_ie_u32 ++ frame_dirty_rect() const { ++ return wuffs_wbmp__decoder__frame_dirty_rect(this); ++ } + +-// DecodeCbor calls callbacks based on the CBOR-formatted data in input. +-// +-// On success, the returned error_message is empty and cursor_position counts +-// the number of bytes consumed. On failure, error_message is non-empty and +-// cursor_position is the location of the error. That error may be a content +-// error (invalid CBOR) or an input error (e.g. network failure). +-DecodeCborResult // +-DecodeCbor(DecodeCborCallbacks& callbacks, +- sync_io::Input& input, +- DecodeCborArgQuirks quirks = DecodeCborArgQuirks::DefaultValue()); ++ inline uint32_t ++ num_animation_loops() const { ++ return wuffs_wbmp__decoder__num_animation_loops(this); ++ } + +-} // namespace wuffs_aux ++ inline uint64_t ++ num_decoded_frame_configs() const { ++ return wuffs_wbmp__decoder__num_decoded_frame_configs(this); ++ } + +-// ---------------- Auxiliary - Image ++ inline uint64_t ++ num_decoded_frames() const { ++ return wuffs_wbmp__decoder__num_decoded_frames(this); ++ } + +-namespace wuffs_aux { ++ inline wuffs_base__status ++ restart_frame( ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ return wuffs_wbmp__decoder__restart_frame(this, a_index, a_io_position); ++ } + +-struct DecodeImageResult { +- DecodeImageResult(MemOwner&& pixbuf_mem_owner0, +- wuffs_base__pixel_buffer pixbuf0, +- std::string&& error_message0); +- DecodeImageResult(std::string&& error_message0); ++ inline wuffs_base__empty_struct ++ set_report_metadata( ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_wbmp__decoder__set_report_metadata(this, a_fourcc, a_report); ++ } + +- MemOwner pixbuf_mem_owner; +- wuffs_base__pixel_buffer pixbuf; +- std::string error_message; +-}; ++ inline wuffs_base__status ++ tell_me_more( ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_wbmp__decoder__tell_me_more(this, a_dst, a_minfo, a_src); ++ } + +-// DecodeImageCallbacks are the callbacks given to DecodeImage. They are always +-// called in this order: +-// 1. SelectDecoder +-// 2. HandleMetadata +-// 3. SelectPixfmt +-// 4. AllocPixbuf +-// 5. AllocWorkbuf +-// 6. Done +-// +-// It may return early - the third callback might not be invoked if the second +-// one fails - but the final callback (Done) is always invoked. +-class DecodeImageCallbacks { +- public: +- // AllocPixbufResult holds a memory allocation (the result of malloc or new, +- // a statically allocated pointer, etc), or an error message. The memory is +- // de-allocated when mem_owner goes out of scope and is destroyed. +- struct AllocPixbufResult { +- AllocPixbufResult(MemOwner&& mem_owner0, wuffs_base__pixel_buffer pixbuf0); +- AllocPixbufResult(std::string&& error_message0); ++ inline wuffs_base__range_ii_u64 ++ workbuf_len() const { ++ return wuffs_wbmp__decoder__workbuf_len(this); ++ } + +- MemOwner mem_owner; +- wuffs_base__pixel_buffer pixbuf; +- std::string error_message; +- }; ++#endif // __cplusplus ++}; // struct wuffs_wbmp__decoder__struct + +- // AllocWorkbufResult holds a memory allocation (the result of malloc or new, +- // a statically allocated pointer, etc), or an error message. The memory is +- // de-allocated when mem_owner goes out of scope and is destroyed. +- struct AllocWorkbufResult { +- AllocWorkbufResult(MemOwner&& mem_owner0, wuffs_base__slice_u8 workbuf0); +- AllocWorkbufResult(std::string&& error_message0); ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +- MemOwner mem_owner; +- wuffs_base__slice_u8 workbuf; +- std::string error_message; +- }; ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) || defined(WUFFS_NONMONOLITHIC) + +- virtual ~DecodeImageCallbacks(); ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WEBP) || defined(WUFFS_NONMONOLITHIC) + +- // SelectDecoder returns the image decoder for the input data's file format. +- // Returning a nullptr means failure (DecodeImage_UnsupportedImageFormat). +- // +- // Common formats will have a FourCC value in the range [1 ..= 0x7FFF_FFFF], +- // such as WUFFS_BASE__FOURCC__JPEG. A zero FourCC value means that Wuffs' +- // standard library did not recognize the image format but if SelectDecoder +- // was overridden, it may examine the input data's starting bytes and still +- // provide its own image decoder, e.g. for an exotic image file format that's +- // not in Wuffs' standard library. The prefix_etc fields have the same +- // meaning as wuffs_base__magic_number_guess_fourcc arguments. SelectDecoder +- // implementations should not modify prefix_data's contents. +- // +- // SelectDecoder might be called more than once, since some image file +- // formats can wrap others. For example, a nominal BMP file can actually +- // contain a JPEG or a PNG. +- // +- // The default SelectDecoder accepts the FOURCC codes listed below. For +- // modular builds (i.e. when #define'ing WUFFS_CONFIG__MODULES), acceptance +- // of the ETC file format is optional (for each value of ETC) and depends on +- // the corresponding module to be enabled at compile time (i.e. #define'ing +- // WUFFS_CONFIG__MODULE__ETC). +- // - WUFFS_BASE__FOURCC__BMP +- // - WUFFS_BASE__FOURCC__GIF +- // - WUFFS_BASE__FOURCC__JPEG +- // - WUFFS_BASE__FOURCC__NIE +- // - WUFFS_BASE__FOURCC__NPBM +- // - WUFFS_BASE__FOURCC__PNG +- // - WUFFS_BASE__FOURCC__TGA +- // - WUFFS_BASE__FOURCC__WBMP +- virtual wuffs_base__image_decoder::unique_ptr // +- SelectDecoder(uint32_t fourcc, +- wuffs_base__slice_u8 prefix_data, +- bool prefix_closed); +- +- // HandleMetadata acknowledges image metadata. minfo.flavor will be one of: +- // - WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH +- // - WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED +- // If it is ETC__METADATA_RAW_ETC then raw contains the metadata bytes. Those +- // bytes should not be retained beyond the the HandleMetadata call. +- // +- // minfo.metadata__fourcc() will typically match one of the +- // DecodeImageArgFlags bits. For example, if (REPORT_METADATA_CHRM | +- // REPORT_METADATA_GAMA) was passed to DecodeImage then the metadata FourCC +- // will be either WUFFS_BASE__FOURCC__CHRM or WUFFS_BASE__FOURCC__GAMA. +- // +- // It returns an error message, or an empty string on success. +- virtual std::string // +- HandleMetadata(const wuffs_base__more_information& minfo, +- wuffs_base__slice_u8 raw); +- +- // SelectPixfmt returns the destination pixel format for AllocPixbuf. It +- // should return wuffs_base__make_pixel_format(etc) called with one of: +- // - WUFFS_BASE__PIXEL_FORMAT__BGR_565 +- // - WUFFS_BASE__PIXEL_FORMAT__BGR +- // - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL +- // - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE +- // - WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL +- // - WUFFS_BASE__PIXEL_FORMAT__RGB +- // - WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL +- // - WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL +- // or return image_config.pixcfg.pixel_format(). The latter means to use the +- // image file's natural pixel format. For example, GIF images' natural pixel +- // format is an indexed one. +- // +- // Returning otherwise means failure (DecodeImage_UnsupportedPixelFormat). +- // +- // The default SelectPixfmt implementation returns +- // wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL) which +- // is 4 bytes per pixel (8 bits per channel × 4 channels). +- virtual wuffs_base__pixel_format // +- SelectPixfmt(const wuffs_base__image_config& image_config); ++// ---------------- Status Codes + +- // AllocPixbuf allocates the pixel buffer. +- // +- // allow_uninitialized_memory will be true if a valid background_color was +- // passed to DecodeImage, since the pixel buffer's contents will be +- // overwritten with that color after AllocPixbuf returns. +- // +- // The default AllocPixbuf implementation allocates either uninitialized or +- // zeroed memory. Zeroed memory typically corresponds to filling with opaque +- // black or transparent black, depending on the pixel format. +- virtual AllocPixbufResult // +- AllocPixbuf(const wuffs_base__image_config& image_config, +- bool allow_uninitialized_memory); ++extern const char wuffs_webp__error__bad_huffman_code_over_subscribed[]; ++extern const char wuffs_webp__error__bad_huffman_code_under_subscribed[]; ++extern const char wuffs_webp__error__bad_huffman_code[]; ++extern const char wuffs_webp__error__bad_back_reference[]; ++extern const char wuffs_webp__error__bad_color_cache[]; ++extern const char wuffs_webp__error__bad_header[]; ++extern const char wuffs_webp__error__bad_transform[]; ++extern const char wuffs_webp__error__short_chunk[]; ++extern const char wuffs_webp__error__truncated_input[]; ++extern const char wuffs_webp__error__unsupported_number_of_huffman_groups[]; ++extern const char wuffs_webp__error__unsupported_transform_after_color_indexing_transform[]; ++extern const char wuffs_webp__error__unsupported_webp_file[]; + +- // AllocWorkbuf allocates the work buffer. The allocated buffer's length +- // should be at least len_range.min_incl, but larger allocations (up to +- // len_range.max_incl) may have better performance (by using more memory). +- // +- // The default AllocWorkbuf implementation allocates len_range.max_incl bytes +- // of either uninitialized or zeroed memory. +- virtual AllocWorkbufResult // +- AllocWorkbuf(wuffs_base__range_ii_u64 len_range, +- bool allow_uninitialized_memory); ++// ---------------- Public Consts + +- // Done is always the last Callback method called by DecodeImage, whether or +- // not parsing the input encountered an error. Even when successful, trailing +- // data may remain in input and buffer. +- // +- // The image_decoder is the one returned by SelectDecoder (if SelectDecoder +- // was successful), or a no-op unique_ptr otherwise. Like any unique_ptr, +- // ownership moves to the Done implementation. +- // +- // Do not keep a reference to buffer or buffer.data.ptr after Done returns, +- // as DecodeImage may then de-allocate the backing array. +- // +- // The default Done implementation is a no-op, other than running the +- // image_decoder unique_ptr destructor. +- virtual void // +- Done(DecodeImageResult& result, +- sync_io::Input& input, +- IOBuffer& buffer, +- wuffs_base__image_decoder::unique_ptr image_decoder); +-}; ++#define WUFFS_WEBP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0u + +-extern const char DecodeImage_BufferIsTooShort[]; +-extern const char DecodeImage_MaxInclDimensionExceeded[]; +-extern const char DecodeImage_MaxInclMetadataLengthExceeded[]; +-extern const char DecodeImage_OutOfMemory[]; +-extern const char DecodeImage_UnexpectedEndOfFile[]; +-extern const char DecodeImage_UnsupportedImageFormat[]; +-extern const char DecodeImage_UnsupportedMetadata[]; +-extern const char DecodeImage_UnsupportedPixelBlend[]; +-extern const char DecodeImage_UnsupportedPixelConfiguration[]; +-extern const char DecodeImage_UnsupportedPixelFormat[]; ++// ---------------- Struct Declarations + +-// The FooArgBar types add structure to Foo's optional arguments. They wrap +-// inner representations for several reasons: +-// - It provides a home for the DefaultValue static method, for Foo callers +-// that want to override some but not all optional arguments. +-// - It provides the "Bar" name at Foo call sites, which can help self- +-// document Foo calls with many arguemnts. +-// - It provides some type safety against accidentally transposing or omitting +-// adjacent fundamentally-numeric-typed optional arguments. ++typedef struct wuffs_webp__decoder__struct wuffs_webp__decoder; + +-// DecodeImageArgQuirks wraps an optional argument to DecodeImage. +-struct DecodeImageArgQuirks { +- explicit DecodeImageArgQuirks(wuffs_base__slice_u32 repr0); +- explicit DecodeImageArgQuirks(uint32_t* ptr, size_t len); ++#ifdef __cplusplus ++extern "C" { ++#endif + +- // DefaultValue returns an empty slice. +- static DecodeImageArgQuirks DefaultValue(); ++// ---------------- Public Initializer Prototypes + +- wuffs_base__slice_u32 repr; +-}; ++// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self, ++// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)". ++// ++// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version. ++// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + +-// DecodeImageArgFlags wraps an optional argument to DecodeImage. +-struct DecodeImageArgFlags { +- explicit DecodeImageArgFlags(uint64_t repr0); ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_webp__decoder__initialize( ++ wuffs_webp__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options); + +- // DefaultValue returns 0. +- static DecodeImageArgFlags DefaultValue(); ++size_t ++sizeof__wuffs_webp__decoder(void); + +- // TODO: support all of the REPORT_METADATA_ETC flags, not just CHRM, EXIF, +- // GAMA, ICCP, KVP, SRGB and XMP. ++// ---------------- Allocs + +- // Background Color. +- static constexpr uint64_t REPORT_METADATA_BGCL = 0x0001; +- // Primary Chromaticities and White Point. +- static constexpr uint64_t REPORT_METADATA_CHRM = 0x0002; +- // Exchangeable Image File Format. +- static constexpr uint64_t REPORT_METADATA_EXIF = 0x0004; +- // Gamma Correction. +- static constexpr uint64_t REPORT_METADATA_GAMA = 0x0008; +- // International Color Consortium Profile. +- static constexpr uint64_t REPORT_METADATA_ICCP = 0x0010; +- // Key-Value Pair. +- // +- // For PNG files, this includes iTXt, tEXt and zTXt chunks. In the +- // HandleMetadata callback, the raw argument contains UTF-8 strings. +- static constexpr uint64_t REPORT_METADATA_KVP = 0x0020; +- // Modification Time. +- static constexpr uint64_t REPORT_METADATA_MTIM = 0x0040; +- // Offset (2-Dimensional). +- static constexpr uint64_t REPORT_METADATA_OFS2 = 0x0080; +- // Physical Dimensions. +- static constexpr uint64_t REPORT_METADATA_PHYD = 0x0100; +- // Standard Red Green Blue (Rendering Intent). +- static constexpr uint64_t REPORT_METADATA_SRGB = 0x0200; +- // Extensible Metadata Platform. +- static constexpr uint64_t REPORT_METADATA_XMP = 0x0400; ++// These functions allocate and initialize Wuffs structs. They return NULL if ++// memory allocation fails. If they return non-NULL, there is no need to call ++// wuffs_foo__bar__initialize, but the caller is responsible for eventually ++// calling free on the returned pointer. That pointer is effectively a C++ ++// std::unique_ptr. + +- uint64_t repr; +-}; ++wuffs_webp__decoder* ++wuffs_webp__decoder__alloc(void); + +-// DecodeImageArgPixelBlend wraps an optional argument to DecodeImage. +-struct DecodeImageArgPixelBlend { +- explicit DecodeImageArgPixelBlend(wuffs_base__pixel_blend repr0); ++static inline wuffs_base__image_decoder* ++wuffs_webp__decoder__alloc_as__wuffs_base__image_decoder(void) { ++ return (wuffs_base__image_decoder*)(wuffs_webp__decoder__alloc()); ++} + +- // DefaultValue returns WUFFS_BASE__PIXEL_BLEND__SRC. +- static DecodeImageArgPixelBlend DefaultValue(); ++// ---------------- Upcasts + +- wuffs_base__pixel_blend repr; +-}; ++static inline wuffs_base__image_decoder* ++wuffs_webp__decoder__upcast_as__wuffs_base__image_decoder( ++ wuffs_webp__decoder* p) { ++ return (wuffs_base__image_decoder*)p; ++} + +-// DecodeImageArgBackgroundColor wraps an optional argument to DecodeImage. +-struct DecodeImageArgBackgroundColor { +- explicit DecodeImageArgBackgroundColor( +- wuffs_base__color_u32_argb_premul repr0); ++// ---------------- Public Function Prototypes + +- // DefaultValue returns 1, an invalid wuffs_base__color_u32_argb_premul. +- static DecodeImageArgBackgroundColor DefaultValue(); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_webp__decoder__get_quirk( ++ const wuffs_webp__decoder* self, ++ uint32_t a_key); + +- wuffs_base__color_u32_argb_premul repr; +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_webp__decoder__set_quirk( ++ wuffs_webp__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value); + +-// DecodeImageArgMaxInclDimension wraps an optional argument to DecodeImage. +-struct DecodeImageArgMaxInclDimension { +- explicit DecodeImageArgMaxInclDimension(uint32_t repr0); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_webp__decoder__decode_image_config( ++ wuffs_webp__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- // DefaultValue returns 1048575 = 0x000F_FFFF, more than 1 million pixels. +- static DecodeImageArgMaxInclDimension DefaultValue(); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_webp__decoder__decode_frame_config( ++ wuffs_webp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- uint32_t repr; +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_webp__decoder__decode_frame( ++ wuffs_webp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); + +-// DecodeImageArgMaxInclMetadataLength wraps an optional argument to +-// DecodeImage. +-struct DecodeImageArgMaxInclMetadataLength { +- explicit DecodeImageArgMaxInclMetadataLength(uint64_t repr0); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_webp__decoder__frame_dirty_rect( ++ const wuffs_webp__decoder* self); + +- // DefaultValue returns 16777215 = 0x00FF_FFFF, one less than 16 MiB. +- static DecodeImageArgMaxInclMetadataLength DefaultValue(); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_webp__decoder__num_animation_loops( ++ const wuffs_webp__decoder* self); + +- uint64_t repr; +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_webp__decoder__num_decoded_frame_configs( ++ const wuffs_webp__decoder* self); + +-// DecodeImage decodes the image data in input. A variety of image file formats +-// can be decoded, depending on what callbacks.SelectDecoder returns. +-// +-// For animated formats, only the first frame is returned, since the API is +-// simpler for synchronous I/O and having DecodeImage only return when +-// completely done, but rendering animation often involves handling other +-// events in between animation frames. To decode multiple frames of animated +-// images, or for asynchronous I/O (e.g. when decoding an image streamed over +-// the network), use Wuffs' lower level C API instead of its higher level, +-// simplified C++ API (the wuffs_aux API). +-// +-// The DecodeImageResult's fields depend on whether decoding succeeded: +-// - On total success, the error_message is empty and pixbuf.pixcfg.is_valid() +-// is true. +-// - On partial success (e.g. the input file was truncated but we are still +-// able to decode some of the pixels), error_message is non-empty but +-// pixbuf.pixcfg.is_valid() is still true. It is up to the caller whether to +-// accept or reject partial success. +-// - On failure, the error_message is non_empty and pixbuf.pixcfg.is_valid() +-// is false. +-// +-// The callbacks allocate the pixel buffer memory and work buffer memory. On +-// success, pixel buffer memory ownership is passed to the DecodeImage caller +-// as the returned pixbuf_mem_owner. Regardless of success or failure, the work +-// buffer memory is deleted. +-// +-// The pixel_blend (one of the constants listed below) determines how to +-// composite the decoded image over the pixel buffer's original pixels (as +-// returned by callbacks.AllocPixbuf): +-// - WUFFS_BASE__PIXEL_BLEND__SRC +-// - WUFFS_BASE__PIXEL_BLEND__SRC_OVER +-// +-// The background_color is used to fill the pixel buffer after +-// callbacks.AllocPixbuf returns, if it is valid in the +-// wuffs_base__color_u32_argb_premul__is_valid sense. The default value, +-// 0x0000_0001, is not valid since its Blue channel value (0x01) is greater +-// than its Alpha channel value (0x00). A valid background_color will typically +-// be overwritten when pixel_blend is WUFFS_BASE__PIXEL_BLEND__SRC, but might +-// still be visible on partial (not total) success or when pixel_blend is +-// WUFFS_BASE__PIXEL_BLEND__SRC_OVER and the decoded image is not fully opaque. +-// +-// Decoding fails (with DecodeImage_MaxInclDimensionExceeded) if the image's +-// width or height is greater than max_incl_dimension or if any opted-in (via +-// flags bits) metadata is longer than max_incl_metadata_length. +-DecodeImageResult // +-DecodeImage(DecodeImageCallbacks& callbacks, +- sync_io::Input& input, +- DecodeImageArgQuirks quirks = DecodeImageArgQuirks::DefaultValue(), +- DecodeImageArgFlags flags = DecodeImageArgFlags::DefaultValue(), +- DecodeImageArgPixelBlend pixel_blend = +- DecodeImageArgPixelBlend::DefaultValue(), +- DecodeImageArgBackgroundColor background_color = +- DecodeImageArgBackgroundColor::DefaultValue(), +- DecodeImageArgMaxInclDimension max_incl_dimension = +- DecodeImageArgMaxInclDimension::DefaultValue(), +- DecodeImageArgMaxInclMetadataLength max_incl_metadata_length = +- DecodeImageArgMaxInclMetadataLength::DefaultValue()); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_webp__decoder__num_decoded_frames( ++ const wuffs_webp__decoder* self); + +-} // namespace wuffs_aux ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_webp__decoder__restart_frame( ++ wuffs_webp__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position); + +-// ---------------- Auxiliary - JSON ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_webp__decoder__set_report_metadata( ++ wuffs_webp__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report); + +-namespace wuffs_aux { ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_webp__decoder__tell_me_more( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src); + +-struct DecodeJsonResult { +- DecodeJsonResult(std::string&& error_message0, uint64_t cursor_position0); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_webp__decoder__workbuf_len( ++ const wuffs_webp__decoder* self); + +- std::string error_message; +- uint64_t cursor_position; +-}; ++#ifdef __cplusplus ++} // extern "C" ++#endif + +-class DecodeJsonCallbacks { +- public: +- virtual ~DecodeJsonCallbacks(); ++// ---------------- Struct Definitions + +- // AppendXxx are called for leaf nodes: literals, numbers and strings. For +- // strings, the Callbacks implementation is responsible for tracking map keys +- // versus other values. ++// These structs' fields, and the sizeof them, are private implementation ++// details that aren't guaranteed to be stable across Wuffs versions. ++// ++// See https://en.wikipedia.org/wiki/Opaque_pointer#C + +- virtual std::string AppendNull() = 0; +- virtual std::string AppendBool(bool val) = 0; +- virtual std::string AppendF64(double val) = 0; +- virtual std::string AppendI64(int64_t val) = 0; +- virtual std::string AppendTextString(std::string&& val) = 0; ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +- // Push and Pop are called for container nodes: JSON arrays (lists) and JSON +- // objects (dictionaries). ++struct wuffs_webp__decoder__struct { ++ // Do not access the private_impl's or private_data's fields directly. There ++ // is no API/ABI compatibility or safety guarantee if you do so. Instead, use ++ // the wuffs_foo__bar__baz functions. + // +- // The flags bits combine exactly one of: +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT +- // and exactly one of: +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST +- // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT ++ // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct ++ // can be stack allocated when WUFFS_IMPLEMENTATION is defined. + +- virtual std::string Push(uint32_t flags) = 0; +- virtual std::string Pop(uint32_t flags) = 0; ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable vtable_for__wuffs_base__image_decoder; ++ wuffs_base__vtable null_vtable; + +- // Done is always the last Callback method called by DecodeJson, whether or +- // not parsing the input as JSON encountered an error. Even when successful, +- // trailing data may remain in input and buffer. See "Unintuitive JSON +- // Parsing" (https://nullprogram.com/blog/2019/12/28/) which discusses JSON +- // parsing and when it stops. +- // +- // Do not keep a reference to buffer or buffer.data.ptr after Done returns, +- // as DecodeJson may then de-allocate the backing array. +- // +- // The default Done implementation is a no-op. +- virtual void // +- Done(DecodeJsonResult& result, sync_io::Input& input, IOBuffer& buffer); +-}; ++ uint32_t f_pixfmt; ++ uint32_t f_width; ++ uint32_t f_height; ++ uint8_t f_call_sequence; ++ uint8_t f_code_length_code_lengths[19]; ++ bool f_sub_chunk_has_padding; ++ uint64_t f_frame_config_io_position; ++ uint32_t f_riff_chunk_length; ++ uint32_t f_sub_chunk_length; ++ uint32_t f_bits; ++ uint32_t f_n_bits; ++ bool f_seen_transform[4]; ++ uint8_t f_transform_type[4]; ++ uint8_t f_transform_tile_size_log2[4]; ++ uint32_t f_n_transforms; ++ uint32_t f_color_cache_bits; ++ uint32_t f_overall_color_cache_bits; ++ uint32_t f_overall_tile_size_log2; ++ uint32_t f_overall_n_huffman_groups; ++ uint32_t f_ht_n_symbols; ++ uint32_t f_ht_code_lengths_remaining; ++ uint32_t f_color_indexing_palette_size; ++ uint32_t f_color_indexing_width; ++ uint32_t f_workbuf_offset_for_transform[4]; ++ uint32_t f_workbuf_offset_for_color_indexing; ++ wuffs_base__pixel_swizzler f_swizzler; + +-extern const char DecodeJson_BadJsonPointer[]; +-extern const char DecodeJson_NoMatch[]; ++ uint32_t p_decode_huffman_groups; ++ uint32_t p_decode_huffman_tree; ++ uint32_t p_decode_huffman_tree_simple; ++ uint32_t p_decode_code_length_code_lengths; ++ uint32_t p_build_code_lengths; ++ uint32_t p_decode_pixels_slow; ++ uint32_t p_decode_image_config; ++ uint32_t p_do_decode_image_config; ++ uint32_t p_do_decode_image_config_limited; ++ uint32_t p_do_decode_image_config_limited_vp8l; ++ uint32_t p_decode_frame_config; ++ uint32_t p_do_decode_frame_config; ++ uint32_t p_decode_frame; ++ uint32_t p_do_decode_frame; ++ uint32_t p_decode_transform; ++ uint32_t p_decode_color_cache_parameters; ++ uint32_t p_decode_hg_table; ++ uint32_t p_decode_pixels; ++ } private_impl; + +-// The FooArgBar types add structure to Foo's optional arguments. They wrap +-// inner representations for several reasons: +-// - It provides a home for the DefaultValue static method, for Foo callers +-// that want to override some but not all optional arguments. +-// - It provides the "Bar" name at Foo call sites, which can help self- +-// document Foo calls with many arguemnts. +-// - It provides some type safety against accidentally transposing or omitting +-// adjacent fundamentally-numeric-typed optional arguments. ++ struct { ++ uint8_t f_palette[1024]; ++ uint32_t f_color_cache[2048]; ++ uint16_t f_codes[2328]; ++ uint16_t f_code_lengths[2328]; ++ uint16_t f_code_lengths_huffman_nodes[37]; ++ uint16_t f_huffman_nodes[256][6267]; + +-// DecodeJsonArgQuirks wraps an optional argument to DecodeJson. +-struct DecodeJsonArgQuirks { +- explicit DecodeJsonArgQuirks(wuffs_base__slice_u32 repr0); +- explicit DecodeJsonArgQuirks(uint32_t* ptr, size_t len); ++ struct { ++ uint32_t v_hg; ++ uint32_t v_ht; ++ } s_decode_huffman_groups; ++ struct { ++ uint32_t v_use_second_symbol; ++ uint32_t v_first_symbol_n_bits; ++ uint32_t v_symbol0; ++ uint32_t v_base_offset; ++ } s_decode_huffman_tree_simple; ++ struct { ++ uint32_t v_n_codes; ++ uint32_t v_i; ++ } s_decode_code_length_code_lengths; ++ struct { ++ uint32_t v_length_n_bits; ++ uint16_t v_prev_code_length; ++ uint32_t v_s; ++ uint32_t v_s_max; ++ uint16_t v_node; ++ uint16_t v_repeat_value; ++ uint32_t v_repeat_n_bits; ++ } s_build_code_lengths; ++ struct { ++ uint64_t v_p; ++ uint64_t v_p_max; ++ uint32_t v_tile_size_log2; ++ uint32_t v_width_in_tiles; ++ uint32_t v_x; ++ uint32_t v_y; ++ uint32_t v_hg; ++ uint16_t v_node; ++ uint32_t v_color; ++ uint32_t v_back_ref_len_n_bits; ++ uint32_t v_back_ref_len_minus_1; ++ uint32_t v_back_ref_dist_n_bits; ++ uint32_t v_back_ref_dist_premap_minus_1; ++ uint64_t v_color_cache_p; ++ } s_decode_pixels_slow; ++ struct { ++ uint64_t scratch; ++ } s_do_decode_image_config; ++ struct { ++ uint64_t scratch; ++ } s_do_decode_image_config_limited; ++ struct { ++ uint64_t scratch; ++ } s_do_decode_image_config_limited_vp8l; ++ struct { ++ uint32_t v_width; ++ } s_do_decode_frame; ++ struct { ++ uint32_t v_transform_type; ++ uint32_t v_tile_size_log2; ++ } s_decode_transform; ++ struct { ++ uint32_t v_tile_size_log2; ++ } s_decode_hg_table; ++ } private_data; + +- // DefaultValue returns an empty slice. +- static DecodeJsonArgQuirks DefaultValue(); ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; + +- wuffs_base__slice_u32 repr; +-}; ++ // On failure, the alloc_etc functions return nullptr. They don't throw. + +-// DecodeJsonArgJsonPointer wraps an optional argument to DecodeJson. +-struct DecodeJsonArgJsonPointer { +- explicit DecodeJsonArgJsonPointer(std::string repr0); ++ static inline unique_ptr ++ alloc() { ++ return unique_ptr(wuffs_webp__decoder__alloc()); ++ } + +- // DefaultValue returns an empty string. +- static DecodeJsonArgJsonPointer DefaultValue(); ++ static inline wuffs_base__image_decoder::unique_ptr ++ alloc_as__wuffs_base__image_decoder() { ++ return wuffs_base__image_decoder::unique_ptr( ++ wuffs_webp__decoder__alloc_as__wuffs_base__image_decoder()); ++ } ++#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +- std::string repr; +-}; ++#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ // Disallow constructing or copying an object via standard C++ mechanisms, ++ // e.g. the "new" operator, as this struct is intentionally opaque. Its total ++ // size and field layout is not part of the public, stable, memory-safe API. ++ // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and ++ // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as ++ // their first argument) rather than tweaking bar.private_impl.qux fields. ++ // ++ // In C, we can just leave wuffs_foo__bar as an incomplete type (unless ++ // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in ++ // order to provide convenience methods. These forward on "this", so that you ++ // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". ++ wuffs_webp__decoder__struct() = delete; ++ wuffs_webp__decoder__struct(const wuffs_webp__decoder__struct&) = delete; ++ wuffs_webp__decoder__struct& operator=( ++ const wuffs_webp__decoder__struct&) = delete; ++#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + +-// DecodeJson calls callbacks based on the JSON-formatted data in input. +-// +-// On success, the returned error_message is empty and cursor_position counts +-// the number of bytes consumed. On failure, error_message is non-empty and +-// cursor_position is the location of the error. That error may be a content +-// error (invalid JSON) or an input error (e.g. network failure). +-// +-// json_pointer is a query in the JSON Pointer (RFC 6901) syntax. The callbacks +-// run for the input's sub-node that matches the query. DecodeJson_NoMatch is +-// returned if no matching sub-node was found. The empty query matches the +-// input's root node, consistent with JSON Pointer semantics. +-// +-// The JSON Pointer implementation is greedy: duplicate keys are not rejected +-// but only the first match for each '/'-separated fragment is followed. +-DecodeJsonResult // +-DecodeJson(DecodeJsonCallbacks& callbacks, +- sync_io::Input& input, +- DecodeJsonArgQuirks quirks = DecodeJsonArgQuirks::DefaultValue(), +- DecodeJsonArgJsonPointer json_pointer = +- DecodeJsonArgJsonPointer::DefaultValue()); ++#if !defined(WUFFS_IMPLEMENTATION) ++ // As above, the size of the struct is not part of the public API, and unless ++ // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap ++ // allocated, not stack allocated. Its size is not intended to be known at ++ // compile time, but it is unfortunately divulged as a side effect of ++ // defining C++ convenience methods. Use "sizeof__T()", calling the function, ++ // instead of "sizeof T", invoking the operator. To make the two values ++ // different, so that passing the latter will be rejected by the initialize ++ // function, we add an arbitrary amount of dead weight. ++ uint8_t dead_weight[123000000]; // 123 MB. ++#endif // !defined(WUFFS_IMPLEMENTATION) + +-} // namespace wuffs_aux ++ inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++ initialize( ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options) { ++ return wuffs_webp__decoder__initialize( ++ this, sizeof_star_self, wuffs_version, options); ++ } + +-#endif // defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ inline wuffs_base__image_decoder* ++ upcast_as__wuffs_base__image_decoder() { ++ return (wuffs_base__image_decoder*)this; ++ } + +-// ‼ WUFFS C HEADER ENDS HERE. +-#ifdef WUFFS_IMPLEMENTATION ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_webp__decoder__get_quirk(this, a_key); ++ } + +-#ifdef __cplusplus +-extern "C" { +-#endif ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_webp__decoder__set_quirk(this, a_key, a_value); ++ } + +-// ---------------- Fundamentals ++ inline wuffs_base__status ++ decode_image_config( ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_webp__decoder__decode_image_config(this, a_dst, a_src); ++ } + +-// WUFFS_BASE__MAGIC is a magic number to check that initializers are called. +-// It's not foolproof, given C doesn't automatically zero memory before use, +-// but it should catch 99.99% of cases. +-// +-// Its (non-zero) value is arbitrary, based on md5sum("wuffs"). +-#define WUFFS_BASE__MAGIC ((uint32_t)0x3CCB6C71) ++ inline wuffs_base__status ++ decode_frame_config( ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_webp__decoder__decode_frame_config(this, a_dst, a_src); ++ } + +-// WUFFS_BASE__DISABLED is a magic number to indicate that a non-recoverable +-// error was previously encountered. +-// +-// Its (non-zero) value is arbitrary, based on md5sum("disabled"). +-#define WUFFS_BASE__DISABLED ((uint32_t)0x075AE3D2) ++ inline wuffs_base__status ++ decode_frame( ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ return wuffs_webp__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts); ++ } + +-// Use switch cases for coroutine suspension points, similar to the technique +-// in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html +-// +-// The implicit fallthrough is intentional. +-// +-// We use trivial macros instead of an explicit assignment and case statement +-// so that clang-format doesn't get confused by the unusual "case"s. +-#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0 case 0:; +-#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT(n) \ +- coro_susp_point = n; \ +- case n:; ++ inline wuffs_base__rect_ie_u32 ++ frame_dirty_rect() const { ++ return wuffs_webp__decoder__frame_dirty_rect(this); ++ } + +-#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \ +- if (!status.repr) { \ +- goto ok; \ +- } else if (*status.repr != '$') { \ +- goto exit; \ +- } \ +- coro_susp_point = n; \ +- goto suspend; \ +- case n:; ++ inline uint32_t ++ num_animation_loops() const { ++ return wuffs_webp__decoder__num_animation_loops(this); ++ } + +-// The "defined(__clang__)" isn't redundant. While vanilla clang defines +-// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not. +-#if defined(__GNUC__) || defined(__clang__) +-#define WUFFS_BASE__LIKELY(expr) (__builtin_expect(!!(expr), 1)) +-#define WUFFS_BASE__UNLIKELY(expr) (__builtin_expect(!!(expr), 0)) +-#else +-#define WUFFS_BASE__LIKELY(expr) (expr) +-#define WUFFS_BASE__UNLIKELY(expr) (expr) +-#endif ++ inline uint64_t ++ num_decoded_frame_configs() const { ++ return wuffs_webp__decoder__num_decoded_frame_configs(this); ++ } + +-// -------- ++ inline uint64_t ++ num_decoded_frames() const { ++ return wuffs_webp__decoder__num_decoded_frames(this); ++ } + +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wcast-qual" +-#endif +-static inline uint8_t* // +-wuffs_base__strip_const_from_u8_ptr(const uint8_t* ptr) { +- return (uint8_t*)ptr; +-} +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif ++ inline wuffs_base__status ++ restart_frame( ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ return wuffs_webp__decoder__restart_frame(this, a_index, a_io_position); ++ } + +-// -------- ++ inline wuffs_base__empty_struct ++ set_report_metadata( ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_webp__decoder__set_report_metadata(this, a_fourcc, a_report); ++ } + +-static inline wuffs_base__empty_struct // +-wuffs_base__ignore_status(wuffs_base__status z) { +- return wuffs_base__make_empty_struct(); +-} ++ inline wuffs_base__status ++ tell_me_more( ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ return wuffs_webp__decoder__tell_me_more(this, a_dst, a_minfo, a_src); ++ } + +-static inline wuffs_base__status // +-wuffs_base__status__ensure_not_a_suspension(wuffs_base__status z) { +- if (z.repr && (*z.repr == '$')) { +- z.repr = wuffs_base__error__cannot_return_a_suspension; ++ inline wuffs_base__range_ii_u64 ++ workbuf_len() const { ++ return wuffs_webp__decoder__workbuf_len(this); + } +- return z; +-} + +-// -------- ++#endif // __cplusplus ++}; // struct wuffs_webp__decoder__struct + +-// wuffs_base__iterate_total_advance returns the exclusive pointer-offset at +-// which iteration should stop. The overall slice has length total_len, each +-// iteration's sub-slice has length iter_len and are placed iter_advance apart. +-// +-// The iter_advance may not be larger than iter_len. The iter_advance may be +-// smaller than iter_len, in which case the sub-slices will overlap. +-// +-// The return value r satisfies ((0 <= r) && (r <= total_len)). +-// +-// For example, if total_len = 15, iter_len = 5 and iter_advance = 3, there are +-// four iterations at offsets 0, 3, 6 and 9. This function returns 12. +-// +-// 0123456789012345 +-// [....] +-// [....] +-// [....] +-// [....] +-// $ +-// 0123456789012345 +-// +-// For example, if total_len = 15, iter_len = 5 and iter_advance = 5, there are +-// three iterations at offsets 0, 5 and 10. This function returns 15. ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WEBP) || defined(WUFFS_NONMONOLITHIC) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH32) || defined(WUFFS_NONMONOLITHIC) ++ ++// ---------------- Status Codes ++ ++// ---------------- Public Consts ++ ++// ---------------- Struct Declarations ++ ++typedef struct wuffs_xxhash32__hasher__struct wuffs_xxhash32__hasher; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++// ---------------- Public Initializer Prototypes ++ ++// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self, ++// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)". + // +-// 0123456789012345 +-// [....] +-// [....] +-// [....] +-// $ +-// 0123456789012345 +-static inline size_t // +-wuffs_base__iterate_total_advance(size_t total_len, +- size_t iter_len, +- size_t iter_advance) { +- if (total_len >= iter_len) { +- size_t n = total_len - iter_len; +- return ((n / iter_advance) * iter_advance) + iter_advance; +- } +- return 0; +-} ++// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version. ++// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + +-// ---------------- Numeric Types ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_xxhash32__hasher__initialize( ++ wuffs_xxhash32__hasher* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options); + +-extern const uint8_t wuffs_base__low_bits_mask__u8[8]; +-extern const uint16_t wuffs_base__low_bits_mask__u16[16]; +-extern const uint32_t wuffs_base__low_bits_mask__u32[32]; +-extern const uint64_t wuffs_base__low_bits_mask__u64[64]; ++size_t ++sizeof__wuffs_xxhash32__hasher(void); + +-#define WUFFS_BASE__LOW_BITS_MASK__U8(n) (wuffs_base__low_bits_mask__u8[n]) +-#define WUFFS_BASE__LOW_BITS_MASK__U16(n) (wuffs_base__low_bits_mask__u16[n]) +-#define WUFFS_BASE__LOW_BITS_MASK__U32(n) (wuffs_base__low_bits_mask__u32[n]) +-#define WUFFS_BASE__LOW_BITS_MASK__U64(n) (wuffs_base__low_bits_mask__u64[n]) ++// ---------------- Allocs + +-// -------- ++// These functions allocate and initialize Wuffs structs. They return NULL if ++// memory allocation fails. If they return non-NULL, there is no need to call ++// wuffs_foo__bar__initialize, but the caller is responsible for eventually ++// calling free on the returned pointer. That pointer is effectively a C++ ++// std::unique_ptr. + +-static inline void // +-wuffs_base__u8__sat_add_indirect(uint8_t* x, uint8_t y) { +- *x = wuffs_base__u8__sat_add(*x, y); +-} ++wuffs_xxhash32__hasher* ++wuffs_xxhash32__hasher__alloc(void); + +-static inline void // +-wuffs_base__u8__sat_sub_indirect(uint8_t* x, uint8_t y) { +- *x = wuffs_base__u8__sat_sub(*x, y); ++static inline wuffs_base__hasher_u32* ++wuffs_xxhash32__hasher__alloc_as__wuffs_base__hasher_u32(void) { ++ return (wuffs_base__hasher_u32*)(wuffs_xxhash32__hasher__alloc()); + } + +-static inline void // +-wuffs_base__u16__sat_add_indirect(uint16_t* x, uint16_t y) { +- *x = wuffs_base__u16__sat_add(*x, y); +-} ++// ---------------- Upcasts + +-static inline void // +-wuffs_base__u16__sat_sub_indirect(uint16_t* x, uint16_t y) { +- *x = wuffs_base__u16__sat_sub(*x, y); ++static inline wuffs_base__hasher_u32* ++wuffs_xxhash32__hasher__upcast_as__wuffs_base__hasher_u32( ++ wuffs_xxhash32__hasher* p) { ++ return (wuffs_base__hasher_u32*)p; + } + +-static inline void // +-wuffs_base__u32__sat_add_indirect(uint32_t* x, uint32_t y) { +- *x = wuffs_base__u32__sat_add(*x, y); +-} ++// ---------------- Public Function Prototypes + +-static inline void // +-wuffs_base__u32__sat_sub_indirect(uint32_t* x, uint32_t y) { +- *x = wuffs_base__u32__sat_sub(*x, y); +-} ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_xxhash32__hasher__get_quirk( ++ const wuffs_xxhash32__hasher* self, ++ uint32_t a_key); + +-static inline void // +-wuffs_base__u64__sat_add_indirect(uint64_t* x, uint64_t y) { +- *x = wuffs_base__u64__sat_add(*x, y); +-} ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_xxhash32__hasher__set_quirk( ++ wuffs_xxhash32__hasher* self, ++ uint32_t a_key, ++ uint64_t a_value); + +-static inline void // +-wuffs_base__u64__sat_sub_indirect(uint64_t* x, uint64_t y) { +- *x = wuffs_base__u64__sat_sub(*x, y); +-} ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_xxhash32__hasher__update( ++ wuffs_xxhash32__hasher* self, ++ wuffs_base__slice_u8 a_x); + +-// ---------------- Numeric Types (Utility) ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_xxhash32__hasher__update_u32( ++ wuffs_xxhash32__hasher* self, ++ wuffs_base__slice_u8 a_x); + +-#define wuffs_base__utility__sign_extend_convert_u16_u32(a) \ +- ((uint32_t)(int32_t)(int16_t)(a)) ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_xxhash32__hasher__checksum_u32( ++ const wuffs_xxhash32__hasher* self); + +-#define wuffs_base__utility__sign_extend_rshift_u32(a, n) \ +- ((uint32_t)(((int32_t)(a)) >> (n))) ++#ifdef __cplusplus ++} // extern "C" ++#endif + +-#define wuffs_base__utility__sign_extend_rshift_u64(a, n) \ +- ((uint64_t)(((int64_t)(a)) >> (n))) ++// ---------------- Struct Definitions + +-// ---------------- Slices and Tables ++// These structs' fields, and the sizeof them, are private implementation ++// details that aren't guaranteed to be stable across Wuffs versions. ++// ++// See https://en.wikipedia.org/wiki/Opaque_pointer#C + +-// wuffs_base__slice_u8__prefix returns up to the first up_to bytes of s. +-static inline wuffs_base__slice_u8 // +-wuffs_base__slice_u8__prefix(wuffs_base__slice_u8 s, uint64_t up_to) { +- if (((uint64_t)(s.len)) > up_to) { +- s.len = ((size_t)up_to); ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++struct wuffs_xxhash32__hasher__struct { ++ // Do not access the private_impl's or private_data's fields directly. There ++ // is no API/ABI compatibility or safety guarantee if you do so. Instead, use ++ // the wuffs_foo__bar__baz functions. ++ // ++ // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct ++ // can be stack allocated when WUFFS_IMPLEMENTATION is defined. ++ ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable vtable_for__wuffs_base__hasher_u32; ++ wuffs_base__vtable null_vtable; ++ ++ uint32_t f_length_modulo_u32; ++ bool f_length_overflows_u32; ++ uint8_t f_padding0; ++ uint8_t f_padding1; ++ uint8_t f_buf_len; ++ uint8_t f_buf_data[16]; ++ uint32_t f_v0; ++ uint32_t f_v1; ++ uint32_t f_v2; ++ uint32_t f_v3; ++ } private_impl; ++ ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; ++ ++ // On failure, the alloc_etc functions return nullptr. They don't throw. ++ ++ static inline unique_ptr ++ alloc() { ++ return unique_ptr(wuffs_xxhash32__hasher__alloc()); + } +- return s; +-} + +-// wuffs_base__slice_u8__suffix returns up to the last up_to bytes of s. +-static inline wuffs_base__slice_u8 // +-wuffs_base__slice_u8__suffix(wuffs_base__slice_u8 s, uint64_t up_to) { +- if (((uint64_t)(s.len)) > up_to) { +- s.ptr += ((uint64_t)(s.len)) - up_to; +- s.len = ((size_t)up_to); ++ static inline wuffs_base__hasher_u32::unique_ptr ++ alloc_as__wuffs_base__hasher_u32() { ++ return wuffs_base__hasher_u32::unique_ptr( ++ wuffs_xxhash32__hasher__alloc_as__wuffs_base__hasher_u32()); + } +- return s; +-} ++#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +-// wuffs_base__slice_u8__copy_from_slice calls memmove(dst.ptr, src.ptr, len) +-// where len is the minimum of dst.len and src.len. +-// +-// Passing a wuffs_base__slice_u8 with all fields NULL or zero (a valid, empty +-// slice) is valid and results in a no-op. +-static inline uint64_t // +-wuffs_base__slice_u8__copy_from_slice(wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 src) { +- size_t len = dst.len < src.len ? dst.len : src.len; +- if (len > 0) { +- memmove(dst.ptr, src.ptr, len); ++#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ // Disallow constructing or copying an object via standard C++ mechanisms, ++ // e.g. the "new" operator, as this struct is intentionally opaque. Its total ++ // size and field layout is not part of the public, stable, memory-safe API. ++ // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and ++ // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as ++ // their first argument) rather than tweaking bar.private_impl.qux fields. ++ // ++ // In C, we can just leave wuffs_foo__bar as an incomplete type (unless ++ // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in ++ // order to provide convenience methods. These forward on "this", so that you ++ // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". ++ wuffs_xxhash32__hasher__struct() = delete; ++ wuffs_xxhash32__hasher__struct(const wuffs_xxhash32__hasher__struct&) = delete; ++ wuffs_xxhash32__hasher__struct& operator=( ++ const wuffs_xxhash32__hasher__struct&) = delete; ++#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ ++#if !defined(WUFFS_IMPLEMENTATION) ++ // As above, the size of the struct is not part of the public API, and unless ++ // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap ++ // allocated, not stack allocated. Its size is not intended to be known at ++ // compile time, but it is unfortunately divulged as a side effect of ++ // defining C++ convenience methods. Use "sizeof__T()", calling the function, ++ // instead of "sizeof T", invoking the operator. To make the two values ++ // different, so that passing the latter will be rejected by the initialize ++ // function, we add an arbitrary amount of dead weight. ++ uint8_t dead_weight[123000000]; // 123 MB. ++#endif // !defined(WUFFS_IMPLEMENTATION) ++ ++ inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++ initialize( ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options) { ++ return wuffs_xxhash32__hasher__initialize( ++ this, sizeof_star_self, wuffs_version, options); + } +- return len; +-} + +-static inline wuffs_base__empty_struct // +-wuffs_base__bulk_load_host_endian(void* ptr, +- size_t len, +- wuffs_base__slice_u8 src) { +- if (len && (len <= src.len)) { +- memmove(ptr, src.ptr, len); ++ inline wuffs_base__hasher_u32* ++ upcast_as__wuffs_base__hasher_u32() { ++ return (wuffs_base__hasher_u32*)this; + } +- return wuffs_base__make_empty_struct(); +-} + +-static inline wuffs_base__empty_struct // +-wuffs_base__bulk_memset(void* ptr, size_t len, uint8_t byte_value) { +- if (len) { +- memset(ptr, byte_value, len); ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_xxhash32__hasher__get_quirk(this, a_key); + } +- return wuffs_base__make_empty_struct(); +-} + +-static inline wuffs_base__empty_struct // +-wuffs_base__bulk_save_host_endian(void* ptr, +- size_t len, +- wuffs_base__slice_u8 dst) { +- if (len && (len <= dst.len)) { +- memmove(dst.ptr, ptr, len); ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_xxhash32__hasher__set_quirk(this, a_key, a_value); + } +- return wuffs_base__make_empty_struct(); +-} + +-// -------- ++ inline wuffs_base__empty_struct ++ update( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_xxhash32__hasher__update(this, a_x); ++ } + +-static inline wuffs_base__slice_u8 // +-wuffs_base__table_u8__row_u32(wuffs_base__table_u8 t, uint32_t y) { +- if (y < t.height) { +- return wuffs_base__make_slice_u8(t.ptr + (t.stride * y), t.width); ++ inline uint32_t ++ update_u32( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_xxhash32__hasher__update_u32(this, a_x); + } +- return wuffs_base__make_slice_u8(NULL, 0); +-} + +-// ---------------- Slices and Tables (Utility) ++ inline uint32_t ++ checksum_u32() const { ++ return wuffs_xxhash32__hasher__checksum_u32(this); ++ } + +-#define wuffs_base__utility__empty_slice_u8 wuffs_base__empty_slice_u8 ++#endif // __cplusplus ++}; // struct wuffs_xxhash32__hasher__struct + +-// ---------------- Ranges and Rects ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-static inline uint32_t // +-wuffs_base__range_ii_u32__get_min_incl(const wuffs_base__range_ii_u32* r) { +- return r->min_incl; +-} ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH32) || defined(WUFFS_NONMONOLITHIC) + +-static inline uint32_t // +-wuffs_base__range_ii_u32__get_max_incl(const wuffs_base__range_ii_u32* r) { +- return r->max_incl; +-} ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH64) || defined(WUFFS_NONMONOLITHIC) + +-static inline uint32_t // +-wuffs_base__range_ie_u32__get_min_incl(const wuffs_base__range_ie_u32* r) { +- return r->min_incl; +-} ++// ---------------- Status Codes + +-static inline uint32_t // +-wuffs_base__range_ie_u32__get_max_excl(const wuffs_base__range_ie_u32* r) { +- return r->max_excl; +-} ++// ---------------- Public Consts + +-static inline uint64_t // +-wuffs_base__range_ii_u64__get_min_incl(const wuffs_base__range_ii_u64* r) { +- return r->min_incl; +-} ++// ---------------- Struct Declarations + +-static inline uint64_t // +-wuffs_base__range_ii_u64__get_max_incl(const wuffs_base__range_ii_u64* r) { +- return r->max_incl; +-} ++typedef struct wuffs_xxhash64__hasher__struct wuffs_xxhash64__hasher; + +-static inline uint64_t // +-wuffs_base__range_ie_u64__get_min_incl(const wuffs_base__range_ie_u64* r) { +- return r->min_incl; +-} ++#ifdef __cplusplus ++extern "C" { ++#endif + +-static inline uint64_t // +-wuffs_base__range_ie_u64__get_max_excl(const wuffs_base__range_ie_u64* r) { +- return r->max_excl; +-} ++// ---------------- Public Initializer Prototypes + +-// ---------------- Ranges and Rects (Utility) ++// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self, ++// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)". ++// ++// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version. ++// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + +-#define wuffs_base__utility__empty_range_ii_u32 wuffs_base__empty_range_ii_u32 +-#define wuffs_base__utility__empty_range_ie_u32 wuffs_base__empty_range_ie_u32 +-#define wuffs_base__utility__empty_range_ii_u64 wuffs_base__empty_range_ii_u64 +-#define wuffs_base__utility__empty_range_ie_u64 wuffs_base__empty_range_ie_u64 +-#define wuffs_base__utility__empty_rect_ii_u32 wuffs_base__empty_rect_ii_u32 +-#define wuffs_base__utility__empty_rect_ie_u32 wuffs_base__empty_rect_ie_u32 +-#define wuffs_base__utility__make_range_ii_u32 wuffs_base__make_range_ii_u32 +-#define wuffs_base__utility__make_range_ie_u32 wuffs_base__make_range_ie_u32 +-#define wuffs_base__utility__make_range_ii_u64 wuffs_base__make_range_ii_u64 +-#define wuffs_base__utility__make_range_ie_u64 wuffs_base__make_range_ie_u64 +-#define wuffs_base__utility__make_rect_ii_u32 wuffs_base__make_rect_ii_u32 +-#define wuffs_base__utility__make_rect_ie_u32 wuffs_base__make_rect_ie_u32 ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_xxhash64__hasher__initialize( ++ wuffs_xxhash64__hasher* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options); + +-// ---------------- I/O ++size_t ++sizeof__wuffs_xxhash64__hasher(void); + +-static inline uint64_t // +-wuffs_base__io__count_since(uint64_t mark, uint64_t index) { +- if (index >= mark) { +- return index - mark; +- } +- return 0; +-} ++// ---------------- Allocs + +-// TODO: drop the "const" in "const uint8_t* ptr". Some though required about +-// the base.io_reader.since method returning a mutable "slice base.u8". +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wcast-qual" +-#endif +-static inline wuffs_base__slice_u8 // +-wuffs_base__io__since(uint64_t mark, uint64_t index, const uint8_t* ptr) { +- if (index >= mark) { +- return wuffs_base__make_slice_u8(((uint8_t*)ptr) + mark, +- ((size_t)(index - mark))); +- } +- return wuffs_base__make_slice_u8(NULL, 0); +-} +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif ++// These functions allocate and initialize Wuffs structs. They return NULL if ++// memory allocation fails. If they return non-NULL, there is no need to call ++// wuffs_foo__bar__initialize, but the caller is responsible for eventually ++// calling free on the returned pointer. That pointer is effectively a C++ ++// std::unique_ptr. + +-// -------- ++wuffs_xxhash64__hasher* ++wuffs_xxhash64__hasher__alloc(void); + +-static inline void // +-wuffs_base__io_reader__limit(const uint8_t** ptr_io2_r, +- const uint8_t* iop_r, +- uint64_t limit) { +- if (((uint64_t)(*ptr_io2_r - iop_r)) > limit) { +- *ptr_io2_r = iop_r + limit; +- } ++static inline wuffs_base__hasher_u64* ++wuffs_xxhash64__hasher__alloc_as__wuffs_base__hasher_u64(void) { ++ return (wuffs_base__hasher_u64*)(wuffs_xxhash64__hasher__alloc()); + } + +-static inline uint32_t // +-wuffs_base__io_reader__limited_copy_u32_to_slice(const uint8_t** ptr_iop_r, +- const uint8_t* io2_r, +- uint32_t length, +- wuffs_base__slice_u8 dst) { +- const uint8_t* iop_r = *ptr_iop_r; +- size_t n = dst.len; +- if (n > length) { +- n = length; +- } +- if (n > ((size_t)(io2_r - iop_r))) { +- n = (size_t)(io2_r - iop_r); +- } +- if (n > 0) { +- memmove(dst.ptr, iop_r, n); +- *ptr_iop_r += n; +- } +- return (uint32_t)(n); ++// ---------------- Upcasts ++ ++static inline wuffs_base__hasher_u64* ++wuffs_xxhash64__hasher__upcast_as__wuffs_base__hasher_u64( ++ wuffs_xxhash64__hasher* p) { ++ return (wuffs_base__hasher_u64*)p; + } + +-// wuffs_base__io_reader__match7 returns whether the io_reader's upcoming bytes +-// start with the given prefix (up to 7 bytes long). It is peek-like, not +-// read-like, in that there are no side-effects. +-// +-// The low 3 bits of a hold the prefix length, n. +-// +-// The high 56 bits of a hold the prefix itself, in little-endian order. The +-// first prefix byte is in bits 8..=15, the second prefix byte is in bits +-// 16..=23, etc. The high (8 * (7 - n)) bits are ignored. +-// +-// There are three possible return values: +-// - 0 means success. +-// - 1 means inconclusive, equivalent to "$short read". +-// - 2 means failure. +-static inline uint32_t // +-wuffs_base__io_reader__match7(const uint8_t* iop_r, +- const uint8_t* io2_r, +- wuffs_base__io_buffer* r, +- uint64_t a) { +- uint32_t n = a & 7; +- a >>= 8; +- if ((io2_r - iop_r) >= 8) { +- uint64_t x = wuffs_base__peek_u64le__no_bounds_check(iop_r); +- uint32_t shift = 8 * (8 - n); +- return ((a << shift) == (x << shift)) ? 0 : 2; +- } +- for (; n > 0; n--) { +- if (iop_r >= io2_r) { +- return (r && r->meta.closed) ? 2 : 1; +- } else if (*iop_r != ((uint8_t)(a))) { +- return 2; +- } +- iop_r++; +- a >>= 8; +- } +- return 0; +-} ++// ---------------- Public Function Prototypes + +-static inline wuffs_base__io_buffer* // +-wuffs_base__io_reader__set(wuffs_base__io_buffer* b, +- const uint8_t** ptr_iop_r, +- const uint8_t** ptr_io0_r, +- const uint8_t** ptr_io1_r, +- const uint8_t** ptr_io2_r, +- wuffs_base__slice_u8 data, +- uint64_t history_position) { +- b->data = data; +- b->meta.wi = data.len; +- b->meta.ri = 0; +- b->meta.pos = history_position; +- b->meta.closed = false; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_xxhash64__hasher__get_quirk( ++ const wuffs_xxhash64__hasher* self, ++ uint32_t a_key); + +- *ptr_iop_r = data.ptr; +- *ptr_io0_r = data.ptr; +- *ptr_io1_r = data.ptr; +- *ptr_io2_r = data.ptr + data.len; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_xxhash64__hasher__set_quirk( ++ wuffs_xxhash64__hasher* self, ++ uint32_t a_key, ++ uint64_t a_value); + +- return b; +-} ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_xxhash64__hasher__update( ++ wuffs_xxhash64__hasher* self, ++ wuffs_base__slice_u8 a_x); + +-// -------- ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_xxhash64__hasher__update_u64( ++ wuffs_xxhash64__hasher* self, ++ wuffs_base__slice_u8 a_x); + +-static inline uint64_t // +-wuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w, +- uint8_t* io2_w, +- wuffs_base__slice_u8 src) { +- uint8_t* iop_w = *ptr_iop_w; +- size_t n = src.len; +- if (n > ((size_t)(io2_w - iop_w))) { +- n = (size_t)(io2_w - iop_w); +- } +- if (n > 0) { +- memmove(iop_w, src.ptr, n); +- *ptr_iop_w += n; +- } +- return (uint64_t)(n); +-} ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_xxhash64__hasher__checksum_u64( ++ const wuffs_xxhash64__hasher* self); + +-static inline void // +-wuffs_base__io_writer__limit(uint8_t** ptr_io2_w, +- uint8_t* iop_w, +- uint64_t limit) { +- if (((uint64_t)(*ptr_io2_w - iop_w)) > limit) { +- *ptr_io2_w = iop_w + limit; +- } +-} ++#ifdef __cplusplus ++} // extern "C" ++#endif + +-static inline uint32_t // +-wuffs_base__io_writer__limited_copy_u32_from_history(uint8_t** ptr_iop_w, +- uint8_t* io0_w, +- uint8_t* io2_w, +- uint32_t length, +- uint32_t distance) { +- if (!distance) { +- return 0; +- } +- uint8_t* p = *ptr_iop_w; +- if ((size_t)(p - io0_w) < (size_t)(distance)) { +- return 0; +- } +- uint8_t* q = p - distance; +- size_t n = (size_t)(io2_w - p); +- if ((size_t)(length) > n) { +- length = (uint32_t)(n); +- } else { +- n = (size_t)(length); +- } +- // TODO: unrolling by 3 seems best for the std/deflate benchmarks, but that +- // is mostly because 3 is the minimum length for the deflate format. This +- // function implementation shouldn't overfit to that one format. Perhaps the +- // limited_copy_u32_from_history Wuffs method should also take an unroll hint +- // argument, and the cgen can look if that argument is the constant +- // expression '3'. +- // +- // See also wuffs_base__io_writer__limited_copy_u32_from_history_fast below. +- for (; n >= 3; n -= 3) { +- *p++ = *q++; +- *p++ = *q++; +- *p++ = *q++; +- } +- for (; n; n--) { +- *p++ = *q++; +- } +- *ptr_iop_w = p; +- return length; +-} ++// ---------------- Struct Definitions + +-// wuffs_base__io_writer__limited_copy_u32_from_history_fast is like the +-// wuffs_base__io_writer__limited_copy_u32_from_history function above, but has +-// stronger pre-conditions. ++// These structs' fields, and the sizeof them, are private implementation ++// details that aren't guaranteed to be stable across Wuffs versions. + // +-// The caller needs to prove that: +-// - length <= (io2_w - *ptr_iop_w) +-// - distance >= 1 +-// - distance <= (*ptr_iop_w - io0_w) +-static inline uint32_t // +-wuffs_base__io_writer__limited_copy_u32_from_history_fast(uint8_t** ptr_iop_w, +- uint8_t* io0_w, +- uint8_t* io2_w, +- uint32_t length, +- uint32_t distance) { +- uint8_t* p = *ptr_iop_w; +- uint8_t* q = p - distance; +- uint32_t n = length; +- for (; n >= 3; n -= 3) { +- *p++ = *q++; +- *p++ = *q++; +- *p++ = *q++; +- } +- for (; n; n--) { +- *p++ = *q++; ++// See https://en.wikipedia.org/wiki/Opaque_pointer#C ++ ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) ++ ++struct wuffs_xxhash64__hasher__struct { ++ // Do not access the private_impl's or private_data's fields directly. There ++ // is no API/ABI compatibility or safety guarantee if you do so. Instead, use ++ // the wuffs_foo__bar__baz functions. ++ // ++ // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct ++ // can be stack allocated when WUFFS_IMPLEMENTATION is defined. ++ ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable vtable_for__wuffs_base__hasher_u64; ++ wuffs_base__vtable null_vtable; ++ ++ uint64_t f_length_modulo_u64; ++ bool f_length_overflows_u64; ++ uint8_t f_padding0; ++ uint8_t f_padding1; ++ uint8_t f_padding2; ++ uint32_t f_buf_len; ++ uint8_t f_buf_data[32]; ++ uint64_t f_v0; ++ uint64_t f_v1; ++ uint64_t f_v2; ++ uint64_t f_v3; ++ } private_impl; ++ ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; ++ ++ // On failure, the alloc_etc functions return nullptr. They don't throw. ++ ++ static inline unique_ptr ++ alloc() { ++ return unique_ptr(wuffs_xxhash64__hasher__alloc()); + } +- *ptr_iop_w = p; +- return length; +-} + +-// wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast +-// copies the previous byte (the one immediately before *ptr_iop_w), copying 8 +-// byte chunks at a time. Each chunk contains 8 repetitions of the same byte. +-// +-// In terms of number of bytes copied, length is rounded up to a multiple of 8. +-// As a special case, a zero length rounds up to 8 (even though 0 is already a +-// multiple of 8), since there is always at least one 8 byte chunk copied. +-// +-// In terms of advancing *ptr_iop_w, length is not rounded up. +-// +-// The caller needs to prove that: +-// - (length + 8) <= (io2_w - *ptr_iop_w) +-// - distance == 1 +-// - distance <= (*ptr_iop_w - io0_w) +-static inline uint32_t // +-wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast( +- uint8_t** ptr_iop_w, +- uint8_t* io0_w, +- uint8_t* io2_w, +- uint32_t length, +- uint32_t distance) { +- uint8_t* p = *ptr_iop_w; +- uint64_t x = p[-1]; +- x |= x << 8; +- x |= x << 16; +- x |= x << 32; +- uint32_t n = length; +- while (1) { +- wuffs_base__poke_u64le__no_bounds_check(p, x); +- if (n <= 8) { +- p += n; +- break; +- } +- p += 8; +- n -= 8; ++ static inline wuffs_base__hasher_u64::unique_ptr ++ alloc_as__wuffs_base__hasher_u64() { ++ return wuffs_base__hasher_u64::unique_ptr( ++ wuffs_xxhash64__hasher__alloc_as__wuffs_base__hasher_u64()); + } +- *ptr_iop_w = p; +- return length; +-} ++#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +-// wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast is +-// like the wuffs_base__io_writer__limited_copy_u32_from_history_fast function +-// above, but copies 8 byte chunks at a time. +-// +-// In terms of number of bytes copied, length is rounded up to a multiple of 8. +-// As a special case, a zero length rounds up to 8 (even though 0 is already a +-// multiple of 8), since there is always at least one 8 byte chunk copied. +-// +-// In terms of advancing *ptr_iop_w, length is not rounded up. +-// +-// The caller needs to prove that: +-// - (length + 8) <= (io2_w - *ptr_iop_w) +-// - distance >= 8 +-// - distance <= (*ptr_iop_w - io0_w) +-static inline uint32_t // +-wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast( +- uint8_t** ptr_iop_w, +- uint8_t* io0_w, +- uint8_t* io2_w, +- uint32_t length, +- uint32_t distance) { +- uint8_t* p = *ptr_iop_w; +- uint8_t* q = p - distance; +- uint32_t n = length; +- while (1) { +- memcpy(p, q, 8); +- if (n <= 8) { +- p += n; +- break; +- } +- p += 8; +- q += 8; +- n -= 8; ++#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ // Disallow constructing or copying an object via standard C++ mechanisms, ++ // e.g. the "new" operator, as this struct is intentionally opaque. Its total ++ // size and field layout is not part of the public, stable, memory-safe API. ++ // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and ++ // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as ++ // their first argument) rather than tweaking bar.private_impl.qux fields. ++ // ++ // In C, we can just leave wuffs_foo__bar as an incomplete type (unless ++ // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in ++ // order to provide convenience methods. These forward on "this", so that you ++ // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". ++ wuffs_xxhash64__hasher__struct() = delete; ++ wuffs_xxhash64__hasher__struct(const wuffs_xxhash64__hasher__struct&) = delete; ++ wuffs_xxhash64__hasher__struct& operator=( ++ const wuffs_xxhash64__hasher__struct&) = delete; ++#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ ++#if !defined(WUFFS_IMPLEMENTATION) ++ // As above, the size of the struct is not part of the public API, and unless ++ // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap ++ // allocated, not stack allocated. Its size is not intended to be known at ++ // compile time, but it is unfortunately divulged as a side effect of ++ // defining C++ convenience methods. Use "sizeof__T()", calling the function, ++ // instead of "sizeof T", invoking the operator. To make the two values ++ // different, so that passing the latter will be rejected by the initialize ++ // function, we add an arbitrary amount of dead weight. ++ uint8_t dead_weight[123000000]; // 123 MB. ++#endif // !defined(WUFFS_IMPLEMENTATION) ++ ++ inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++ initialize( ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options) { ++ return wuffs_xxhash64__hasher__initialize( ++ this, sizeof_star_self, wuffs_version, options); + } +- *ptr_iop_w = p; +- return length; +-} + +-static inline uint32_t // +-wuffs_base__io_writer__limited_copy_u32_from_reader(uint8_t** ptr_iop_w, +- uint8_t* io2_w, +- uint32_t length, +- const uint8_t** ptr_iop_r, +- const uint8_t* io2_r) { +- uint8_t* iop_w = *ptr_iop_w; +- size_t n = length; +- if (n > ((size_t)(io2_w - iop_w))) { +- n = (size_t)(io2_w - iop_w); ++ inline wuffs_base__hasher_u64* ++ upcast_as__wuffs_base__hasher_u64() { ++ return (wuffs_base__hasher_u64*)this; + } +- const uint8_t* iop_r = *ptr_iop_r; +- if (n > ((size_t)(io2_r - iop_r))) { +- n = (size_t)(io2_r - iop_r); ++ ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_xxhash64__hasher__get_quirk(this, a_key); + } +- if (n > 0) { +- memmove(iop_w, iop_r, n); +- *ptr_iop_w += n; +- *ptr_iop_r += n; ++ ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_xxhash64__hasher__set_quirk(this, a_key, a_value); + } +- return (uint32_t)(n); +-} + +-static inline uint32_t // +-wuffs_base__io_writer__limited_copy_u32_from_slice(uint8_t** ptr_iop_w, +- uint8_t* io2_w, +- uint32_t length, +- wuffs_base__slice_u8 src) { +- uint8_t* iop_w = *ptr_iop_w; +- size_t n = src.len; +- if (n > length) { +- n = length; ++ inline wuffs_base__empty_struct ++ update( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_xxhash64__hasher__update(this, a_x); + } +- if (n > ((size_t)(io2_w - iop_w))) { +- n = (size_t)(io2_w - iop_w); ++ ++ inline uint64_t ++ update_u64( ++ wuffs_base__slice_u8 a_x) { ++ return wuffs_xxhash64__hasher__update_u64(this, a_x); + } +- if (n > 0) { +- memmove(iop_w, src.ptr, n); +- *ptr_iop_w += n; ++ ++ inline uint64_t ++ checksum_u64() const { ++ return wuffs_xxhash64__hasher__checksum_u64(this); + } +- return (uint32_t)(n); +-} + +-static inline wuffs_base__io_buffer* // +-wuffs_base__io_writer__set(wuffs_base__io_buffer* b, +- uint8_t** ptr_iop_w, +- uint8_t** ptr_io0_w, +- uint8_t** ptr_io1_w, +- uint8_t** ptr_io2_w, +- wuffs_base__slice_u8 data, +- uint64_t history_position) { +- b->data = data; +- b->meta.wi = 0; +- b->meta.ri = 0; +- b->meta.pos = history_position; +- b->meta.closed = false; ++#endif // __cplusplus ++}; // struct wuffs_xxhash64__hasher__struct + +- *ptr_iop_w = data.ptr; +- *ptr_io0_w = data.ptr; +- *ptr_io1_w = data.ptr; +- *ptr_io2_w = data.ptr + data.len; ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +- return b; +-} ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH64) || defined(WUFFS_NONMONOLITHIC) + +-// ---------------- I/O (Utility) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XZ) || defined(WUFFS_NONMONOLITHIC) + +-#define wuffs_base__utility__empty_io_reader wuffs_base__empty_io_reader +-#define wuffs_base__utility__empty_io_writer wuffs_base__empty_io_writer ++// ---------------- Status Codes + +-// ---------------- Tokens ++extern const char wuffs_xz__error__bad_bcj_offset[]; ++extern const char wuffs_xz__error__bad_block_header[]; ++extern const char wuffs_xz__error__bad_checksum[]; ++extern const char wuffs_xz__error__bad_filter[]; ++extern const char wuffs_xz__error__bad_footer[]; ++extern const char wuffs_xz__error__bad_header[]; ++extern const char wuffs_xz__error__bad_header_concatenated_stream[]; ++extern const char wuffs_xz__error__bad_index[]; ++extern const char wuffs_xz__error__bad_padding[]; ++extern const char wuffs_xz__error__truncated_input[]; ++extern const char wuffs_xz__error__unsupported_checksum_algorithm[]; ++extern const char wuffs_xz__error__unsupported_filter[]; ++extern const char wuffs_xz__error__unsupported_filter_combination[]; + +-// ---------------- Tokens (Utility) ++// ---------------- Public Consts + +-// ---------------- Memory Allocation ++#define WUFFS_XZ__QUIRK_DECODE_STANDALONE_CONCATENATED_STREAMS 2021322752u + +-// ---------------- Images ++#define WUFFS_XZ__DECODER_DST_HISTORY_RETAIN_LENGTH_MAX_INCL_WORST_CASE 0u + +-WUFFS_BASE__MAYBE_STATIC uint64_t // +-wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader( +- const wuffs_base__pixel_swizzler* p, +- uint32_t up_to_num_pixels, +- wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 dst_palette, +- const uint8_t** ptr_iop_r, +- const uint8_t* io2_r); ++#define WUFFS_XZ__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 4294967568u + +-WUFFS_BASE__MAYBE_STATIC uint64_t // +-wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( +- const wuffs_base__pixel_swizzler* p, +- wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 dst_palette, +- const uint8_t** ptr_iop_r, +- const uint8_t* io2_r); ++// ---------------- Struct Declarations + +-WUFFS_BASE__MAYBE_STATIC uint64_t // +-wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black( +- const wuffs_base__pixel_swizzler* p, +- wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 dst_palette, +- uint64_t num_pixels); ++typedef struct wuffs_xz__decoder__struct wuffs_xz__decoder; + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status // +-wuffs_base__pixel_swizzler__swizzle_ycck( +- const wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_buffer* dst, +- wuffs_base__slice_u8 dst_palette, +- uint32_t width, +- uint32_t height, +- wuffs_base__slice_u8 src0, +- wuffs_base__slice_u8 src1, +- wuffs_base__slice_u8 src2, +- wuffs_base__slice_u8 src3, +- uint32_t width0, +- uint32_t width1, +- uint32_t width2, +- uint32_t width3, +- uint32_t height0, +- uint32_t height1, +- uint32_t height2, +- uint32_t height3, +- uint32_t stride0, +- uint32_t stride1, +- uint32_t stride2, +- uint32_t stride3, +- uint8_t h0, +- uint8_t h1, +- uint8_t h2, +- uint8_t h3, +- uint8_t v0, +- uint8_t v1, +- uint8_t v2, +- uint8_t v3, +- bool is_rgb_or_cmyk, +- bool triangle_filter_for_2to1, +- wuffs_base__slice_u8 scratch_buffer_2k); ++#ifdef __cplusplus ++extern "C" { ++#endif + +-// ---------------- Images (Utility) ++// ---------------- Public Initializer Prototypes + +-#define wuffs_base__utility__make_pixel_format wuffs_base__make_pixel_format ++// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self, ++// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)". ++// ++// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version. ++// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options. + +-// ---------------- String Conversions ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_xz__decoder__initialize( ++ wuffs_xz__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options); + +-// ---------------- Unicode and UTF-8 ++size_t ++sizeof__wuffs_xz__decoder(void); + +-// ---------------- ++// ---------------- Allocs + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ +- defined(WUFFS_CONFIG__MODULE__BASE__CORE) ++// These functions allocate and initialize Wuffs structs. They return NULL if ++// memory allocation fails. If they return non-NULL, there is no need to call ++// wuffs_foo__bar__initialize, but the caller is responsible for eventually ++// calling free on the returned pointer. That pointer is effectively a C++ ++// std::unique_ptr. + +-const uint8_t wuffs_base__low_bits_mask__u8[8] = { +- 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, +-}; ++wuffs_xz__decoder* ++wuffs_xz__decoder__alloc(void); + +-const uint16_t wuffs_base__low_bits_mask__u16[16] = { +- 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, +- 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, +-}; ++static inline wuffs_base__io_transformer* ++wuffs_xz__decoder__alloc_as__wuffs_base__io_transformer(void) { ++ return (wuffs_base__io_transformer*)(wuffs_xz__decoder__alloc()); ++} + +-const uint32_t wuffs_base__low_bits_mask__u32[32] = { +- 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, +- 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, +- 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, +- 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, +- 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, +- 0x3FFFFFFF, 0x7FFFFFFF, +-}; ++// ---------------- Upcasts + +-const uint64_t wuffs_base__low_bits_mask__u64[64] = { +- 0x0000000000000000, 0x0000000000000001, 0x0000000000000003, +- 0x0000000000000007, 0x000000000000000F, 0x000000000000001F, +- 0x000000000000003F, 0x000000000000007F, 0x00000000000000FF, +- 0x00000000000001FF, 0x00000000000003FF, 0x00000000000007FF, +- 0x0000000000000FFF, 0x0000000000001FFF, 0x0000000000003FFF, +- 0x0000000000007FFF, 0x000000000000FFFF, 0x000000000001FFFF, +- 0x000000000003FFFF, 0x000000000007FFFF, 0x00000000000FFFFF, +- 0x00000000001FFFFF, 0x00000000003FFFFF, 0x00000000007FFFFF, +- 0x0000000000FFFFFF, 0x0000000001FFFFFF, 0x0000000003FFFFFF, +- 0x0000000007FFFFFF, 0x000000000FFFFFFF, 0x000000001FFFFFFF, +- 0x000000003FFFFFFF, 0x000000007FFFFFFF, 0x00000000FFFFFFFF, +- 0x00000001FFFFFFFF, 0x00000003FFFFFFFF, 0x00000007FFFFFFFF, +- 0x0000000FFFFFFFFF, 0x0000001FFFFFFFFF, 0x0000003FFFFFFFFF, +- 0x0000007FFFFFFFFF, 0x000000FFFFFFFFFF, 0x000001FFFFFFFFFF, +- 0x000003FFFFFFFFFF, 0x000007FFFFFFFFFF, 0x00000FFFFFFFFFFF, +- 0x00001FFFFFFFFFFF, 0x00003FFFFFFFFFFF, 0x00007FFFFFFFFFFF, +- 0x0000FFFFFFFFFFFF, 0x0001FFFFFFFFFFFF, 0x0003FFFFFFFFFFFF, +- 0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x001FFFFFFFFFFFFF, +- 0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF, +- 0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF, +- 0x0FFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF, +- 0x7FFFFFFFFFFFFFFF, +-}; ++static inline wuffs_base__io_transformer* ++wuffs_xz__decoder__upcast_as__wuffs_base__io_transformer( ++ wuffs_xz__decoder* p) { ++ return (wuffs_base__io_transformer*)p; ++} + +-const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = { +- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +- 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40, +-}; ++// ---------------- Public Function Prototypes + +-const char wuffs_base__note__i_o_redirect[] = "@base: I/O redirect"; +-const char wuffs_base__note__end_of_data[] = "@base: end of data"; +-const char wuffs_base__note__metadata_reported[] = "@base: metadata reported"; +-const char wuffs_base__suspension__even_more_information[] = "$base: even more information"; +-const char wuffs_base__suspension__mispositioned_read[] = "$base: mispositioned read"; +-const char wuffs_base__suspension__mispositioned_write[] = "$base: mispositioned write"; +-const char wuffs_base__suspension__short_read[] = "$base: short read"; +-const char wuffs_base__suspension__short_write[] = "$base: short write"; +-const char wuffs_base__error__bad_i_o_position[] = "#base: bad I/O position"; +-const char wuffs_base__error__bad_argument_length_too_short[] = "#base: bad argument (length too short)"; +-const char wuffs_base__error__bad_argument[] = "#base: bad argument"; +-const char wuffs_base__error__bad_call_sequence[] = "#base: bad call sequence"; +-const char wuffs_base__error__bad_data[] = "#base: bad data"; +-const char wuffs_base__error__bad_receiver[] = "#base: bad receiver"; +-const char wuffs_base__error__bad_restart[] = "#base: bad restart"; +-const char wuffs_base__error__bad_sizeof_receiver[] = "#base: bad sizeof receiver"; +-const char wuffs_base__error__bad_vtable[] = "#base: bad vtable"; +-const char wuffs_base__error__bad_workbuf_length[] = "#base: bad workbuf length"; +-const char wuffs_base__error__bad_wuffs_version[] = "#base: bad wuffs version"; +-const char wuffs_base__error__cannot_return_a_suspension[] = "#base: cannot return a suspension"; +-const char wuffs_base__error__disabled_by_previous_error[] = "#base: disabled by previous error"; +-const char wuffs_base__error__initialize_falsely_claimed_already_zeroed[] = "#base: initialize falsely claimed already zeroed"; +-const char wuffs_base__error__initialize_not_called[] = "#base: initialize not called"; +-const char wuffs_base__error__interleaved_coroutine_calls[] = "#base: interleaved coroutine calls"; +-const char wuffs_base__error__no_more_information[] = "#base: no more information"; +-const char wuffs_base__error__not_enough_data[] = "#base: not enough data"; +-const char wuffs_base__error__out_of_bounds[] = "#base: out of bounds"; +-const char wuffs_base__error__unsupported_image_dimension[] = "#base: unsupported image dimension"; +-const char wuffs_base__error__unsupported_method[] = "#base: unsupported method"; +-const char wuffs_base__error__unsupported_option[] = "#base: unsupported option"; +-const char wuffs_base__error__unsupported_pixel_swizzler_option[] = "#base: unsupported pixel swizzler option"; +-const char wuffs_base__error__too_much_data[] = "#base: too much data"; +- +-const char wuffs_base__hasher_u32__vtable_name[] = "{vtable}wuffs_base__hasher_u32"; +-const char wuffs_base__hasher_u64__vtable_name[] = "{vtable}wuffs_base__hasher_u64"; +-const char wuffs_base__image_decoder__vtable_name[] = "{vtable}wuffs_base__image_decoder"; +-const char wuffs_base__io_transformer__vtable_name[] = "{vtable}wuffs_base__io_transformer"; +-const char wuffs_base__token_decoder__vtable_name[] = "{vtable}wuffs_base__token_decoder"; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_xz__decoder__get_quirk( ++ const wuffs_xz__decoder* self, ++ uint32_t a_key); + +-#endif // !defined(WUFFS_CONFIG__MODULES) || +- // defined(WUFFS_CONFIG__MODULE__BASE) || +- // defined(WUFFS_CONFIG__MODULE__BASE__CORE) ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_xz__decoder__set_quirk( ++ wuffs_xz__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value); + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ +- defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES) ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_xz__decoder__dst_history_retain_length( ++ const wuffs_xz__decoder* self); + +-// ---------------- Interface Definitions. ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_xz__decoder__workbuf_len( ++ const wuffs_xz__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_base__hasher_u32__checksum_u32( +- const wuffs_base__hasher_u32* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_xz__decoder__transform_io( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { +- const wuffs_base__hasher_u32__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->checksum_u32)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++#ifdef __cplusplus ++} // extern "C" ++#endif + +- return 0; +-} ++// ---------------- Struct Definitions + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__hasher_u32__get_quirk( +- const wuffs_base__hasher_u32* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++// These structs' fields, and the sizeof them, are private implementation ++// details that aren't guaranteed to be stable across Wuffs versions. ++// ++// See https://en.wikipedia.org/wiki/Opaque_pointer#C + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { +- const wuffs_base__hasher_u32__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->get_quirk)(self, a_key); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +- return 0; +-} ++struct wuffs_xz__decoder__struct { ++ // Do not access the private_impl's or private_data's fields directly. There ++ // is no API/ABI compatibility or safety guarantee if you do so. Instead, use ++ // the wuffs_foo__bar__baz functions. ++ // ++ // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct ++ // can be stack allocated when WUFFS_IMPLEMENTATION is defined. + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__hasher_u32__set_quirk( +- wuffs_base__hasher_u32* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++ struct { ++ uint32_t magic; ++ uint32_t active_coroutine; ++ wuffs_base__vtable vtable_for__wuffs_base__io_transformer; ++ wuffs_base__vtable null_vtable; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { +- const wuffs_base__hasher_u32__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->set_quirk)(self, a_key, a_value); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ uint32_t f_filters[3]; ++ uint32_t f_num_non_final_filters; ++ uint8_t f_checksummer; ++ bool f_ignore_checksum; ++ bool f_standalone_format; ++ bool f_lzma_needs_reset; ++ bool f_block_has_compressed_size; ++ bool f_block_has_uncompressed_size; ++ uint8_t f_bcj_undo_index; ++ uint32_t f_bcj_pos; ++ uint32_t f_bcj_x86_prev_mask; ++ uint64_t f_block_compressed_size; ++ uint64_t f_block_uncompressed_size; ++ uint64_t f_compressed_size_for_index; ++ uint32_t f_verification_have_hashed_sizes[2]; ++ uint32_t f_verification_want_hashed_sizes[2]; ++ uint64_t f_verification_have_total_sizes[2]; ++ uint64_t f_verification_want_total_sizes[2]; ++ uint64_t f_num_actual_blocks; ++ uint64_t f_num_index_blocks; ++ uint64_t f_index_block_compressed_size; ++ uint64_t f_index_block_uncompressed_size; ++ uint64_t f_backwards_size; ++ bool f_started_verify_index; ++ uint16_t f_flags; ++ ++ uint8_t (*choosy_apply_non_final_filters)( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ uint32_t p_transform_io; ++ uint32_t p_do_transform_io; ++ uint32_t p_decode_block_header_with_padding; ++ uint32_t p_decode_block_header_sans_padding; ++ uint32_t p_verify_index; ++ uint32_t p_verify_footer; ++ } private_impl; + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++ struct { ++ uint8_t f_filter_data[3][256]; ++ wuffs_crc32__ieee_hasher f_crc32; ++ wuffs_crc64__ecma_hasher f_crc64; ++ wuffs_sha256__hasher f_sha256; ++ wuffs_lzma__decoder f_lzma; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_base__hasher_u32__update( +- wuffs_base__hasher_u32* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return wuffs_base__make_empty_struct(); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); +- } ++ struct { ++ uint32_t v_checksum32_have; ++ uint32_t v_checksum32_want; ++ wuffs_base__bitvec256 v_checksum256_have; ++ uint64_t v_compressed_size; ++ uint64_t v_uncompressed_size; ++ uint64_t scratch; ++ } s_do_transform_io; ++ struct { ++ uint64_t v_padded_size_have; ++ uint64_t v_padded_size_want; ++ } s_decode_block_header_with_padding; ++ struct { ++ uint8_t v_flags; ++ uint8_t v_filter_id; ++ uint32_t v_shift; ++ uint32_t v_f; ++ uint64_t scratch; ++ } s_decode_block_header_sans_padding; ++ struct { ++ uint32_t v_shift; ++ } s_verify_index; ++ struct { ++ uint64_t scratch; ++ } s_verify_footer; ++ } private_data; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { +- const wuffs_base__hasher_u32__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->update)(self, a_x); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++#ifdef __cplusplus ++#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR) ++ using unique_ptr = std::unique_ptr; + +- return wuffs_base__make_empty_struct(); +-} ++ // On failure, the alloc_etc functions return nullptr. They don't throw. + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_base__hasher_u32__update_u32( +- wuffs_base__hasher_u32* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return 0; +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return 0; ++ static inline unique_ptr ++ alloc() { ++ return unique_ptr(wuffs_xz__decoder__alloc()); + } + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { +- const wuffs_base__hasher_u32__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->update_u32)(self, a_x); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; ++ static inline wuffs_base__io_transformer::unique_ptr ++ alloc_as__wuffs_base__io_transformer() { ++ return wuffs_base__io_transformer::unique_ptr( ++ wuffs_xz__decoder__alloc_as__wuffs_base__io_transformer()); + } ++#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +- return 0; +-} ++#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) ++ // Disallow constructing or copying an object via standard C++ mechanisms, ++ // e.g. the "new" operator, as this struct is intentionally opaque. Its total ++ // size and field layout is not part of the public, stable, memory-safe API. ++ // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and ++ // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as ++ // their first argument) rather than tweaking bar.private_impl.qux fields. ++ // ++ // In C, we can just leave wuffs_foo__bar as an incomplete type (unless ++ // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in ++ // order to provide convenience methods. These forward on "this", so that you ++ // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)". ++ wuffs_xz__decoder__struct() = delete; ++ wuffs_xz__decoder__struct(const wuffs_xz__decoder__struct&) = delete; ++ wuffs_xz__decoder__struct& operator=( ++ const wuffs_xz__decoder__struct&) = delete; ++#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION) + +-// -------- ++#if !defined(WUFFS_IMPLEMENTATION) ++ // As above, the size of the struct is not part of the public API, and unless ++ // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap ++ // allocated, not stack allocated. Its size is not intended to be known at ++ // compile time, but it is unfortunately divulged as a side effect of ++ // defining C++ convenience methods. Use "sizeof__T()", calling the function, ++ // instead of "sizeof T", invoking the operator. To make the two values ++ // different, so that passing the latter will be rejected by the initialize ++ // function, we add an arbitrary amount of dead weight. ++ uint8_t dead_weight[123000000]; // 123 MB. ++#endif // !defined(WUFFS_IMPLEMENTATION) + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__hasher_u64__checksum_u64( +- const wuffs_base__hasher_u64* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++ initialize( ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options) { ++ return wuffs_xz__decoder__initialize( ++ this, sizeof_star_self, wuffs_version, options); + } + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { +- const wuffs_base__hasher_u64__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->checksum_u64)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; ++ inline wuffs_base__io_transformer* ++ upcast_as__wuffs_base__io_transformer() { ++ return (wuffs_base__io_transformer*)this; + } + +- return 0; +-} +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__hasher_u64__get_quirk( +- const wuffs_base__hasher_u64* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ inline uint64_t ++ get_quirk( ++ uint32_t a_key) const { ++ return wuffs_xz__decoder__get_quirk(this, a_key); + } + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { +- const wuffs_base__hasher_u64__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->get_quirk)(self, a_key); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; ++ inline wuffs_base__status ++ set_quirk( ++ uint32_t a_key, ++ uint64_t a_value) { ++ return wuffs_xz__decoder__set_quirk(this, a_key, a_value); + } + +- return 0; +-} +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__hasher_u64__set_quirk( +- wuffs_base__hasher_u64* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ inline wuffs_base__optional_u63 ++ dst_history_retain_length() const { ++ return wuffs_xz__decoder__dst_history_retain_length(this); + } + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { +- const wuffs_base__hasher_u64__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->set_quirk)(self, a_key, a_value); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; ++ inline wuffs_base__range_ii_u64 ++ workbuf_len() const { ++ return wuffs_xz__decoder__workbuf_len(this); + } + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_base__hasher_u64__update( +- wuffs_base__hasher_u64* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return wuffs_base__make_empty_struct(); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); ++ inline wuffs_base__status ++ transform_io( ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ return wuffs_xz__decoder__transform_io(this, a_dst, a_src, a_workbuf); + } + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { +- const wuffs_base__hasher_u64__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->update)(self, a_x); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++#endif // __cplusplus ++}; // struct wuffs_xz__decoder__struct + +- return wuffs_base__make_empty_struct(); +-} ++#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION) + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__hasher_u64__update_u64( +- wuffs_base__hasher_u64* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return 0; +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return 0; +- } ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XZ) || defined(WUFFS_NONMONOLITHIC) + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { +- const wuffs_base__hasher_u64__func_ptrs* func_ptrs = +- (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->update_u64)(self, a_x); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++#if defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +- return 0; +-} ++// ---------------- Auxiliary - Base + +-// -------- ++// Auxiliary code is discussed at ++// https://github.com/google/wuffs/blob/main/doc/note/auxiliary-code.md + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__image_decoder__decode_frame( +- wuffs_base__image_decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++#include + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->decode_frame)(self, a_dst, a_src, a_blend, a_workbuf, a_opts); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++#include ++#include + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++namespace wuffs_aux { + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__image_decoder__decode_frame_config( +- wuffs_base__image_decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++using IOBuffer = wuffs_base__io_buffer; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->decode_frame_config)(self, a_dst, a_src); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++// MemOwner represents ownership of some memory. Dynamically allocated memory ++// (e.g. from malloc or new) is typically paired with free or delete, invoked ++// when the std::unique_ptr is destroyed. Statically allocated memory might use ++// MemOwner(nullptr, &free), even if that statically allocated memory is not ++// nullptr, since calling free(nullptr) is a no-op. ++using MemOwner = std::unique_ptr; + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++using QuirkKeyValuePair = std::pair; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__image_decoder__decode_image_config( +- wuffs_base__image_decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++namespace sync_io { + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->decode_image_config)(self, a_dst, a_src); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++// -------- + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++// DynIOBuffer is an IOBuffer that is backed by a dynamically sized byte array. ++// It owns that backing array and will free it in its destructor. ++// ++// The array size can be explicitly extended (by calling the grow method) but, ++// unlike a C++ std::vector, there is no implicit extension (e.g. by calling ++// std::vector::insert) and its maximum size is capped by the max_incl ++// constructor argument. ++// ++// It contains an IOBuffer-typed field whose reader side provides access to ++// previously written bytes and whose writer side provides access to the ++// allocated but not-yet-written-to slack space. For Go programmers, this slack ++// space is roughly analogous to the s[len(s):cap(s)] space of a slice s. ++class DynIOBuffer { ++ public: ++ enum GrowResult { ++ OK = 0, ++ FailedMaxInclExceeded = 1, ++ FailedOutOfMemory = 2, ++ }; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_base__image_decoder__frame_dirty_rect( +- const wuffs_base__image_decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } ++ // m_buf holds the dynamically sized byte array and its read/write indexes: ++ // - m_buf.meta.wi is roughly analogous to a Go slice's length. ++ // - m_buf.data.len is roughly analogous to a Go slice's capacity. It is ++ // also equal to the m_buf.data.ptr malloc/realloc size. ++ // ++ // Users should not modify the m_buf.data.ptr or m_buf.data.len fields (as ++ // they are conceptually private to this class), but they can modify the ++ // bytes referenced by that pointer-length pair (e.g. compactions). ++ IOBuffer m_buf; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->frame_dirty_rect)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ // m_max_incl is an inclusive upper bound on the backing array size. ++ const uint64_t m_max_incl; + +- return wuffs_base__utility__empty_rect_ie_u32(); +-} ++ // Constructor and destructor. ++ explicit DynIOBuffer(uint64_t max_incl); ++ ~DynIOBuffer(); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__image_decoder__get_quirk( +- const wuffs_base__image_decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ // Drop frees the byte array and resets m_buf. The DynIOBuffer can still be ++ // used after a drop call. It just restarts from zero. ++ void drop(); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->get_quirk)(self, a_key); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ // grow ensures that the byte array size is at least min_incl and at most ++ // max_incl. It returns FailedMaxInclExceeded if that would require ++ // allocating more than max_incl bytes, including the case where (min_incl > ++ // max_incl). It returns FailedOutOfMemory if memory allocation failed. ++ GrowResult grow(uint64_t min_incl); + +- return 0; +-} ++ private: ++ // Delete the copy and assign constructors. ++ DynIOBuffer(const DynIOBuffer&) = delete; ++ DynIOBuffer& operator=(const DynIOBuffer&) = delete; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__image_decoder__history_retain_length( +- const wuffs_base__image_decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ static uint64_t round_up(uint64_t min_incl, uint64_t max_incl); ++}; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->history_retain_length)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++// -------- + +- return 0; +-} ++class Input { ++ public: ++ virtual ~Input(); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_base__image_decoder__num_animation_loops( +- const wuffs_base__image_decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ virtual IOBuffer* BringsItsOwnIOBuffer(); ++ virtual std::string CopyIn(IOBuffer* dst) = 0; ++}; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->num_animation_loops)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++// -------- + +- return 0; +-} ++// FileInput is an Input that reads from a file source. ++// ++// It does not take responsibility for closing the file when done. ++class FileInput : public Input { ++ public: ++ FileInput(FILE* f); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__image_decoder__num_decoded_frame_configs( +- const wuffs_base__image_decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ virtual std::string CopyIn(IOBuffer* dst); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->num_decoded_frame_configs)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ private: ++ FILE* m_f; + +- return 0; +-} ++ // Delete the copy and assign constructors. ++ FileInput(const FileInput&) = delete; ++ FileInput& operator=(const FileInput&) = delete; ++}; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__image_decoder__num_decoded_frames( +- const wuffs_base__image_decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++// -------- + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->num_decoded_frames)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++// MemoryInput is an Input that reads from an in-memory source. ++// ++// It does not take responsibility for freeing the memory when done. ++class MemoryInput : public Input { ++ public: ++ MemoryInput(const char* ptr, size_t len); ++ MemoryInput(const uint8_t* ptr, size_t len); + +- return 0; +-} ++ virtual IOBuffer* BringsItsOwnIOBuffer(); ++ virtual std::string CopyIn(IOBuffer* dst); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__image_decoder__restart_frame( +- wuffs_base__image_decoder* self, +- uint64_t a_index, +- uint64_t a_io_position) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++ private: ++ IOBuffer m_io; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->restart_frame)(self, a_index, a_io_position); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ // Delete the copy and assign constructors. ++ MemoryInput(const MemoryInput&) = delete; ++ MemoryInput& operator=(const MemoryInput&) = delete; ++}; + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++// -------- + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__image_decoder__set_quirk( +- wuffs_base__image_decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++} // namespace sync_io + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->set_quirk)(self, a_key, a_value); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++} // namespace wuffs_aux + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++// ---------------- Auxiliary - CBOR + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_base__image_decoder__set_report_metadata( +- wuffs_base__image_decoder* self, +- uint32_t a_fourcc, +- bool a_report) { +- if (!self) { +- return wuffs_base__make_empty_struct(); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); +- } ++namespace wuffs_aux { + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->set_report_metadata)(self, a_fourcc, a_report); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++struct DecodeCborResult { ++ DecodeCborResult(std::string&& error_message0, uint64_t cursor_position0); + +- return wuffs_base__make_empty_struct(); +-} ++ std::string error_message; ++ uint64_t cursor_position; ++}; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__image_decoder__tell_me_more( +- wuffs_base__image_decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++class DecodeCborCallbacks { ++ public: ++ virtual ~DecodeCborCallbacks(); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->tell_me_more)(self, a_dst, a_minfo, a_src); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ // AppendXxx are called for leaf nodes: literals, numbers, strings, etc. + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++ virtual std::string AppendNull() = 0; ++ virtual std::string AppendUndefined() = 0; ++ virtual std::string AppendBool(bool val) = 0; ++ virtual std::string AppendF64(double val) = 0; ++ virtual std::string AppendI64(int64_t val) = 0; ++ virtual std::string AppendU64(uint64_t val) = 0; ++ virtual std::string AppendByteString(std::string&& val) = 0; ++ virtual std::string AppendTextString(std::string&& val) = 0; ++ virtual std::string AppendMinus1MinusX(uint64_t val) = 0; ++ virtual std::string AppendCborSimpleValue(uint8_t val) = 0; ++ virtual std::string AppendCborTag(uint64_t val) = 0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_base__image_decoder__workbuf_len( +- const wuffs_base__image_decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } ++ // Push and Pop are called for container nodes: CBOR arrays (lists) and CBOR ++ // maps (dictionaries). ++ // ++ // The flags bits combine exactly one of: ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT ++ // and exactly one of: ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { +- const wuffs_base__image_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->workbuf_len)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ virtual std::string Push(uint32_t flags) = 0; ++ virtual std::string Pop(uint32_t flags) = 0; + +- return wuffs_base__utility__empty_range_ii_u64(); +-} ++ // Done is always the last Callback method called by DecodeCbor, whether or ++ // not parsing the input as CBOR encountered an error. Even when successful, ++ // trailing data may remain in input and buffer. ++ // ++ // Do not keep a reference to buffer or buffer.data.ptr after Done returns, ++ // as DecodeCbor may then de-allocate the backing array. ++ // ++ // The default Done implementation is a no-op. ++ virtual void // ++ Done(DecodeCborResult& result, sync_io::Input& input, IOBuffer& buffer); ++}; + +-// -------- ++// The FooArgBar types add structure to Foo's optional arguments. They wrap ++// inner representations for several reasons: ++// - It provides a home for the DefaultValue static method, for Foo callers ++// that want to override some but not all optional arguments. ++// - It provides the "Bar" name at Foo call sites, which can help self- ++// document Foo calls with many arguemnts. ++// - It provides some type safety against accidentally transposing or omitting ++// adjacent fundamentally-numeric-typed optional arguments. + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__io_transformer__get_quirk( +- const wuffs_base__io_transformer* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++// DecodeCborArgQuirks wraps an optional argument to DecodeCbor. ++struct DecodeCborArgQuirks { ++ explicit DecodeCborArgQuirks(const QuirkKeyValuePair* ptr0, ++ const size_t len0); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { +- const wuffs_base__io_transformer__func_ptrs* func_ptrs = +- (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->get_quirk)(self, a_key); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ // DefaultValue returns an empty slice. ++ static DecodeCborArgQuirks DefaultValue(); + +- return 0; +-} ++ const QuirkKeyValuePair* ptr; ++ const size_t len; ++}; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__io_transformer__history_retain_length( +- const wuffs_base__io_transformer* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++// DecodeCbor calls callbacks based on the CBOR-formatted data in input. ++// ++// On success, the returned error_message is empty and cursor_position counts ++// the number of bytes consumed. On failure, error_message is non-empty and ++// cursor_position is the location of the error. That error may be a content ++// error (invalid CBOR) or an input error (e.g. network failure). ++DecodeCborResult // ++DecodeCbor(DecodeCborCallbacks& callbacks, ++ sync_io::Input& input, ++ DecodeCborArgQuirks quirks = DecodeCborArgQuirks::DefaultValue()); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { +- const wuffs_base__io_transformer__func_ptrs* func_ptrs = +- (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->history_retain_length)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++} // namespace wuffs_aux + +- return 0; +-} ++// ---------------- Auxiliary - Image + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__io_transformer__set_quirk( +- wuffs_base__io_transformer* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++namespace wuffs_aux { + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { +- const wuffs_base__io_transformer__func_ptrs* func_ptrs = +- (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->set_quirk)(self, a_key, a_value); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++struct DecodeImageResult { ++ DecodeImageResult(MemOwner&& pixbuf_mem_owner0, ++ wuffs_base__pixel_buffer pixbuf0, ++ std::string&& error_message0); ++ DecodeImageResult(std::string&& error_message0); + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++ MemOwner pixbuf_mem_owner; ++ wuffs_base__pixel_buffer pixbuf; ++ std::string error_message; ++}; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__io_transformer__transform_io( +- wuffs_base__io_transformer* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++// DecodeImageCallbacks are the callbacks given to DecodeImage. They are always ++// called in this order: ++// 1. SelectDecoder ++// 2. HandleMetadata ++// 3. SelectPixfmt ++// 4. AllocPixbuf ++// 5. AllocWorkbuf ++// 6. Done ++// ++// It may return early - the third callback might not be invoked if the second ++// one fails - but the final callback (Done) is always invoked. ++class DecodeImageCallbacks { ++ public: ++ // AllocPixbufResult holds a memory allocation (the result of malloc or new, ++ // a statically allocated pointer, etc), or an error message. The memory is ++ // de-allocated when mem_owner goes out of scope and is destroyed. ++ struct AllocPixbufResult { ++ AllocPixbufResult(MemOwner&& mem_owner0, wuffs_base__pixel_buffer pixbuf0); ++ AllocPixbufResult(std::string&& error_message0); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { +- const wuffs_base__io_transformer__func_ptrs* func_ptrs = +- (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->transform_io)(self, a_dst, a_src, a_workbuf); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ MemOwner mem_owner; ++ wuffs_base__pixel_buffer pixbuf; ++ std::string error_message; ++ }; + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++ // AllocWorkbufResult holds a memory allocation (the result of malloc or new, ++ // a statically allocated pointer, etc), or an error message. The memory is ++ // de-allocated when mem_owner goes out of scope and is destroyed. ++ struct AllocWorkbufResult { ++ AllocWorkbufResult(MemOwner&& mem_owner0, wuffs_base__slice_u8 workbuf0); ++ AllocWorkbufResult(std::string&& error_message0); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_base__io_transformer__workbuf_len( +- const wuffs_base__io_transformer* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } ++ MemOwner mem_owner; ++ wuffs_base__slice_u8 workbuf; ++ std::string error_message; ++ }; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { +- const wuffs_base__io_transformer__func_ptrs* func_ptrs = +- (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->workbuf_len)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ virtual ~DecodeImageCallbacks(); + +- return wuffs_base__utility__empty_range_ii_u64(); +-} ++ // SelectDecoder returns the image decoder for the input data's file format. ++ // Returning a nullptr means failure (DecodeImage_UnsupportedImageFormat). ++ // ++ // Common formats will have a FourCC value in the range [1 ..= 0x7FFF_FFFF], ++ // such as WUFFS_BASE__FOURCC__JPEG. A zero FourCC value means that Wuffs' ++ // standard library did not recognize the image format but if SelectDecoder ++ // was overridden, it may examine the input data's starting bytes and still ++ // provide its own image decoder, e.g. for an exotic image file format that's ++ // not in Wuffs' standard library. The prefix_etc fields have the same ++ // meaning as wuffs_base__magic_number_guess_fourcc arguments. SelectDecoder ++ // implementations should not modify prefix_data's contents. ++ // ++ // SelectDecoder might be called more than once, since some image file ++ // formats can wrap others. For example, a nominal BMP file can actually ++ // contain a JPEG or a PNG. ++ // ++ // The default SelectDecoder accepts the FOURCC codes listed below. For ++ // modular builds (i.e. when #define'ing WUFFS_CONFIG__MODULES), acceptance ++ // of the ETC file format is optional (for each value of ETC) and depends on ++ // the corresponding module to be enabled at compile time (i.e. #define'ing ++ // WUFFS_CONFIG__MODULE__ETC). ++ // - WUFFS_BASE__FOURCC__BMP ++ // - WUFFS_BASE__FOURCC__GIF ++ // - WUFFS_BASE__FOURCC__JPEG ++ // - WUFFS_BASE__FOURCC__NIE ++ // - WUFFS_BASE__FOURCC__NPBM ++ // - WUFFS_BASE__FOURCC__PNG ++ // - WUFFS_BASE__FOURCC__QOI ++ // - WUFFS_BASE__FOURCC__TGA ++ // - WUFFS_BASE__FOURCC__WBMP ++ // - WUFFS_BASE__FOURCC__WEBP ++ virtual wuffs_base__image_decoder::unique_ptr // ++ SelectDecoder(uint32_t fourcc, ++ wuffs_base__slice_u8 prefix_data, ++ bool prefix_closed); + +-// -------- ++ // HandleMetadata acknowledges image metadata. minfo.flavor will be one of: ++ // - WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH ++ // - WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED ++ // If it is ETC__METADATA_RAW_ETC then raw contains the metadata bytes. Those ++ // bytes should not be retained beyond the the HandleMetadata call. ++ // ++ // minfo.metadata__fourcc() will typically match one of the ++ // DecodeImageArgFlags bits. For example, if (REPORT_METADATA_CHRM | ++ // REPORT_METADATA_GAMA) was passed to DecodeImage then the metadata FourCC ++ // will be either WUFFS_BASE__FOURCC__CHRM or WUFFS_BASE__FOURCC__GAMA. ++ // ++ // It returns an error message, or an empty string on success. ++ virtual std::string // ++ HandleMetadata(const wuffs_base__more_information& minfo, ++ wuffs_base__slice_u8 raw); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__token_decoder__decode_tokens( +- wuffs_base__token_decoder* self, +- wuffs_base__token_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++ // SelectPixfmt returns the destination pixel format for AllocPixbuf. It ++ // should return wuffs_base__make_pixel_format(etc) called with one of: ++ // - WUFFS_BASE__PIXEL_FORMAT__BGR_565 ++ // - WUFFS_BASE__PIXEL_FORMAT__BGR ++ // - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL ++ // - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE ++ // - WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL ++ // - WUFFS_BASE__PIXEL_FORMAT__RGB ++ // - WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL ++ // - WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL ++ // or return image_config.pixcfg.pixel_format(). The latter means to use the ++ // image file's natural pixel format. For example, GIF images' natural pixel ++ // format is an indexed one. ++ // ++ // Returning otherwise means failure (DecodeImage_UnsupportedPixelFormat). ++ // ++ // The default SelectPixfmt implementation returns ++ // wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL) which ++ // is 4 bytes per pixel (8 bits per channel × 4 channels). ++ virtual wuffs_base__pixel_format // ++ SelectPixfmt(const wuffs_base__image_config& image_config); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { +- const wuffs_base__token_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->decode_tokens)(self, a_dst, a_src, a_workbuf); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ // AllocPixbuf allocates the pixel buffer. ++ // ++ // allow_uninitialized_memory will be true if a valid background_color was ++ // passed to DecodeImage, since the pixel buffer's contents will be ++ // overwritten with that color after AllocPixbuf returns. ++ // ++ // The default AllocPixbuf implementation allocates either uninitialized or ++ // zeroed memory. Zeroed memory typically corresponds to filling with opaque ++ // black or transparent black, depending on the pixel format. ++ virtual AllocPixbufResult // ++ AllocPixbuf(const wuffs_base__image_config& image_config, ++ bool allow_uninitialized_memory); + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++ // AllocWorkbuf allocates the work buffer. The allocated buffer's length ++ // should be at least len_range.min_incl, but larger allocations (up to ++ // len_range.max_incl) may have better performance (by using more memory). ++ // ++ // The default AllocWorkbuf implementation allocates len_range.max_incl bytes ++ // of either uninitialized or zeroed memory. ++ virtual AllocWorkbufResult // ++ AllocWorkbuf(wuffs_base__range_ii_u64 len_range, ++ bool allow_uninitialized_memory); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__token_decoder__get_quirk( +- const wuffs_base__token_decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ // Done is always the last Callback method called by DecodeImage, whether or ++ // not parsing the input encountered an error. Even when successful, trailing ++ // data may remain in input and buffer. ++ // ++ // The image_decoder is the one returned by SelectDecoder (if SelectDecoder ++ // was successful), or a no-op unique_ptr otherwise. Like any unique_ptr, ++ // ownership moves to the Done implementation. ++ // ++ // Do not keep a reference to buffer or buffer.data.ptr after Done returns, ++ // as DecodeImage may then de-allocate the backing array. ++ // ++ // The default Done implementation is a no-op, other than running the ++ // image_decoder unique_ptr destructor. ++ virtual void // ++ Done(DecodeImageResult& result, ++ sync_io::Input& input, ++ IOBuffer& buffer, ++ wuffs_base__image_decoder::unique_ptr image_decoder); ++}; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { +- const wuffs_base__token_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->get_quirk)(self, a_key); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++extern const char DecodeImage_BufferIsTooShort[]; ++extern const char DecodeImage_MaxInclDimensionExceeded[]; ++extern const char DecodeImage_MaxInclMetadataLengthExceeded[]; ++extern const char DecodeImage_OutOfMemory[]; ++extern const char DecodeImage_UnexpectedEndOfFile[]; ++extern const char DecodeImage_UnsupportedImageFormat[]; ++extern const char DecodeImage_UnsupportedMetadata[]; ++extern const char DecodeImage_UnsupportedPixelBlend[]; ++extern const char DecodeImage_UnsupportedPixelConfiguration[]; ++extern const char DecodeImage_UnsupportedPixelFormat[]; + +- return 0; +-} ++// The FooArgBar types add structure to Foo's optional arguments. They wrap ++// inner representations for several reasons: ++// - It provides a home for the DefaultValue static method, for Foo callers ++// that want to override some but not all optional arguments. ++// - It provides the "Bar" name at Foo call sites, which can help self- ++// document Foo calls with many arguemnts. ++// - It provides some type safety against accidentally transposing or omitting ++// adjacent fundamentally-numeric-typed optional arguments. + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_base__token_decoder__history_retain_length( +- const wuffs_base__token_decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++// DecodeImageArgQuirks wraps an optional argument to DecodeImage. ++struct DecodeImageArgQuirks { ++ explicit DecodeImageArgQuirks(const QuirkKeyValuePair* ptr0, ++ const size_t len0); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { +- const wuffs_base__token_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->history_retain_length)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ // DefaultValue returns an empty slice. ++ static DecodeImageArgQuirks DefaultValue(); + +- return 0; +-} ++ const QuirkKeyValuePair* ptr; ++ const size_t len; ++}; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_base__token_decoder__set_quirk( +- wuffs_base__token_decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++// DecodeImageArgFlags wraps an optional argument to DecodeImage. ++struct DecodeImageArgFlags { ++ explicit DecodeImageArgFlags(uint64_t repr0); + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { +- const wuffs_base__token_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->set_quirk)(self, a_key, a_value); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ // DefaultValue returns 0. ++ static DecodeImageArgFlags DefaultValue(); + +- return wuffs_base__make_status(wuffs_base__error__bad_vtable); +-} ++ // TODO: support all of the REPORT_METADATA_ETC flags, not just CHRM, EXIF, ++ // GAMA, ICCP, KVP, SRGB and XMP. + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_base__token_decoder__workbuf_len( +- const wuffs_base__token_decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } ++ // Background Color. ++ static constexpr uint64_t REPORT_METADATA_BGCL = 0x0001; ++ // Primary Chromaticities and White Point. ++ static constexpr uint64_t REPORT_METADATA_CHRM = 0x0002; ++ // Exchangeable Image File Format. ++ static constexpr uint64_t REPORT_METADATA_EXIF = 0x0004; ++ // Gamma Correction. ++ static constexpr uint64_t REPORT_METADATA_GAMA = 0x0008; ++ // International Color Consortium Profile. ++ static constexpr uint64_t REPORT_METADATA_ICCP = 0x0010; ++ // Key-Value Pair. ++ // ++ // For PNG files, this includes iTXt, tEXt and zTXt chunks. In the ++ // HandleMetadata callback, the raw argument contains UTF-8 strings. ++ static constexpr uint64_t REPORT_METADATA_KVP = 0x0020; ++ // Modification Time. ++ static constexpr uint64_t REPORT_METADATA_MTIM = 0x0040; ++ // Offset (2-Dimensional). ++ static constexpr uint64_t REPORT_METADATA_OFS2 = 0x0080; ++ // Physical Dimensions. ++ static constexpr uint64_t REPORT_METADATA_PHYD = 0x0100; ++ // Standard Red Green Blue (Rendering Intent). ++ static constexpr uint64_t REPORT_METADATA_SRGB = 0x0200; ++ // Extensible Metadata Platform. ++ static constexpr uint64_t REPORT_METADATA_XMP = 0x0400; + +- const wuffs_base__vtable* v = &self->private_impl.first_vtable; +- int i; +- for (i = 0; i < 63; i++) { +- if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { +- const wuffs_base__token_decoder__func_ptrs* func_ptrs = +- (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); +- return (*func_ptrs->workbuf_len)(self); +- } else if (v->vtable_name == NULL) { +- break; +- } +- v++; +- } ++ uint64_t repr; ++}; + +- return wuffs_base__utility__empty_range_ii_u64(); +-} ++// DecodeImageArgPixelBlend wraps an optional argument to DecodeImage. ++struct DecodeImageArgPixelBlend { ++ explicit DecodeImageArgPixelBlend(wuffs_base__pixel_blend repr0); + +-#endif // !defined(WUFFS_CONFIG__MODULES) || +- // defined(WUFFS_CONFIG__MODULE__BASE) || +- // defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES) ++ // DefaultValue returns WUFFS_BASE__PIXEL_BLEND__SRC. ++ static DecodeImageArgPixelBlend DefaultValue(); + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ +- defined(WUFFS_CONFIG__MODULE__BASE__FLOATCONV) ++ wuffs_base__pixel_blend repr; ++}; + +-// ---------------- IEEE 754 Floating Point ++// DecodeImageArgBackgroundColor wraps an optional argument to DecodeImage. ++struct DecodeImageArgBackgroundColor { ++ explicit DecodeImageArgBackgroundColor( ++ wuffs_base__color_u32_argb_premul repr0); + +-// The etc__hpd_left_shift and etc__powers_of_5 tables were printed by +-// script/print-hpd-left-shift.go. That script has an optional -comments flag, +-// whose output is not copied here, which prints further detail. +-// +-// These tables are used in +-// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits. ++ // DefaultValue returns 1, an invalid wuffs_base__color_u32_argb_premul. ++ static DecodeImageArgBackgroundColor DefaultValue(); ++ ++ wuffs_base__color_u32_argb_premul repr; ++}; ++ ++// DecodeImageArgMaxInclDimension wraps an optional argument to DecodeImage. ++struct DecodeImageArgMaxInclDimension { ++ explicit DecodeImageArgMaxInclDimension(uint32_t repr0); ++ ++ // DefaultValue returns 1048575 = 0x000F_FFFF, more than 1 million pixels. ++ static DecodeImageArgMaxInclDimension DefaultValue(); ++ ++ uint32_t repr; ++}; ++ ++// DecodeImageArgMaxInclMetadataLength wraps an optional argument to ++// DecodeImage. ++struct DecodeImageArgMaxInclMetadataLength { ++ explicit DecodeImageArgMaxInclMetadataLength(uint64_t repr0); ++ ++ // DefaultValue returns 16777215 = 0x00FF_FFFF, one less than 16 MiB. ++ static DecodeImageArgMaxInclMetadataLength DefaultValue(); ++ ++ uint64_t repr; ++}; + +-// wuffs_base__private_implementation__hpd_left_shift[i] encodes the number of +-// new digits created after multiplying a positive integer by (1 << i): the +-// additional length in the decimal representation. For example, shifting "234" +-// by 3 (equivalent to multiplying by 8) will produce "1872". Going from a +-// 3-length string to a 4-length string means that 1 new digit was added (and +-// existing digits may have changed). ++// DecodeImage decodes the image data in input. A variety of image file formats ++// can be decoded, depending on what callbacks.SelectDecoder returns. + // +-// Shifting by i can add either N or N-1 new digits, depending on whether the +-// original positive integer compares >= or < to the i'th power of 5 (as 10 +-// equals 2 * 5). Comparison is lexicographic, not numerical. ++// For animated formats, only the first frame is returned, since the API is ++// simpler for synchronous I/O and having DecodeImage only return when ++// completely done, but rendering animation often involves handling other ++// events in between animation frames. To decode multiple frames of animated ++// images, or for asynchronous I/O (e.g. when decoding an image streamed over ++// the network), use Wuffs' lower level C API instead of its higher level, ++// simplified C++ API (the wuffs_aux API). + // +-// For example, shifting by 4 (i.e. multiplying by 16) can add 1 or 2 new +-// digits, depending on a lexicographic comparison to (5 ** 4), i.e. "625": +-// - ("1" << 4) is "16", which adds 1 new digit. +-// - ("5678" << 4) is "90848", which adds 1 new digit. +-// - ("624" << 4) is "9984", which adds 1 new digit. +-// - ("62498" << 4) is "999968", which adds 1 new digit. +-// - ("625" << 4) is "10000", which adds 2 new digits. +-// - ("625001" << 4) is "10000016", which adds 2 new digits. +-// - ("7008" << 4) is "112128", which adds 2 new digits. +-// - ("99" << 4) is "1584", which adds 2 new digits. ++// The DecodeImageResult's fields depend on whether decoding succeeded: ++// - On total success, the error_message is empty and pixbuf.pixcfg.is_valid() ++// is true. ++// - On partial success (e.g. the input file was truncated but we are still ++// able to decode some of the pixels), error_message is non-empty but ++// pixbuf.pixcfg.is_valid() is still true. It is up to the caller whether to ++// accept or reject partial success. ++// - On failure, the error_message is non_empty and pixbuf.pixcfg.is_valid() ++// is false. + // +-// Thus, when i is 4, N is 2 and (5 ** i) is "625". This etc__hpd_left_shift +-// array encodes this as: +-// - etc__hpd_left_shift[4] is 0x1006 = (2 << 11) | 0x0006. +-// - etc__hpd_left_shift[5] is 0x1009 = (? << 11) | 0x0009. +-// where the ? isn't relevant for i == 4. ++// The callbacks allocate the pixel buffer memory and work buffer memory. On ++// success, pixel buffer memory ownership is passed to the DecodeImage caller ++// as the returned pixbuf_mem_owner. Regardless of success or failure, the work ++// buffer memory is deleted. + // +-// The high 5 bits of etc__hpd_left_shift[i] is N, the higher of the two +-// possible number of new digits. The low 11 bits are an offset into the +-// etc__powers_of_5 array (of length 0x051C, so offsets fit in 11 bits). When i +-// is 4, its offset and the next one is 6 and 9, and etc__powers_of_5[6 .. 9] +-// is the string "\x06\x02\x05", so the relevant power of 5 is "625". ++// The pixel_blend (one of the constants listed below) determines how to ++// composite the decoded image over the pixel buffer's original pixels (as ++// returned by callbacks.AllocPixbuf): ++// - WUFFS_BASE__PIXEL_BLEND__SRC ++// - WUFFS_BASE__PIXEL_BLEND__SRC_OVER + // +-// Thanks to Ken Thompson for the original idea. +-static const uint16_t wuffs_base__private_implementation__hpd_left_shift[65] = { +- 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, +- 0x181D, 0x2024, 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, +- 0x3073, 0x3080, 0x388E, 0x389C, 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, +- 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, 0x5180, 0x5998, 0x59B0, +- 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, 0x72AA, +- 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, +- 0x8C02, 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, +- 0x051C, 0x051C, +-}; +- +-// wuffs_base__private_implementation__powers_of_5 contains the powers of 5, +-// concatenated together: "5", "25", "125", "625", "3125", etc. +-static const uint8_t wuffs_base__private_implementation__powers_of_5[0x051C] = { +- 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, +- 0, 6, 2, 5, 1, 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, +- 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, 1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, +- 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, 5, 1, 5, 2, 5, 8, 7, 8, 9, 0, +- 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6, 9, 7, 2, 6, 5, +- 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1, +- 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, +- 1, 8, 5, 7, 9, 1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, +- 8, 1, 2, 5, 5, 9, 6, 0, 4, 6, 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, +- 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1, 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, +- 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2, 3, 8, 2, 8, 1, +- 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6, +- 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, +- 7, 4, 6, 1, 5, 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, +- 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, 5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, +- 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5, 3, 2, 1, 8, 2, 6, 9, 3, 4, 8, +- 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4, 6, 7, 4, 0, 7, +- 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6, +- 1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, +- 0, 6, 6, 4, 0, 6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, +- 0, 3, 3, 2, 0, 3, 1, 2, 5, 3, 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, +- 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, +- 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, 7, 0, 1, 7, 7, +- 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5, +- 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, +- 7, 3, 6, 7, 5, 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, +- 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, 7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, +- 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8, 8, 6, 0, 8, 0, 8, 0, 1, 4, 8, +- 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0, 9, 4, 3, 0, 4, +- 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0, +- 8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, +- 6, 2, 5, 7, 1, 0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, +- 2, 4, 2, 6, 7, 5, 7, 8, 1, 2, 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, +- 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, +- 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0, 6, 6, 8, 9, 4, +- 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3, +- 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, +- 5, 0, 0, 6, 2, 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, +- 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, 9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, +- 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1, 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, +- 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8, 2, 0, 3, 1, 2, +- 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, +- 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, +- 6, 2, 8, 9, 1, 3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, +- 1, 2, 5, 1, 3, 8, 7, 7, 7, 8, 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, +- 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, 6, 2, 5, 6, 9, 3, 8, 8, 9, 3, +- 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, 5, 5, 6, 7, 6, +- 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1, +- 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, +- 7, 3, 4, 7, 2, 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, +- 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, 8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, +- 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2, 2, 4, 0, 6, 9, 5, 9, 5, 3, 3, +- 6, 9, 1, 4, 0, 6, 2, 5, +-}; ++// The background_color is used to fill the pixel buffer after ++// callbacks.AllocPixbuf returns, if it is valid in the ++// wuffs_base__color_u32_argb_premul__is_valid sense. The default value, ++// 0x0000_0001, is not valid since its Blue channel value (0x01) is greater ++// than its Alpha channel value (0x00). A valid background_color will typically ++// be overwritten when pixel_blend is WUFFS_BASE__PIXEL_BLEND__SRC, but might ++// still be visible on partial (not total) success or when pixel_blend is ++// WUFFS_BASE__PIXEL_BLEND__SRC_OVER and the decoded image is not fully opaque. ++// ++// Decoding fails (with DecodeImage_MaxInclDimensionExceeded) if the image's ++// width or height is greater than max_incl_dimension or if any opted-in (via ++// flags bits) metadata is longer than max_incl_metadata_length. ++DecodeImageResult // ++DecodeImage(DecodeImageCallbacks& callbacks, ++ sync_io::Input& input, ++ DecodeImageArgQuirks quirks = DecodeImageArgQuirks::DefaultValue(), ++ DecodeImageArgFlags flags = DecodeImageArgFlags::DefaultValue(), ++ DecodeImageArgPixelBlend pixel_blend = ++ DecodeImageArgPixelBlend::DefaultValue(), ++ DecodeImageArgBackgroundColor background_color = ++ DecodeImageArgBackgroundColor::DefaultValue(), ++ DecodeImageArgMaxInclDimension max_incl_dimension = ++ DecodeImageArgMaxInclDimension::DefaultValue(), ++ DecodeImageArgMaxInclMetadataLength max_incl_metadata_length = ++ DecodeImageArgMaxInclMetadataLength::DefaultValue()); + +-// -------- ++} // namespace wuffs_aux + +-// wuffs_base__private_implementation__powers_of_10 contains truncated +-// approximations to the powers of 10, ranging from 1e-307 to 1e+288 inclusive, +-// as 596 pairs of uint64_t values (a 128-bit mantissa). +-// +-// There's also an implicit third column (implied by a linear formula involving +-// the base-10 exponent) that is the base-2 exponent, biased by a magic +-// constant. That constant (1214 or 0x04BE) equals 1023 + 191. 1023 is the bias +-// for IEEE 754 double-precision floating point. 191 is ((3 * 64) - 1) and +-// wuffs_base__private_implementation__parse_number_f64_eisel_lemire works with +-// multiples-of-64-bit mantissas. +-// +-// For example, the third row holds the approximation to 1e-305: +-// 0xE0B62E29_29ABA83C_331ACDAB_FE94DE87 * (2 ** (0x0049 - 0x04BE)) +-// +-// Similarly, 1e+4 is approximated by: +-// 0x9C400000_00000000_00000000_00000000 * (2 ** (0x044C - 0x04BE)) +-// +-// Similarly, 1e+68 is approximated by: +-// 0xED63A231_D4C4FB27_4CA7AAA8_63EE4BDD * (2 ** (0x0520 - 0x04BE)) +-// +-// This table was generated by by script/print-mpb-powers-of-10.go +-static const uint64_t wuffs_base__private_implementation__powers_of_10[596][2] = +- { +- {0xA5D3B6D479F8E056, 0x8FD0C16206306BAB}, // 1e-307 +- {0x8F48A4899877186C, 0xB3C4F1BA87BC8696}, // 1e-306 +- {0x331ACDABFE94DE87, 0xE0B62E2929ABA83C}, // 1e-305 +- {0x9FF0C08B7F1D0B14, 0x8C71DCD9BA0B4925}, // 1e-304 +- {0x07ECF0AE5EE44DD9, 0xAF8E5410288E1B6F}, // 1e-303 +- {0xC9E82CD9F69D6150, 0xDB71E91432B1A24A}, // 1e-302 +- {0xBE311C083A225CD2, 0x892731AC9FAF056E}, // 1e-301 +- {0x6DBD630A48AAF406, 0xAB70FE17C79AC6CA}, // 1e-300 +- {0x092CBBCCDAD5B108, 0xD64D3D9DB981787D}, // 1e-299 +- {0x25BBF56008C58EA5, 0x85F0468293F0EB4E}, // 1e-298 +- {0xAF2AF2B80AF6F24E, 0xA76C582338ED2621}, // 1e-297 +- {0x1AF5AF660DB4AEE1, 0xD1476E2C07286FAA}, // 1e-296 +- {0x50D98D9FC890ED4D, 0x82CCA4DB847945CA}, // 1e-295 +- {0xE50FF107BAB528A0, 0xA37FCE126597973C}, // 1e-294 +- {0x1E53ED49A96272C8, 0xCC5FC196FEFD7D0C}, // 1e-293 +- {0x25E8E89C13BB0F7A, 0xFF77B1FCBEBCDC4F}, // 1e-292 +- {0x77B191618C54E9AC, 0x9FAACF3DF73609B1}, // 1e-291 +- {0xD59DF5B9EF6A2417, 0xC795830D75038C1D}, // 1e-290 +- {0x4B0573286B44AD1D, 0xF97AE3D0D2446F25}, // 1e-289 +- {0x4EE367F9430AEC32, 0x9BECCE62836AC577}, // 1e-288 +- {0x229C41F793CDA73F, 0xC2E801FB244576D5}, // 1e-287 +- {0x6B43527578C1110F, 0xF3A20279ED56D48A}, // 1e-286 +- {0x830A13896B78AAA9, 0x9845418C345644D6}, // 1e-285 +- {0x23CC986BC656D553, 0xBE5691EF416BD60C}, // 1e-284 +- {0x2CBFBE86B7EC8AA8, 0xEDEC366B11C6CB8F}, // 1e-283 +- {0x7BF7D71432F3D6A9, 0x94B3A202EB1C3F39}, // 1e-282 +- {0xDAF5CCD93FB0CC53, 0xB9E08A83A5E34F07}, // 1e-281 +- {0xD1B3400F8F9CFF68, 0xE858AD248F5C22C9}, // 1e-280 +- {0x23100809B9C21FA1, 0x91376C36D99995BE}, // 1e-279 +- {0xABD40A0C2832A78A, 0xB58547448FFFFB2D}, // 1e-278 +- {0x16C90C8F323F516C, 0xE2E69915B3FFF9F9}, // 1e-277 +- {0xAE3DA7D97F6792E3, 0x8DD01FAD907FFC3B}, // 1e-276 +- {0x99CD11CFDF41779C, 0xB1442798F49FFB4A}, // 1e-275 +- {0x40405643D711D583, 0xDD95317F31C7FA1D}, // 1e-274 +- {0x482835EA666B2572, 0x8A7D3EEF7F1CFC52}, // 1e-273 +- {0xDA3243650005EECF, 0xAD1C8EAB5EE43B66}, // 1e-272 +- {0x90BED43E40076A82, 0xD863B256369D4A40}, // 1e-271 +- {0x5A7744A6E804A291, 0x873E4F75E2224E68}, // 1e-270 +- {0x711515D0A205CB36, 0xA90DE3535AAAE202}, // 1e-269 +- {0x0D5A5B44CA873E03, 0xD3515C2831559A83}, // 1e-268 +- {0xE858790AFE9486C2, 0x8412D9991ED58091}, // 1e-267 +- {0x626E974DBE39A872, 0xA5178FFF668AE0B6}, // 1e-266 +- {0xFB0A3D212DC8128F, 0xCE5D73FF402D98E3}, // 1e-265 +- {0x7CE66634BC9D0B99, 0x80FA687F881C7F8E}, // 1e-264 +- {0x1C1FFFC1EBC44E80, 0xA139029F6A239F72}, // 1e-263 +- {0xA327FFB266B56220, 0xC987434744AC874E}, // 1e-262 +- {0x4BF1FF9F0062BAA8, 0xFBE9141915D7A922}, // 1e-261 +- {0x6F773FC3603DB4A9, 0x9D71AC8FADA6C9B5}, // 1e-260 +- {0xCB550FB4384D21D3, 0xC4CE17B399107C22}, // 1e-259 +- {0x7E2A53A146606A48, 0xF6019DA07F549B2B}, // 1e-258 +- {0x2EDA7444CBFC426D, 0x99C102844F94E0FB}, // 1e-257 +- {0xFA911155FEFB5308, 0xC0314325637A1939}, // 1e-256 +- {0x793555AB7EBA27CA, 0xF03D93EEBC589F88}, // 1e-255 +- {0x4BC1558B2F3458DE, 0x96267C7535B763B5}, // 1e-254 +- {0x9EB1AAEDFB016F16, 0xBBB01B9283253CA2}, // 1e-253 +- {0x465E15A979C1CADC, 0xEA9C227723EE8BCB}, // 1e-252 +- {0x0BFACD89EC191EC9, 0x92A1958A7675175F}, // 1e-251 +- {0xCEF980EC671F667B, 0xB749FAED14125D36}, // 1e-250 +- {0x82B7E12780E7401A, 0xE51C79A85916F484}, // 1e-249 +- {0xD1B2ECB8B0908810, 0x8F31CC0937AE58D2}, // 1e-248 +- {0x861FA7E6DCB4AA15, 0xB2FE3F0B8599EF07}, // 1e-247 +- {0x67A791E093E1D49A, 0xDFBDCECE67006AC9}, // 1e-246 +- {0xE0C8BB2C5C6D24E0, 0x8BD6A141006042BD}, // 1e-245 +- {0x58FAE9F773886E18, 0xAECC49914078536D}, // 1e-244 +- {0xAF39A475506A899E, 0xDA7F5BF590966848}, // 1e-243 +- {0x6D8406C952429603, 0x888F99797A5E012D}, // 1e-242 +- {0xC8E5087BA6D33B83, 0xAAB37FD7D8F58178}, // 1e-241 +- {0xFB1E4A9A90880A64, 0xD5605FCDCF32E1D6}, // 1e-240 +- {0x5CF2EEA09A55067F, 0x855C3BE0A17FCD26}, // 1e-239 +- {0xF42FAA48C0EA481E, 0xA6B34AD8C9DFC06F}, // 1e-238 +- {0xF13B94DAF124DA26, 0xD0601D8EFC57B08B}, // 1e-237 +- {0x76C53D08D6B70858, 0x823C12795DB6CE57}, // 1e-236 +- {0x54768C4B0C64CA6E, 0xA2CB1717B52481ED}, // 1e-235 +- {0xA9942F5DCF7DFD09, 0xCB7DDCDDA26DA268}, // 1e-234 +- {0xD3F93B35435D7C4C, 0xFE5D54150B090B02}, // 1e-233 +- {0xC47BC5014A1A6DAF, 0x9EFA548D26E5A6E1}, // 1e-232 +- {0x359AB6419CA1091B, 0xC6B8E9B0709F109A}, // 1e-231 +- {0xC30163D203C94B62, 0xF867241C8CC6D4C0}, // 1e-230 +- {0x79E0DE63425DCF1D, 0x9B407691D7FC44F8}, // 1e-229 +- {0x985915FC12F542E4, 0xC21094364DFB5636}, // 1e-228 +- {0x3E6F5B7B17B2939D, 0xF294B943E17A2BC4}, // 1e-227 +- {0xA705992CEECF9C42, 0x979CF3CA6CEC5B5A}, // 1e-226 +- {0x50C6FF782A838353, 0xBD8430BD08277231}, // 1e-225 +- {0xA4F8BF5635246428, 0xECE53CEC4A314EBD}, // 1e-224 +- {0x871B7795E136BE99, 0x940F4613AE5ED136}, // 1e-223 +- {0x28E2557B59846E3F, 0xB913179899F68584}, // 1e-222 +- {0x331AEADA2FE589CF, 0xE757DD7EC07426E5}, // 1e-221 +- {0x3FF0D2C85DEF7621, 0x9096EA6F3848984F}, // 1e-220 +- {0x0FED077A756B53A9, 0xB4BCA50B065ABE63}, // 1e-219 +- {0xD3E8495912C62894, 0xE1EBCE4DC7F16DFB}, // 1e-218 +- {0x64712DD7ABBBD95C, 0x8D3360F09CF6E4BD}, // 1e-217 +- {0xBD8D794D96AACFB3, 0xB080392CC4349DEC}, // 1e-216 +- {0xECF0D7A0FC5583A0, 0xDCA04777F541C567}, // 1e-215 +- {0xF41686C49DB57244, 0x89E42CAAF9491B60}, // 1e-214 +- {0x311C2875C522CED5, 0xAC5D37D5B79B6239}, // 1e-213 +- {0x7D633293366B828B, 0xD77485CB25823AC7}, // 1e-212 +- {0xAE5DFF9C02033197, 0x86A8D39EF77164BC}, // 1e-211 +- {0xD9F57F830283FDFC, 0xA8530886B54DBDEB}, // 1e-210 +- {0xD072DF63C324FD7B, 0xD267CAA862A12D66}, // 1e-209 +- {0x4247CB9E59F71E6D, 0x8380DEA93DA4BC60}, // 1e-208 +- {0x52D9BE85F074E608, 0xA46116538D0DEB78}, // 1e-207 +- {0x67902E276C921F8B, 0xCD795BE870516656}, // 1e-206 +- {0x00BA1CD8A3DB53B6, 0x806BD9714632DFF6}, // 1e-205 +- {0x80E8A40ECCD228A4, 0xA086CFCD97BF97F3}, // 1e-204 +- {0x6122CD128006B2CD, 0xC8A883C0FDAF7DF0}, // 1e-203 +- {0x796B805720085F81, 0xFAD2A4B13D1B5D6C}, // 1e-202 +- {0xCBE3303674053BB0, 0x9CC3A6EEC6311A63}, // 1e-201 +- {0xBEDBFC4411068A9C, 0xC3F490AA77BD60FC}, // 1e-200 +- {0xEE92FB5515482D44, 0xF4F1B4D515ACB93B}, // 1e-199 +- {0x751BDD152D4D1C4A, 0x991711052D8BF3C5}, // 1e-198 +- {0xD262D45A78A0635D, 0xBF5CD54678EEF0B6}, // 1e-197 +- {0x86FB897116C87C34, 0xEF340A98172AACE4}, // 1e-196 +- {0xD45D35E6AE3D4DA0, 0x9580869F0E7AAC0E}, // 1e-195 +- {0x8974836059CCA109, 0xBAE0A846D2195712}, // 1e-194 +- {0x2BD1A438703FC94B, 0xE998D258869FACD7}, // 1e-193 +- {0x7B6306A34627DDCF, 0x91FF83775423CC06}, // 1e-192 +- {0x1A3BC84C17B1D542, 0xB67F6455292CBF08}, // 1e-191 +- {0x20CABA5F1D9E4A93, 0xE41F3D6A7377EECA}, // 1e-190 +- {0x547EB47B7282EE9C, 0x8E938662882AF53E}, // 1e-189 +- {0xE99E619A4F23AA43, 0xB23867FB2A35B28D}, // 1e-188 +- {0x6405FA00E2EC94D4, 0xDEC681F9F4C31F31}, // 1e-187 +- {0xDE83BC408DD3DD04, 0x8B3C113C38F9F37E}, // 1e-186 +- {0x9624AB50B148D445, 0xAE0B158B4738705E}, // 1e-185 +- {0x3BADD624DD9B0957, 0xD98DDAEE19068C76}, // 1e-184 +- {0xE54CA5D70A80E5D6, 0x87F8A8D4CFA417C9}, // 1e-183 +- {0x5E9FCF4CCD211F4C, 0xA9F6D30A038D1DBC}, // 1e-182 +- {0x7647C3200069671F, 0xD47487CC8470652B}, // 1e-181 +- {0x29ECD9F40041E073, 0x84C8D4DFD2C63F3B}, // 1e-180 +- {0xF468107100525890, 0xA5FB0A17C777CF09}, // 1e-179 +- {0x7182148D4066EEB4, 0xCF79CC9DB955C2CC}, // 1e-178 +- {0xC6F14CD848405530, 0x81AC1FE293D599BF}, // 1e-177 +- {0xB8ADA00E5A506A7C, 0xA21727DB38CB002F}, // 1e-176 +- {0xA6D90811F0E4851C, 0xCA9CF1D206FDC03B}, // 1e-175 +- {0x908F4A166D1DA663, 0xFD442E4688BD304A}, // 1e-174 +- {0x9A598E4E043287FE, 0x9E4A9CEC15763E2E}, // 1e-173 +- {0x40EFF1E1853F29FD, 0xC5DD44271AD3CDBA}, // 1e-172 +- {0xD12BEE59E68EF47C, 0xF7549530E188C128}, // 1e-171 +- {0x82BB74F8301958CE, 0x9A94DD3E8CF578B9}, // 1e-170 +- {0xE36A52363C1FAF01, 0xC13A148E3032D6E7}, // 1e-169 +- {0xDC44E6C3CB279AC1, 0xF18899B1BC3F8CA1}, // 1e-168 +- {0x29AB103A5EF8C0B9, 0x96F5600F15A7B7E5}, // 1e-167 +- {0x7415D448F6B6F0E7, 0xBCB2B812DB11A5DE}, // 1e-166 +- {0x111B495B3464AD21, 0xEBDF661791D60F56}, // 1e-165 +- {0xCAB10DD900BEEC34, 0x936B9FCEBB25C995}, // 1e-164 +- {0x3D5D514F40EEA742, 0xB84687C269EF3BFB}, // 1e-163 +- {0x0CB4A5A3112A5112, 0xE65829B3046B0AFA}, // 1e-162 +- {0x47F0E785EABA72AB, 0x8FF71A0FE2C2E6DC}, // 1e-161 +- {0x59ED216765690F56, 0xB3F4E093DB73A093}, // 1e-160 +- {0x306869C13EC3532C, 0xE0F218B8D25088B8}, // 1e-159 +- {0x1E414218C73A13FB, 0x8C974F7383725573}, // 1e-158 +- {0xE5D1929EF90898FA, 0xAFBD2350644EEACF}, // 1e-157 +- {0xDF45F746B74ABF39, 0xDBAC6C247D62A583}, // 1e-156 +- {0x6B8BBA8C328EB783, 0x894BC396CE5DA772}, // 1e-155 +- {0x066EA92F3F326564, 0xAB9EB47C81F5114F}, // 1e-154 +- {0xC80A537B0EFEFEBD, 0xD686619BA27255A2}, // 1e-153 +- {0xBD06742CE95F5F36, 0x8613FD0145877585}, // 1e-152 +- {0x2C48113823B73704, 0xA798FC4196E952E7}, // 1e-151 +- {0xF75A15862CA504C5, 0xD17F3B51FCA3A7A0}, // 1e-150 +- {0x9A984D73DBE722FB, 0x82EF85133DE648C4}, // 1e-149 +- {0xC13E60D0D2E0EBBA, 0xA3AB66580D5FDAF5}, // 1e-148 +- {0x318DF905079926A8, 0xCC963FEE10B7D1B3}, // 1e-147 +- {0xFDF17746497F7052, 0xFFBBCFE994E5C61F}, // 1e-146 +- {0xFEB6EA8BEDEFA633, 0x9FD561F1FD0F9BD3}, // 1e-145 +- {0xFE64A52EE96B8FC0, 0xC7CABA6E7C5382C8}, // 1e-144 +- {0x3DFDCE7AA3C673B0, 0xF9BD690A1B68637B}, // 1e-143 +- {0x06BEA10CA65C084E, 0x9C1661A651213E2D}, // 1e-142 +- {0x486E494FCFF30A62, 0xC31BFA0FE5698DB8}, // 1e-141 +- {0x5A89DBA3C3EFCCFA, 0xF3E2F893DEC3F126}, // 1e-140 +- {0xF89629465A75E01C, 0x986DDB5C6B3A76B7}, // 1e-139 +- {0xF6BBB397F1135823, 0xBE89523386091465}, // 1e-138 +- {0x746AA07DED582E2C, 0xEE2BA6C0678B597F}, // 1e-137 +- {0xA8C2A44EB4571CDC, 0x94DB483840B717EF}, // 1e-136 +- {0x92F34D62616CE413, 0xBA121A4650E4DDEB}, // 1e-135 +- {0x77B020BAF9C81D17, 0xE896A0D7E51E1566}, // 1e-134 +- {0x0ACE1474DC1D122E, 0x915E2486EF32CD60}, // 1e-133 +- {0x0D819992132456BA, 0xB5B5ADA8AAFF80B8}, // 1e-132 +- {0x10E1FFF697ED6C69, 0xE3231912D5BF60E6}, // 1e-131 +- {0xCA8D3FFA1EF463C1, 0x8DF5EFABC5979C8F}, // 1e-130 +- {0xBD308FF8A6B17CB2, 0xB1736B96B6FD83B3}, // 1e-129 +- {0xAC7CB3F6D05DDBDE, 0xDDD0467C64BCE4A0}, // 1e-128 +- {0x6BCDF07A423AA96B, 0x8AA22C0DBEF60EE4}, // 1e-127 +- {0x86C16C98D2C953C6, 0xAD4AB7112EB3929D}, // 1e-126 +- {0xE871C7BF077BA8B7, 0xD89D64D57A607744}, // 1e-125 +- {0x11471CD764AD4972, 0x87625F056C7C4A8B}, // 1e-124 +- {0xD598E40D3DD89BCF, 0xA93AF6C6C79B5D2D}, // 1e-123 +- {0x4AFF1D108D4EC2C3, 0xD389B47879823479}, // 1e-122 +- {0xCEDF722A585139BA, 0x843610CB4BF160CB}, // 1e-121 +- {0xC2974EB4EE658828, 0xA54394FE1EEDB8FE}, // 1e-120 +- {0x733D226229FEEA32, 0xCE947A3DA6A9273E}, // 1e-119 +- {0x0806357D5A3F525F, 0x811CCC668829B887}, // 1e-118 +- {0xCA07C2DCB0CF26F7, 0xA163FF802A3426A8}, // 1e-117 +- {0xFC89B393DD02F0B5, 0xC9BCFF6034C13052}, // 1e-116 +- {0xBBAC2078D443ACE2, 0xFC2C3F3841F17C67}, // 1e-115 +- {0xD54B944B84AA4C0D, 0x9D9BA7832936EDC0}, // 1e-114 +- {0x0A9E795E65D4DF11, 0xC5029163F384A931}, // 1e-113 +- {0x4D4617B5FF4A16D5, 0xF64335BCF065D37D}, // 1e-112 +- {0x504BCED1BF8E4E45, 0x99EA0196163FA42E}, // 1e-111 +- {0xE45EC2862F71E1D6, 0xC06481FB9BCF8D39}, // 1e-110 +- {0x5D767327BB4E5A4C, 0xF07DA27A82C37088}, // 1e-109 +- {0x3A6A07F8D510F86F, 0x964E858C91BA2655}, // 1e-108 +- {0x890489F70A55368B, 0xBBE226EFB628AFEA}, // 1e-107 +- {0x2B45AC74CCEA842E, 0xEADAB0ABA3B2DBE5}, // 1e-106 +- {0x3B0B8BC90012929D, 0x92C8AE6B464FC96F}, // 1e-105 +- {0x09CE6EBB40173744, 0xB77ADA0617E3BBCB}, // 1e-104 +- {0xCC420A6A101D0515, 0xE55990879DDCAABD}, // 1e-103 +- {0x9FA946824A12232D, 0x8F57FA54C2A9EAB6}, // 1e-102 +- {0x47939822DC96ABF9, 0xB32DF8E9F3546564}, // 1e-101 +- {0x59787E2B93BC56F7, 0xDFF9772470297EBD}, // 1e-100 +- {0x57EB4EDB3C55B65A, 0x8BFBEA76C619EF36}, // 1e-99 +- {0xEDE622920B6B23F1, 0xAEFAE51477A06B03}, // 1e-98 +- {0xE95FAB368E45ECED, 0xDAB99E59958885C4}, // 1e-97 +- {0x11DBCB0218EBB414, 0x88B402F7FD75539B}, // 1e-96 +- {0xD652BDC29F26A119, 0xAAE103B5FCD2A881}, // 1e-95 +- {0x4BE76D3346F0495F, 0xD59944A37C0752A2}, // 1e-94 +- {0x6F70A4400C562DDB, 0x857FCAE62D8493A5}, // 1e-93 +- {0xCB4CCD500F6BB952, 0xA6DFBD9FB8E5B88E}, // 1e-92 +- {0x7E2000A41346A7A7, 0xD097AD07A71F26B2}, // 1e-91 +- {0x8ED400668C0C28C8, 0x825ECC24C873782F}, // 1e-90 +- {0x728900802F0F32FA, 0xA2F67F2DFA90563B}, // 1e-89 +- {0x4F2B40A03AD2FFB9, 0xCBB41EF979346BCA}, // 1e-88 +- {0xE2F610C84987BFA8, 0xFEA126B7D78186BC}, // 1e-87 +- {0x0DD9CA7D2DF4D7C9, 0x9F24B832E6B0F436}, // 1e-86 +- {0x91503D1C79720DBB, 0xC6EDE63FA05D3143}, // 1e-85 +- {0x75A44C6397CE912A, 0xF8A95FCF88747D94}, // 1e-84 +- {0xC986AFBE3EE11ABA, 0x9B69DBE1B548CE7C}, // 1e-83 +- {0xFBE85BADCE996168, 0xC24452DA229B021B}, // 1e-82 +- {0xFAE27299423FB9C3, 0xF2D56790AB41C2A2}, // 1e-81 +- {0xDCCD879FC967D41A, 0x97C560BA6B0919A5}, // 1e-80 +- {0x5400E987BBC1C920, 0xBDB6B8E905CB600F}, // 1e-79 +- {0x290123E9AAB23B68, 0xED246723473E3813}, // 1e-78 +- {0xF9A0B6720AAF6521, 0x9436C0760C86E30B}, // 1e-77 +- {0xF808E40E8D5B3E69, 0xB94470938FA89BCE}, // 1e-76 +- {0xB60B1D1230B20E04, 0xE7958CB87392C2C2}, // 1e-75 +- {0xB1C6F22B5E6F48C2, 0x90BD77F3483BB9B9}, // 1e-74 +- {0x1E38AEB6360B1AF3, 0xB4ECD5F01A4AA828}, // 1e-73 +- {0x25C6DA63C38DE1B0, 0xE2280B6C20DD5232}, // 1e-72 +- {0x579C487E5A38AD0E, 0x8D590723948A535F}, // 1e-71 +- {0x2D835A9DF0C6D851, 0xB0AF48EC79ACE837}, // 1e-70 +- {0xF8E431456CF88E65, 0xDCDB1B2798182244}, // 1e-69 +- {0x1B8E9ECB641B58FF, 0x8A08F0F8BF0F156B}, // 1e-68 +- {0xE272467E3D222F3F, 0xAC8B2D36EED2DAC5}, // 1e-67 +- {0x5B0ED81DCC6ABB0F, 0xD7ADF884AA879177}, // 1e-66 +- {0x98E947129FC2B4E9, 0x86CCBB52EA94BAEA}, // 1e-65 +- {0x3F2398D747B36224, 0xA87FEA27A539E9A5}, // 1e-64 +- {0x8EEC7F0D19A03AAD, 0xD29FE4B18E88640E}, // 1e-63 +- {0x1953CF68300424AC, 0x83A3EEEEF9153E89}, // 1e-62 +- {0x5FA8C3423C052DD7, 0xA48CEAAAB75A8E2B}, // 1e-61 +- {0x3792F412CB06794D, 0xCDB02555653131B6}, // 1e-60 +- {0xE2BBD88BBEE40BD0, 0x808E17555F3EBF11}, // 1e-59 +- {0x5B6ACEAEAE9D0EC4, 0xA0B19D2AB70E6ED6}, // 1e-58 +- {0xF245825A5A445275, 0xC8DE047564D20A8B}, // 1e-57 +- {0xEED6E2F0F0D56712, 0xFB158592BE068D2E}, // 1e-56 +- {0x55464DD69685606B, 0x9CED737BB6C4183D}, // 1e-55 +- {0xAA97E14C3C26B886, 0xC428D05AA4751E4C}, // 1e-54 +- {0xD53DD99F4B3066A8, 0xF53304714D9265DF}, // 1e-53 +- {0xE546A8038EFE4029, 0x993FE2C6D07B7FAB}, // 1e-52 +- {0xDE98520472BDD033, 0xBF8FDB78849A5F96}, // 1e-51 +- {0x963E66858F6D4440, 0xEF73D256A5C0F77C}, // 1e-50 +- {0xDDE7001379A44AA8, 0x95A8637627989AAD}, // 1e-49 +- {0x5560C018580D5D52, 0xBB127C53B17EC159}, // 1e-48 +- {0xAAB8F01E6E10B4A6, 0xE9D71B689DDE71AF}, // 1e-47 +- {0xCAB3961304CA70E8, 0x9226712162AB070D}, // 1e-46 +- {0x3D607B97C5FD0D22, 0xB6B00D69BB55C8D1}, // 1e-45 +- {0x8CB89A7DB77C506A, 0xE45C10C42A2B3B05}, // 1e-44 +- {0x77F3608E92ADB242, 0x8EB98A7A9A5B04E3}, // 1e-43 +- {0x55F038B237591ED3, 0xB267ED1940F1C61C}, // 1e-42 +- {0x6B6C46DEC52F6688, 0xDF01E85F912E37A3}, // 1e-41 +- {0x2323AC4B3B3DA015, 0x8B61313BBABCE2C6}, // 1e-40 +- {0xABEC975E0A0D081A, 0xAE397D8AA96C1B77}, // 1e-39 +- {0x96E7BD358C904A21, 0xD9C7DCED53C72255}, // 1e-38 +- {0x7E50D64177DA2E54, 0x881CEA14545C7575}, // 1e-37 +- {0xDDE50BD1D5D0B9E9, 0xAA242499697392D2}, // 1e-36 +- {0x955E4EC64B44E864, 0xD4AD2DBFC3D07787}, // 1e-35 +- {0xBD5AF13BEF0B113E, 0x84EC3C97DA624AB4}, // 1e-34 +- {0xECB1AD8AEACDD58E, 0xA6274BBDD0FADD61}, // 1e-33 +- {0x67DE18EDA5814AF2, 0xCFB11EAD453994BA}, // 1e-32 +- {0x80EACF948770CED7, 0x81CEB32C4B43FCF4}, // 1e-31 +- {0xA1258379A94D028D, 0xA2425FF75E14FC31}, // 1e-30 +- {0x096EE45813A04330, 0xCAD2F7F5359A3B3E}, // 1e-29 +- {0x8BCA9D6E188853FC, 0xFD87B5F28300CA0D}, // 1e-28 +- {0x775EA264CF55347D, 0x9E74D1B791E07E48}, // 1e-27 +- {0x95364AFE032A819D, 0xC612062576589DDA}, // 1e-26 +- {0x3A83DDBD83F52204, 0xF79687AED3EEC551}, // 1e-25 +- {0xC4926A9672793542, 0x9ABE14CD44753B52}, // 1e-24 +- {0x75B7053C0F178293, 0xC16D9A0095928A27}, // 1e-23 +- {0x5324C68B12DD6338, 0xF1C90080BAF72CB1}, // 1e-22 +- {0xD3F6FC16EBCA5E03, 0x971DA05074DA7BEE}, // 1e-21 +- {0x88F4BB1CA6BCF584, 0xBCE5086492111AEA}, // 1e-20 +- {0x2B31E9E3D06C32E5, 0xEC1E4A7DB69561A5}, // 1e-19 +- {0x3AFF322E62439FCF, 0x9392EE8E921D5D07}, // 1e-18 +- {0x09BEFEB9FAD487C2, 0xB877AA3236A4B449}, // 1e-17 +- {0x4C2EBE687989A9B3, 0xE69594BEC44DE15B}, // 1e-16 +- {0x0F9D37014BF60A10, 0x901D7CF73AB0ACD9}, // 1e-15 +- {0x538484C19EF38C94, 0xB424DC35095CD80F}, // 1e-14 +- {0x2865A5F206B06FB9, 0xE12E13424BB40E13}, // 1e-13 +- {0xF93F87B7442E45D3, 0x8CBCCC096F5088CB}, // 1e-12 +- {0xF78F69A51539D748, 0xAFEBFF0BCB24AAFE}, // 1e-11 +- {0xB573440E5A884D1B, 0xDBE6FECEBDEDD5BE}, // 1e-10 +- {0x31680A88F8953030, 0x89705F4136B4A597}, // 1e-9 +- {0xFDC20D2B36BA7C3D, 0xABCC77118461CEFC}, // 1e-8 +- {0x3D32907604691B4C, 0xD6BF94D5E57A42BC}, // 1e-7 +- {0xA63F9A49C2C1B10F, 0x8637BD05AF6C69B5}, // 1e-6 +- {0x0FCF80DC33721D53, 0xA7C5AC471B478423}, // 1e-5 +- {0xD3C36113404EA4A8, 0xD1B71758E219652B}, // 1e-4 +- {0x645A1CAC083126E9, 0x83126E978D4FDF3B}, // 1e-3 +- {0x3D70A3D70A3D70A3, 0xA3D70A3D70A3D70A}, // 1e-2 +- {0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC}, // 1e-1 +- {0x0000000000000000, 0x8000000000000000}, // 1e0 +- {0x0000000000000000, 0xA000000000000000}, // 1e1 +- {0x0000000000000000, 0xC800000000000000}, // 1e2 +- {0x0000000000000000, 0xFA00000000000000}, // 1e3 +- {0x0000000000000000, 0x9C40000000000000}, // 1e4 +- {0x0000000000000000, 0xC350000000000000}, // 1e5 +- {0x0000000000000000, 0xF424000000000000}, // 1e6 +- {0x0000000000000000, 0x9896800000000000}, // 1e7 +- {0x0000000000000000, 0xBEBC200000000000}, // 1e8 +- {0x0000000000000000, 0xEE6B280000000000}, // 1e9 +- {0x0000000000000000, 0x9502F90000000000}, // 1e10 +- {0x0000000000000000, 0xBA43B74000000000}, // 1e11 +- {0x0000000000000000, 0xE8D4A51000000000}, // 1e12 +- {0x0000000000000000, 0x9184E72A00000000}, // 1e13 +- {0x0000000000000000, 0xB5E620F480000000}, // 1e14 +- {0x0000000000000000, 0xE35FA931A0000000}, // 1e15 +- {0x0000000000000000, 0x8E1BC9BF04000000}, // 1e16 +- {0x0000000000000000, 0xB1A2BC2EC5000000}, // 1e17 +- {0x0000000000000000, 0xDE0B6B3A76400000}, // 1e18 +- {0x0000000000000000, 0x8AC7230489E80000}, // 1e19 +- {0x0000000000000000, 0xAD78EBC5AC620000}, // 1e20 +- {0x0000000000000000, 0xD8D726B7177A8000}, // 1e21 +- {0x0000000000000000, 0x878678326EAC9000}, // 1e22 +- {0x0000000000000000, 0xA968163F0A57B400}, // 1e23 +- {0x0000000000000000, 0xD3C21BCECCEDA100}, // 1e24 +- {0x0000000000000000, 0x84595161401484A0}, // 1e25 +- {0x0000000000000000, 0xA56FA5B99019A5C8}, // 1e26 +- {0x0000000000000000, 0xCECB8F27F4200F3A}, // 1e27 +- {0x4000000000000000, 0x813F3978F8940984}, // 1e28 +- {0x5000000000000000, 0xA18F07D736B90BE5}, // 1e29 +- {0xA400000000000000, 0xC9F2C9CD04674EDE}, // 1e30 +- {0x4D00000000000000, 0xFC6F7C4045812296}, // 1e31 +- {0xF020000000000000, 0x9DC5ADA82B70B59D}, // 1e32 +- {0x6C28000000000000, 0xC5371912364CE305}, // 1e33 +- {0xC732000000000000, 0xF684DF56C3E01BC6}, // 1e34 +- {0x3C7F400000000000, 0x9A130B963A6C115C}, // 1e35 +- {0x4B9F100000000000, 0xC097CE7BC90715B3}, // 1e36 +- {0x1E86D40000000000, 0xF0BDC21ABB48DB20}, // 1e37 +- {0x1314448000000000, 0x96769950B50D88F4}, // 1e38 +- {0x17D955A000000000, 0xBC143FA4E250EB31}, // 1e39 +- {0x5DCFAB0800000000, 0xEB194F8E1AE525FD}, // 1e40 +- {0x5AA1CAE500000000, 0x92EFD1B8D0CF37BE}, // 1e41 +- {0xF14A3D9E40000000, 0xB7ABC627050305AD}, // 1e42 +- {0x6D9CCD05D0000000, 0xE596B7B0C643C719}, // 1e43 +- {0xE4820023A2000000, 0x8F7E32CE7BEA5C6F}, // 1e44 +- {0xDDA2802C8A800000, 0xB35DBF821AE4F38B}, // 1e45 +- {0xD50B2037AD200000, 0xE0352F62A19E306E}, // 1e46 +- {0x4526F422CC340000, 0x8C213D9DA502DE45}, // 1e47 +- {0x9670B12B7F410000, 0xAF298D050E4395D6}, // 1e48 +- {0x3C0CDD765F114000, 0xDAF3F04651D47B4C}, // 1e49 +- {0xA5880A69FB6AC800, 0x88D8762BF324CD0F}, // 1e50 +- {0x8EEA0D047A457A00, 0xAB0E93B6EFEE0053}, // 1e51 +- {0x72A4904598D6D880, 0xD5D238A4ABE98068}, // 1e52 +- {0x47A6DA2B7F864750, 0x85A36366EB71F041}, // 1e53 +- {0x999090B65F67D924, 0xA70C3C40A64E6C51}, // 1e54 +- {0xFFF4B4E3F741CF6D, 0xD0CF4B50CFE20765}, // 1e55 +- {0xBFF8F10E7A8921A4, 0x82818F1281ED449F}, // 1e56 +- {0xAFF72D52192B6A0D, 0xA321F2D7226895C7}, // 1e57 +- {0x9BF4F8A69F764490, 0xCBEA6F8CEB02BB39}, // 1e58 +- {0x02F236D04753D5B4, 0xFEE50B7025C36A08}, // 1e59 +- {0x01D762422C946590, 0x9F4F2726179A2245}, // 1e60 +- {0x424D3AD2B7B97EF5, 0xC722F0EF9D80AAD6}, // 1e61 +- {0xD2E0898765A7DEB2, 0xF8EBAD2B84E0D58B}, // 1e62 +- {0x63CC55F49F88EB2F, 0x9B934C3B330C8577}, // 1e63 +- {0x3CBF6B71C76B25FB, 0xC2781F49FFCFA6D5}, // 1e64 +- {0x8BEF464E3945EF7A, 0xF316271C7FC3908A}, // 1e65 +- {0x97758BF0E3CBB5AC, 0x97EDD871CFDA3A56}, // 1e66 +- {0x3D52EEED1CBEA317, 0xBDE94E8E43D0C8EC}, // 1e67 +- {0x4CA7AAA863EE4BDD, 0xED63A231D4C4FB27}, // 1e68 +- {0x8FE8CAA93E74EF6A, 0x945E455F24FB1CF8}, // 1e69 +- {0xB3E2FD538E122B44, 0xB975D6B6EE39E436}, // 1e70 +- {0x60DBBCA87196B616, 0xE7D34C64A9C85D44}, // 1e71 +- {0xBC8955E946FE31CD, 0x90E40FBEEA1D3A4A}, // 1e72 +- {0x6BABAB6398BDBE41, 0xB51D13AEA4A488DD}, // 1e73 +- {0xC696963C7EED2DD1, 0xE264589A4DCDAB14}, // 1e74 +- {0xFC1E1DE5CF543CA2, 0x8D7EB76070A08AEC}, // 1e75 +- {0x3B25A55F43294BCB, 0xB0DE65388CC8ADA8}, // 1e76 +- {0x49EF0EB713F39EBE, 0xDD15FE86AFFAD912}, // 1e77 +- {0x6E3569326C784337, 0x8A2DBF142DFCC7AB}, // 1e78 +- {0x49C2C37F07965404, 0xACB92ED9397BF996}, // 1e79 +- {0xDC33745EC97BE906, 0xD7E77A8F87DAF7FB}, // 1e80 +- {0x69A028BB3DED71A3, 0x86F0AC99B4E8DAFD}, // 1e81 +- {0xC40832EA0D68CE0C, 0xA8ACD7C0222311BC}, // 1e82 +- {0xF50A3FA490C30190, 0xD2D80DB02AABD62B}, // 1e83 +- {0x792667C6DA79E0FA, 0x83C7088E1AAB65DB}, // 1e84 +- {0x577001B891185938, 0xA4B8CAB1A1563F52}, // 1e85 +- {0xED4C0226B55E6F86, 0xCDE6FD5E09ABCF26}, // 1e86 +- {0x544F8158315B05B4, 0x80B05E5AC60B6178}, // 1e87 +- {0x696361AE3DB1C721, 0xA0DC75F1778E39D6}, // 1e88 +- {0x03BC3A19CD1E38E9, 0xC913936DD571C84C}, // 1e89 +- {0x04AB48A04065C723, 0xFB5878494ACE3A5F}, // 1e90 +- {0x62EB0D64283F9C76, 0x9D174B2DCEC0E47B}, // 1e91 +- {0x3BA5D0BD324F8394, 0xC45D1DF942711D9A}, // 1e92 +- {0xCA8F44EC7EE36479, 0xF5746577930D6500}, // 1e93 +- {0x7E998B13CF4E1ECB, 0x9968BF6ABBE85F20}, // 1e94 +- {0x9E3FEDD8C321A67E, 0xBFC2EF456AE276E8}, // 1e95 +- {0xC5CFE94EF3EA101E, 0xEFB3AB16C59B14A2}, // 1e96 +- {0xBBA1F1D158724A12, 0x95D04AEE3B80ECE5}, // 1e97 +- {0x2A8A6E45AE8EDC97, 0xBB445DA9CA61281F}, // 1e98 +- {0xF52D09D71A3293BD, 0xEA1575143CF97226}, // 1e99 +- {0x593C2626705F9C56, 0x924D692CA61BE758}, // 1e100 +- {0x6F8B2FB00C77836C, 0xB6E0C377CFA2E12E}, // 1e101 +- {0x0B6DFB9C0F956447, 0xE498F455C38B997A}, // 1e102 +- {0x4724BD4189BD5EAC, 0x8EDF98B59A373FEC}, // 1e103 +- {0x58EDEC91EC2CB657, 0xB2977EE300C50FE7}, // 1e104 +- {0x2F2967B66737E3ED, 0xDF3D5E9BC0F653E1}, // 1e105 +- {0xBD79E0D20082EE74, 0x8B865B215899F46C}, // 1e106 +- {0xECD8590680A3AA11, 0xAE67F1E9AEC07187}, // 1e107 +- {0xE80E6F4820CC9495, 0xDA01EE641A708DE9}, // 1e108 +- {0x3109058D147FDCDD, 0x884134FE908658B2}, // 1e109 +- {0xBD4B46F0599FD415, 0xAA51823E34A7EEDE}, // 1e110 +- {0x6C9E18AC7007C91A, 0xD4E5E2CDC1D1EA96}, // 1e111 +- {0x03E2CF6BC604DDB0, 0x850FADC09923329E}, // 1e112 +- {0x84DB8346B786151C, 0xA6539930BF6BFF45}, // 1e113 +- {0xE612641865679A63, 0xCFE87F7CEF46FF16}, // 1e114 +- {0x4FCB7E8F3F60C07E, 0x81F14FAE158C5F6E}, // 1e115 +- {0xE3BE5E330F38F09D, 0xA26DA3999AEF7749}, // 1e116 +- {0x5CADF5BFD3072CC5, 0xCB090C8001AB551C}, // 1e117 +- {0x73D9732FC7C8F7F6, 0xFDCB4FA002162A63}, // 1e118 +- {0x2867E7FDDCDD9AFA, 0x9E9F11C4014DDA7E}, // 1e119 +- {0xB281E1FD541501B8, 0xC646D63501A1511D}, // 1e120 +- {0x1F225A7CA91A4226, 0xF7D88BC24209A565}, // 1e121 +- {0x3375788DE9B06958, 0x9AE757596946075F}, // 1e122 +- {0x0052D6B1641C83AE, 0xC1A12D2FC3978937}, // 1e123 +- {0xC0678C5DBD23A49A, 0xF209787BB47D6B84}, // 1e124 +- {0xF840B7BA963646E0, 0x9745EB4D50CE6332}, // 1e125 +- {0xB650E5A93BC3D898, 0xBD176620A501FBFF}, // 1e126 +- {0xA3E51F138AB4CEBE, 0xEC5D3FA8CE427AFF}, // 1e127 +- {0xC66F336C36B10137, 0x93BA47C980E98CDF}, // 1e128 +- {0xB80B0047445D4184, 0xB8A8D9BBE123F017}, // 1e129 +- {0xA60DC059157491E5, 0xE6D3102AD96CEC1D}, // 1e130 +- {0x87C89837AD68DB2F, 0x9043EA1AC7E41392}, // 1e131 +- {0x29BABE4598C311FB, 0xB454E4A179DD1877}, // 1e132 +- {0xF4296DD6FEF3D67A, 0xE16A1DC9D8545E94}, // 1e133 +- {0x1899E4A65F58660C, 0x8CE2529E2734BB1D}, // 1e134 +- {0x5EC05DCFF72E7F8F, 0xB01AE745B101E9E4}, // 1e135 +- {0x76707543F4FA1F73, 0xDC21A1171D42645D}, // 1e136 +- {0x6A06494A791C53A8, 0x899504AE72497EBA}, // 1e137 +- {0x0487DB9D17636892, 0xABFA45DA0EDBDE69}, // 1e138 +- {0x45A9D2845D3C42B6, 0xD6F8D7509292D603}, // 1e139 +- {0x0B8A2392BA45A9B2, 0x865B86925B9BC5C2}, // 1e140 +- {0x8E6CAC7768D7141E, 0xA7F26836F282B732}, // 1e141 +- {0x3207D795430CD926, 0xD1EF0244AF2364FF}, // 1e142 +- {0x7F44E6BD49E807B8, 0x8335616AED761F1F}, // 1e143 +- {0x5F16206C9C6209A6, 0xA402B9C5A8D3A6E7}, // 1e144 +- {0x36DBA887C37A8C0F, 0xCD036837130890A1}, // 1e145 +- {0xC2494954DA2C9789, 0x802221226BE55A64}, // 1e146 +- {0xF2DB9BAA10B7BD6C, 0xA02AA96B06DEB0FD}, // 1e147 +- {0x6F92829494E5ACC7, 0xC83553C5C8965D3D}, // 1e148 +- {0xCB772339BA1F17F9, 0xFA42A8B73ABBF48C}, // 1e149 +- {0xFF2A760414536EFB, 0x9C69A97284B578D7}, // 1e150 +- {0xFEF5138519684ABA, 0xC38413CF25E2D70D}, // 1e151 +- {0x7EB258665FC25D69, 0xF46518C2EF5B8CD1}, // 1e152 +- {0xEF2F773FFBD97A61, 0x98BF2F79D5993802}, // 1e153 +- {0xAAFB550FFACFD8FA, 0xBEEEFB584AFF8603}, // 1e154 +- {0x95BA2A53F983CF38, 0xEEAABA2E5DBF6784}, // 1e155 +- {0xDD945A747BF26183, 0x952AB45CFA97A0B2}, // 1e156 +- {0x94F971119AEEF9E4, 0xBA756174393D88DF}, // 1e157 +- {0x7A37CD5601AAB85D, 0xE912B9D1478CEB17}, // 1e158 +- {0xAC62E055C10AB33A, 0x91ABB422CCB812EE}, // 1e159 +- {0x577B986B314D6009, 0xB616A12B7FE617AA}, // 1e160 +- {0xED5A7E85FDA0B80B, 0xE39C49765FDF9D94}, // 1e161 +- {0x14588F13BE847307, 0x8E41ADE9FBEBC27D}, // 1e162 +- {0x596EB2D8AE258FC8, 0xB1D219647AE6B31C}, // 1e163 +- {0x6FCA5F8ED9AEF3BB, 0xDE469FBD99A05FE3}, // 1e164 +- {0x25DE7BB9480D5854, 0x8AEC23D680043BEE}, // 1e165 +- {0xAF561AA79A10AE6A, 0xADA72CCC20054AE9}, // 1e166 +- {0x1B2BA1518094DA04, 0xD910F7FF28069DA4}, // 1e167 +- {0x90FB44D2F05D0842, 0x87AA9AFF79042286}, // 1e168 +- {0x353A1607AC744A53, 0xA99541BF57452B28}, // 1e169 +- {0x42889B8997915CE8, 0xD3FA922F2D1675F2}, // 1e170 +- {0x69956135FEBADA11, 0x847C9B5D7C2E09B7}, // 1e171 +- {0x43FAB9837E699095, 0xA59BC234DB398C25}, // 1e172 +- {0x94F967E45E03F4BB, 0xCF02B2C21207EF2E}, // 1e173 +- {0x1D1BE0EEBAC278F5, 0x8161AFB94B44F57D}, // 1e174 +- {0x6462D92A69731732, 0xA1BA1BA79E1632DC}, // 1e175 +- {0x7D7B8F7503CFDCFE, 0xCA28A291859BBF93}, // 1e176 +- {0x5CDA735244C3D43E, 0xFCB2CB35E702AF78}, // 1e177 +- {0x3A0888136AFA64A7, 0x9DEFBF01B061ADAB}, // 1e178 +- {0x088AAA1845B8FDD0, 0xC56BAEC21C7A1916}, // 1e179 +- {0x8AAD549E57273D45, 0xF6C69A72A3989F5B}, // 1e180 +- {0x36AC54E2F678864B, 0x9A3C2087A63F6399}, // 1e181 +- {0x84576A1BB416A7DD, 0xC0CB28A98FCF3C7F}, // 1e182 +- {0x656D44A2A11C51D5, 0xF0FDF2D3F3C30B9F}, // 1e183 +- {0x9F644AE5A4B1B325, 0x969EB7C47859E743}, // 1e184 +- {0x873D5D9F0DDE1FEE, 0xBC4665B596706114}, // 1e185 +- {0xA90CB506D155A7EA, 0xEB57FF22FC0C7959}, // 1e186 +- {0x09A7F12442D588F2, 0x9316FF75DD87CBD8}, // 1e187 +- {0x0C11ED6D538AEB2F, 0xB7DCBF5354E9BECE}, // 1e188 +- {0x8F1668C8A86DA5FA, 0xE5D3EF282A242E81}, // 1e189 +- {0xF96E017D694487BC, 0x8FA475791A569D10}, // 1e190 +- {0x37C981DCC395A9AC, 0xB38D92D760EC4455}, // 1e191 +- {0x85BBE253F47B1417, 0xE070F78D3927556A}, // 1e192 +- {0x93956D7478CCEC8E, 0x8C469AB843B89562}, // 1e193 +- {0x387AC8D1970027B2, 0xAF58416654A6BABB}, // 1e194 +- {0x06997B05FCC0319E, 0xDB2E51BFE9D0696A}, // 1e195 +- {0x441FECE3BDF81F03, 0x88FCF317F22241E2}, // 1e196 +- {0xD527E81CAD7626C3, 0xAB3C2FDDEEAAD25A}, // 1e197 +- {0x8A71E223D8D3B074, 0xD60B3BD56A5586F1}, // 1e198 +- {0xF6872D5667844E49, 0x85C7056562757456}, // 1e199 +- {0xB428F8AC016561DB, 0xA738C6BEBB12D16C}, // 1e200 +- {0xE13336D701BEBA52, 0xD106F86E69D785C7}, // 1e201 +- {0xECC0024661173473, 0x82A45B450226B39C}, // 1e202 +- {0x27F002D7F95D0190, 0xA34D721642B06084}, // 1e203 +- {0x31EC038DF7B441F4, 0xCC20CE9BD35C78A5}, // 1e204 +- {0x7E67047175A15271, 0xFF290242C83396CE}, // 1e205 +- {0x0F0062C6E984D386, 0x9F79A169BD203E41}, // 1e206 +- {0x52C07B78A3E60868, 0xC75809C42C684DD1}, // 1e207 +- {0xA7709A56CCDF8A82, 0xF92E0C3537826145}, // 1e208 +- {0x88A66076400BB691, 0x9BBCC7A142B17CCB}, // 1e209 +- {0x6ACFF893D00EA435, 0xC2ABF989935DDBFE}, // 1e210 +- {0x0583F6B8C4124D43, 0xF356F7EBF83552FE}, // 1e211 +- {0xC3727A337A8B704A, 0x98165AF37B2153DE}, // 1e212 +- {0x744F18C0592E4C5C, 0xBE1BF1B059E9A8D6}, // 1e213 +- {0x1162DEF06F79DF73, 0xEDA2EE1C7064130C}, // 1e214 +- {0x8ADDCB5645AC2BA8, 0x9485D4D1C63E8BE7}, // 1e215 +- {0x6D953E2BD7173692, 0xB9A74A0637CE2EE1}, // 1e216 +- {0xC8FA8DB6CCDD0437, 0xE8111C87C5C1BA99}, // 1e217 +- {0x1D9C9892400A22A2, 0x910AB1D4DB9914A0}, // 1e218 +- {0x2503BEB6D00CAB4B, 0xB54D5E4A127F59C8}, // 1e219 +- {0x2E44AE64840FD61D, 0xE2A0B5DC971F303A}, // 1e220 +- {0x5CEAECFED289E5D2, 0x8DA471A9DE737E24}, // 1e221 +- {0x7425A83E872C5F47, 0xB10D8E1456105DAD}, // 1e222 +- {0xD12F124E28F77719, 0xDD50F1996B947518}, // 1e223 +- {0x82BD6B70D99AAA6F, 0x8A5296FFE33CC92F}, // 1e224 +- {0x636CC64D1001550B, 0xACE73CBFDC0BFB7B}, // 1e225 +- {0x3C47F7E05401AA4E, 0xD8210BEFD30EFA5A}, // 1e226 +- {0x65ACFAEC34810A71, 0x8714A775E3E95C78}, // 1e227 +- {0x7F1839A741A14D0D, 0xA8D9D1535CE3B396}, // 1e228 +- {0x1EDE48111209A050, 0xD31045A8341CA07C}, // 1e229 +- {0x934AED0AAB460432, 0x83EA2B892091E44D}, // 1e230 +- {0xF81DA84D5617853F, 0xA4E4B66B68B65D60}, // 1e231 +- {0x36251260AB9D668E, 0xCE1DE40642E3F4B9}, // 1e232 +- {0xC1D72B7C6B426019, 0x80D2AE83E9CE78F3}, // 1e233 +- {0xB24CF65B8612F81F, 0xA1075A24E4421730}, // 1e234 +- {0xDEE033F26797B627, 0xC94930AE1D529CFC}, // 1e235 +- {0x169840EF017DA3B1, 0xFB9B7CD9A4A7443C}, // 1e236 +- {0x8E1F289560EE864E, 0x9D412E0806E88AA5}, // 1e237 +- {0xF1A6F2BAB92A27E2, 0xC491798A08A2AD4E}, // 1e238 +- {0xAE10AF696774B1DB, 0xF5B5D7EC8ACB58A2}, // 1e239 +- {0xACCA6DA1E0A8EF29, 0x9991A6F3D6BF1765}, // 1e240 +- {0x17FD090A58D32AF3, 0xBFF610B0CC6EDD3F}, // 1e241 +- {0xDDFC4B4CEF07F5B0, 0xEFF394DCFF8A948E}, // 1e242 +- {0x4ABDAF101564F98E, 0x95F83D0A1FB69CD9}, // 1e243 +- {0x9D6D1AD41ABE37F1, 0xBB764C4CA7A4440F}, // 1e244 +- {0x84C86189216DC5ED, 0xEA53DF5FD18D5513}, // 1e245 +- {0x32FD3CF5B4E49BB4, 0x92746B9BE2F8552C}, // 1e246 +- {0x3FBC8C33221DC2A1, 0xB7118682DBB66A77}, // 1e247 +- {0x0FABAF3FEAA5334A, 0xE4D5E82392A40515}, // 1e248 +- {0x29CB4D87F2A7400E, 0x8F05B1163BA6832D}, // 1e249 +- {0x743E20E9EF511012, 0xB2C71D5BCA9023F8}, // 1e250 +- {0x914DA9246B255416, 0xDF78E4B2BD342CF6}, // 1e251 +- {0x1AD089B6C2F7548E, 0x8BAB8EEFB6409C1A}, // 1e252 +- {0xA184AC2473B529B1, 0xAE9672ABA3D0C320}, // 1e253 +- {0xC9E5D72D90A2741E, 0xDA3C0F568CC4F3E8}, // 1e254 +- {0x7E2FA67C7A658892, 0x8865899617FB1871}, // 1e255 +- {0xDDBB901B98FEEAB7, 0xAA7EEBFB9DF9DE8D}, // 1e256 +- {0x552A74227F3EA565, 0xD51EA6FA85785631}, // 1e257 +- {0xD53A88958F87275F, 0x8533285C936B35DE}, // 1e258 +- {0x8A892ABAF368F137, 0xA67FF273B8460356}, // 1e259 +- {0x2D2B7569B0432D85, 0xD01FEF10A657842C}, // 1e260 +- {0x9C3B29620E29FC73, 0x8213F56A67F6B29B}, // 1e261 +- {0x8349F3BA91B47B8F, 0xA298F2C501F45F42}, // 1e262 +- {0x241C70A936219A73, 0xCB3F2F7642717713}, // 1e263 +- {0xED238CD383AA0110, 0xFE0EFB53D30DD4D7}, // 1e264 +- {0xF4363804324A40AA, 0x9EC95D1463E8A506}, // 1e265 +- {0xB143C6053EDCD0D5, 0xC67BB4597CE2CE48}, // 1e266 +- {0xDD94B7868E94050A, 0xF81AA16FDC1B81DA}, // 1e267 +- {0xCA7CF2B4191C8326, 0x9B10A4E5E9913128}, // 1e268 +- {0xFD1C2F611F63A3F0, 0xC1D4CE1F63F57D72}, // 1e269 +- {0xBC633B39673C8CEC, 0xF24A01A73CF2DCCF}, // 1e270 +- {0xD5BE0503E085D813, 0x976E41088617CA01}, // 1e271 +- {0x4B2D8644D8A74E18, 0xBD49D14AA79DBC82}, // 1e272 +- {0xDDF8E7D60ED1219E, 0xEC9C459D51852BA2}, // 1e273 +- {0xCABB90E5C942B503, 0x93E1AB8252F33B45}, // 1e274 +- {0x3D6A751F3B936243, 0xB8DA1662E7B00A17}, // 1e275 +- {0x0CC512670A783AD4, 0xE7109BFBA19C0C9D}, // 1e276 +- {0x27FB2B80668B24C5, 0x906A617D450187E2}, // 1e277 +- {0xB1F9F660802DEDF6, 0xB484F9DC9641E9DA}, // 1e278 +- {0x5E7873F8A0396973, 0xE1A63853BBD26451}, // 1e279 +- {0xDB0B487B6423E1E8, 0x8D07E33455637EB2}, // 1e280 +- {0x91CE1A9A3D2CDA62, 0xB049DC016ABC5E5F}, // 1e281 +- {0x7641A140CC7810FB, 0xDC5C5301C56B75F7}, // 1e282 +- {0xA9E904C87FCB0A9D, 0x89B9B3E11B6329BA}, // 1e283 +- {0x546345FA9FBDCD44, 0xAC2820D9623BF429}, // 1e284 +- {0xA97C177947AD4095, 0xD732290FBACAF133}, // 1e285 +- {0x49ED8EABCCCC485D, 0x867F59A9D4BED6C0}, // 1e286 +- {0x5C68F256BFFF5A74, 0xA81F301449EE8C70}, // 1e287 +- {0x73832EEC6FFF3111, 0xD226FC195C6A2F8C}, // 1e288 +-}; ++// ---------------- Auxiliary - JSON + +-// wuffs_base__private_implementation__f64_powers_of_10 holds powers of 10 that +-// can be exactly represented by a float64 (what C calls a double). +-static const double wuffs_base__private_implementation__f64_powers_of_10[23] = { +- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, +- 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, ++namespace wuffs_aux { ++ ++struct DecodeJsonResult { ++ DecodeJsonResult(std::string&& error_message0, uint64_t cursor_position0); ++ ++ std::string error_message; ++ uint64_t cursor_position; + }; + +-// ---------------- IEEE 754 Floating Point ++class DecodeJsonCallbacks { ++ public: ++ virtual ~DecodeJsonCallbacks(); + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16 // +-wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f) { +- uint64_t u = 0; +- if (sizeof(uint64_t) == sizeof(double)) { +- memcpy(&u, &f, sizeof(uint64_t)); +- } +- uint16_t neg = ((uint16_t)((u >> 63) << 15)); +- u &= 0x7FFFFFFFFFFFFFFF; +- uint64_t exp = u >> 52; +- uint64_t man = u & 0x000FFFFFFFFFFFFF; ++ // AppendXxx are called for leaf nodes: literals, numbers and strings. For ++ // strings, the Callbacks implementation is responsible for tracking map keys ++ // versus other values. + +- if (exp == 0x7FF) { +- if (man == 0) { // Infinity. +- wuffs_base__lossy_value_u16 ret; +- ret.value = neg | 0x7C00; +- ret.lossy = false; +- return ret; +- } +- // NaN. Shift the 52 mantissa bits to 10 mantissa bits, keeping the most +- // significant mantissa bit (quiet vs signaling NaNs). Also set the low 9 +- // bits of ret.value so that the 10-bit mantissa is non-zero. +- wuffs_base__lossy_value_u16 ret; +- ret.value = neg | 0x7DFF | ((uint16_t)(man >> 42)); +- ret.lossy = false; +- return ret; ++ virtual std::string AppendNull() = 0; ++ virtual std::string AppendBool(bool val) = 0; ++ virtual std::string AppendF64(double val) = 0; ++ virtual std::string AppendI64(int64_t val) = 0; ++ virtual std::string AppendTextString(std::string&& val) = 0; + +- } else if (exp > 0x40E) { // Truncate to the largest finite f16. +- wuffs_base__lossy_value_u16 ret; +- ret.value = neg | 0x7BFF; +- ret.lossy = true; +- return ret; ++ // Push and Pop are called for container nodes: JSON arrays (lists) and JSON ++ // objects (dictionaries). ++ // ++ // The flags bits combine exactly one of: ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT ++ // and exactly one of: ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST ++ // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT + +- } else if (exp <= 0x3E6) { // Truncate to zero. +- wuffs_base__lossy_value_u16 ret; +- ret.value = neg; +- ret.lossy = (u != 0); +- return ret; ++ virtual std::string Push(uint32_t flags) = 0; ++ virtual std::string Pop(uint32_t flags) = 0; + +- } else if (exp <= 0x3F0) { // Normal f64, subnormal f16. +- // Convert from a 53-bit mantissa (after realizing the implicit bit) to a +- // 10-bit mantissa and then adjust for the exponent. +- man |= 0x0010000000000000; +- uint32_t shift = ((uint32_t)(1051 - exp)); // 1051 = 0x3F0 + 53 - 10. +- uint64_t shifted_man = man >> shift; +- wuffs_base__lossy_value_u16 ret; +- ret.value = neg | ((uint16_t)shifted_man); +- ret.lossy = (shifted_man << shift) != man; +- return ret; +- } ++ // Done is always the last Callback method called by DecodeJson, whether or ++ // not parsing the input as JSON encountered an error. Even when successful, ++ // trailing data may remain in input and buffer. See "Unintuitive JSON ++ // Parsing" (https://nullprogram.com/blog/2019/12/28/) which discusses JSON ++ // parsing and when it stops. ++ // ++ // Do not keep a reference to buffer or buffer.data.ptr after Done returns, ++ // as DecodeJson may then de-allocate the backing array. ++ // ++ // The default Done implementation is a no-op. ++ virtual void // ++ Done(DecodeJsonResult& result, sync_io::Input& input, IOBuffer& buffer); ++}; + +- // Normal f64, normal f16. ++extern const char DecodeJson_BadJsonPointer[]; ++extern const char DecodeJson_NoMatch[]; + +- // Re-bias from 1023 to 15 and shift above f16's 10 mantissa bits. +- exp = (exp - 1008) << 10; // 1008 = 1023 - 15 = 0x3FF - 0xF. ++// The FooArgBar types add structure to Foo's optional arguments. They wrap ++// inner representations for several reasons: ++// - It provides a home for the DefaultValue static method, for Foo callers ++// that want to override some but not all optional arguments. ++// - It provides the "Bar" name at Foo call sites, which can help self- ++// document Foo calls with many arguemnts. ++// - It provides some type safety against accidentally transposing or omitting ++// adjacent fundamentally-numeric-typed optional arguments. + +- // Convert from a 52-bit mantissa (excluding the implicit bit) to a 10-bit +- // mantissa (again excluding the implicit bit). We lose some information if +- // any of the bottom 42 bits are non-zero. +- wuffs_base__lossy_value_u16 ret; +- ret.value = neg | ((uint16_t)exp) | ((uint16_t)(man >> 42)); +- ret.lossy = (man << 22) != 0; +- return ret; +-} ++// DecodeJsonArgQuirks wraps an optional argument to DecodeJson. ++struct DecodeJsonArgQuirks { ++ explicit DecodeJsonArgQuirks(const QuirkKeyValuePair* ptr0, ++ const size_t len0); + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32 // +-wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f) { +- uint64_t u = 0; +- if (sizeof(uint64_t) == sizeof(double)) { +- memcpy(&u, &f, sizeof(uint64_t)); +- } +- uint32_t neg = ((uint32_t)(u >> 63)) << 31; +- u &= 0x7FFFFFFFFFFFFFFF; +- uint64_t exp = u >> 52; +- uint64_t man = u & 0x000FFFFFFFFFFFFF; ++ // DefaultValue returns an empty slice. ++ static DecodeJsonArgQuirks DefaultValue(); + +- if (exp == 0x7FF) { +- if (man == 0) { // Infinity. +- wuffs_base__lossy_value_u32 ret; +- ret.value = neg | 0x7F800000; +- ret.lossy = false; +- return ret; +- } +- // NaN. Shift the 52 mantissa bits to 23 mantissa bits, keeping the most +- // significant mantissa bit (quiet vs signaling NaNs). Also set the low 22 +- // bits of ret.value so that the 23-bit mantissa is non-zero. +- wuffs_base__lossy_value_u32 ret; +- ret.value = neg | 0x7FBFFFFF | ((uint32_t)(man >> 29)); +- ret.lossy = false; +- return ret; ++ const QuirkKeyValuePair* ptr; ++ const size_t len; ++}; + +- } else if (exp > 0x47E) { // Truncate to the largest finite f32. +- wuffs_base__lossy_value_u32 ret; +- ret.value = neg | 0x7F7FFFFF; +- ret.lossy = true; +- return ret; ++// DecodeJsonArgJsonPointer wraps an optional argument to DecodeJson. ++struct DecodeJsonArgJsonPointer { ++ explicit DecodeJsonArgJsonPointer(std::string repr0); + +- } else if (exp <= 0x369) { // Truncate to zero. +- wuffs_base__lossy_value_u32 ret; +- ret.value = neg; +- ret.lossy = (u != 0); +- return ret; ++ // DefaultValue returns an empty string. ++ static DecodeJsonArgJsonPointer DefaultValue(); + +- } else if (exp <= 0x380) { // Normal f64, subnormal f32. +- // Convert from a 53-bit mantissa (after realizing the implicit bit) to a +- // 23-bit mantissa and then adjust for the exponent. +- man |= 0x0010000000000000; +- uint32_t shift = ((uint32_t)(926 - exp)); // 926 = 0x380 + 53 - 23. +- uint64_t shifted_man = man >> shift; +- wuffs_base__lossy_value_u32 ret; +- ret.value = neg | ((uint32_t)shifted_man); +- ret.lossy = (shifted_man << shift) != man; +- return ret; +- } ++ std::string repr; ++}; + +- // Normal f64, normal f32. ++// DecodeJson calls callbacks based on the JSON-formatted data in input. ++// ++// On success, the returned error_message is empty and cursor_position counts ++// the number of bytes consumed. On failure, error_message is non-empty and ++// cursor_position is the location of the error. That error may be a content ++// error (invalid JSON) or an input error (e.g. network failure). ++// ++// json_pointer is a query in the JSON Pointer (RFC 6901) syntax. The callbacks ++// run for the input's sub-node that matches the query. DecodeJson_NoMatch is ++// returned if no matching sub-node was found. The empty query matches the ++// input's root node, consistent with JSON Pointer semantics. ++// ++// The JSON Pointer implementation is greedy: duplicate keys are not rejected ++// but only the first match for each '/'-separated fragment is followed. ++DecodeJsonResult // ++DecodeJson(DecodeJsonCallbacks& callbacks, ++ sync_io::Input& input, ++ DecodeJsonArgQuirks quirks = DecodeJsonArgQuirks::DefaultValue(), ++ DecodeJsonArgJsonPointer json_pointer = ++ DecodeJsonArgJsonPointer::DefaultValue()); + +- // Re-bias from 1023 to 127 and shift above f32's 23 mantissa bits. +- exp = (exp - 896) << 23; // 896 = 1023 - 127 = 0x3FF - 0x7F. ++} // namespace wuffs_aux + +- // Convert from a 52-bit mantissa (excluding the implicit bit) to a 23-bit +- // mantissa (again excluding the implicit bit). We lose some information if +- // any of the bottom 29 bits are non-zero. +- wuffs_base__lossy_value_u32 ret; +- ret.value = neg | ((uint32_t)exp) | ((uint32_t)(man >> 29)); +- ret.lossy = (man << 35) != 0; +- return ret; +-} ++#endif // defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +-// -------- ++// ‼ WUFFS C HEADER ENDS HERE. ++#ifdef WUFFS_IMPLEMENTATION + +-#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 2047 +-#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 800 ++#ifdef __cplusplus ++extern "C" { ++#endif + +-// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL is the largest N +-// such that ((10 << N) < (1 << 64)). +-#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL 60 ++// ---------------- Fundamentals + +-// wuffs_base__private_implementation__high_prec_dec (abbreviated as HPD) is a +-// fixed precision floating point decimal number, augmented with ±infinity +-// values, but it cannot represent NaN (Not a Number). ++// WUFFS_BASE__MAGIC is a magic number to check that initializers are called. ++// It's not foolproof, given C doesn't automatically zero memory before use, ++// but it should catch 99.99% of cases. + // +-// "High precision" means that the mantissa holds 800 decimal digits. 800 is +-// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION. ++// Its (non-zero) value is arbitrary, based on md5sum("wuffs"). ++#define WUFFS_BASE__MAGIC ((uint32_t)0x3CCB6C71) ++ ++// WUFFS_BASE__DISABLED is a magic number to indicate that a non-recoverable ++// error was previously encountered. + // +-// An HPD isn't for general purpose arithmetic, only for conversions to and +-// from IEEE 754 double-precision floating point, where the largest and +-// smallest positive, finite values are approximately 1.8e+308 and 4.9e-324. +-// HPD exponents above +2047 mean infinity, below -2047 mean zero. The ±2047 +-// bounds are further away from zero than ±(324 + 800), where 800 and 2047 is +-// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION and +-// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE. ++// Its (non-zero) value is arbitrary, based on md5sum("disabled"). ++#define WUFFS_BASE__DISABLED ((uint32_t)0x075AE3D2) ++ ++// Use switch cases for coroutine suspension points, similar to the technique ++// in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html + // +-// digits[.. num_digits] are the number's digits in big-endian order. The +-// uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7' +-// is the ASCII value 0x37. ++// The implicit fallthrough is intentional. + // +-// decimal_point is the index (within digits) of the decimal point. It may be +-// negative or be larger than num_digits, in which case the explicit digits are +-// padded with implicit zeroes. ++// We use trivial macros instead of an explicit assignment and case statement ++// so that clang-format doesn't get confused by the unusual "case"s. ++#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0 case 0:; ++#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT(n) \ ++ coro_susp_point = n; \ ++ case n:; ++ ++#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \ ++ if (!status.repr) { \ ++ goto ok; \ ++ } else if (*status.repr != '$') { \ ++ goto exit; \ ++ } \ ++ coro_susp_point = n; \ ++ goto suspend; \ ++ case n:; ++ ++// The "defined(__clang__)" isn't redundant. While vanilla clang defines ++// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not. ++#if defined(__GNUC__) || defined(__clang__) ++#define WUFFS_BASE__LIKELY(expr) (__builtin_expect(!!(expr), 1)) ++#define WUFFS_BASE__UNLIKELY(expr) (__builtin_expect(!!(expr), 0)) ++#else ++#define WUFFS_BASE__LIKELY(expr) (expr) ++#define WUFFS_BASE__UNLIKELY(expr) (expr) ++#endif ++ ++// -------- ++ ++static inline wuffs_base__empty_struct // ++wuffs_private_impl__ignore_status(wuffs_base__status z) { ++ return wuffs_base__make_empty_struct(); ++} ++ ++static inline wuffs_base__status // ++wuffs_private_impl__status__ensure_not_a_suspension(wuffs_base__status z) { ++ if (z.repr && (*z.repr == '$')) { ++ z.repr = wuffs_base__error__cannot_return_a_suspension; ++ } ++ return z; ++} ++ ++// -------- ++ ++// wuffs_private_impl__iterate_total_advance returns the exclusive ++// pointer-offset at which iteration should stop. The overall slice has length ++// total_len, each iteration's sub-slice has length iter_len and are placed ++// iter_advance apart. + // +-// For example, if num_digits is 3 and digits is "\x07\x08\x09": +-// - A decimal_point of -2 means ".00789" +-// - A decimal_point of -1 means ".0789" +-// - A decimal_point of +0 means ".789" +-// - A decimal_point of +1 means "7.89" +-// - A decimal_point of +2 means "78.9" +-// - A decimal_point of +3 means "789." +-// - A decimal_point of +4 means "7890." +-// - A decimal_point of +5 means "78900." ++// The iter_advance may not be larger than iter_len. The iter_advance may be ++// smaller than iter_len, in which case the sub-slices will overlap. + // +-// As above, a decimal_point higher than +2047 means that the overall value is +-// infinity, lower than -2047 means zero. ++// The return value r satisfies ((0 <= r) && (r <= total_len)). + // +-// negative is a sign bit. An HPD can distinguish positive and negative zero. ++// For example, if total_len = 15, iter_len = 5 and iter_advance = 3, there are ++// four iterations at offsets 0, 3, 6 and 9. This function returns 12. + // +-// truncated is whether there are more than +-// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION digits, and at +-// least one of those extra digits are non-zero. The existence of long-tail +-// digits can affect rounding. ++// 0123456789012345 ++// [....] ++// [....] ++// [....] ++// [....] ++// $ ++// 0123456789012345 + // +-// The "all fields are zero" value is valid, and represents the number +0. +-typedef struct wuffs_base__private_implementation__high_prec_dec__struct { +- uint32_t num_digits; +- int32_t decimal_point; +- bool negative; +- bool truncated; +- uint8_t digits[WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION]; +-} wuffs_base__private_implementation__high_prec_dec; +- +-// wuffs_base__private_implementation__high_prec_dec__trim trims trailing +-// zeroes from the h->digits[.. h->num_digits] slice. They have no benefit, +-// since we explicitly track h->decimal_point. ++// For example, if total_len = 15, iter_len = 5 and iter_advance = 5, there are ++// three iterations at offsets 0, 5 and 10. This function returns 15. + // +-// Preconditions: +-// - h is non-NULL. +-static inline void // +-wuffs_base__private_implementation__high_prec_dec__trim( +- wuffs_base__private_implementation__high_prec_dec* h) { +- while ((h->num_digits > 0) && (h->digits[h->num_digits - 1] == 0)) { +- h->num_digits--; ++// 0123456789012345 ++// [....] ++// [....] ++// [....] ++// $ ++// 0123456789012345 ++static inline size_t // ++wuffs_private_impl__iterate_total_advance(size_t total_len, ++ size_t iter_len, ++ size_t iter_advance) { ++ if (total_len >= iter_len) { ++ size_t n = total_len - iter_len; ++ return ((n / iter_advance) * iter_advance) + iter_advance; + } ++ return 0; + } + +-// wuffs_base__private_implementation__high_prec_dec__assign sets h to +-// represent the number x. +-// +-// Preconditions: +-// - h is non-NULL. +-static void // +-wuffs_base__private_implementation__high_prec_dec__assign( +- wuffs_base__private_implementation__high_prec_dec* h, +- uint64_t x, +- bool negative) { +- uint32_t n = 0; ++// ---------------- Numeric Types + +- // Set h->digits. +- if (x > 0) { +- // Calculate the digits, working right-to-left. After we determine n (how +- // many digits there are), copy from buf to h->digits. +- // +- // UINT64_MAX, 18446744073709551615, is 20 digits long. It can be faster to +- // copy a constant number of bytes than a variable number (20 instead of +- // n). Make buf large enough (and start writing to it from the middle) so +- // that can we always copy 20 bytes: the slice buf[(20-n) .. (40-n)]. +- uint8_t buf[40] = {0}; +- uint8_t* ptr = &buf[20]; +- do { +- uint64_t remaining = x / 10; +- x -= remaining * 10; +- ptr--; +- *ptr = (uint8_t)x; +- n++; +- x = remaining; +- } while (x > 0); +- memcpy(h->digits, ptr, 20); +- } ++extern const uint8_t wuffs_private_impl__low_bits_mask__u8[8]; ++extern const uint16_t wuffs_private_impl__low_bits_mask__u16[16]; ++extern const uint32_t wuffs_private_impl__low_bits_mask__u32[32]; ++extern const uint64_t wuffs_private_impl__low_bits_mask__u64[64]; + +- // Set h's other fields. +- h->num_digits = n; +- h->decimal_point = (int32_t)n; +- h->negative = negative; +- h->truncated = false; +- wuffs_base__private_implementation__high_prec_dec__trim(h); ++#define WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U8(n) \ ++ (wuffs_private_impl__low_bits_mask__u8[n]) ++#define WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U16(n) \ ++ (wuffs_private_impl__low_bits_mask__u16[n]) ++#define WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(n) \ ++ (wuffs_private_impl__low_bits_mask__u32[n]) ++#define WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U64(n) \ ++ (wuffs_private_impl__low_bits_mask__u64[n]) ++ ++// -------- ++ ++static inline void // ++wuffs_private_impl__u8__sat_add_indirect(uint8_t* x, uint8_t y) { ++ *x = wuffs_base__u8__sat_add(*x, y); + } + +-static wuffs_base__status // +-wuffs_base__private_implementation__high_prec_dec__parse( +- wuffs_base__private_implementation__high_prec_dec* h, +- wuffs_base__slice_u8 s, +- uint32_t options) { +- if (!h) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- h->num_digits = 0; +- h->decimal_point = 0; +- h->negative = false; +- h->truncated = false; ++static inline void // ++wuffs_private_impl__u8__sat_sub_indirect(uint8_t* x, uint8_t y) { ++ *x = wuffs_base__u8__sat_sub(*x, y); ++} + +- uint8_t* p = s.ptr; +- uint8_t* q = s.ptr + s.len; ++static inline void // ++wuffs_private_impl__u16__sat_add_indirect(uint16_t* x, uint16_t y) { ++ *x = wuffs_base__u16__sat_add(*x, y); ++} + +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { +- for (;; p++) { +- if (p >= q) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } else if (*p != '_') { +- break; +- } +- } +- } ++static inline void // ++wuffs_private_impl__u16__sat_sub_indirect(uint16_t* x, uint16_t y) { ++ *x = wuffs_base__u16__sat_sub(*x, y); ++} + +- // Parse sign. +- do { +- if (*p == '+') { +- p++; +- } else if (*p == '-') { +- h->negative = true; +- p++; +- } else { +- break; +- } +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { +- for (;; p++) { +- if (p >= q) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } else if (*p != '_') { +- break; +- } +- } +- } +- } while (0); ++static inline void // ++wuffs_private_impl__u32__sat_add_indirect(uint32_t* x, uint32_t y) { ++ *x = wuffs_base__u32__sat_add(*x, y); ++} + +- // Parse digits, up to (and including) a '.', 'E' or 'e'. Examples for each +- // limb in this if-else chain: +- // - "0.789" +- // - "1002.789" +- // - ".789" +- // - Other (invalid input). +- uint32_t nd = 0; +- int32_t dp = 0; +- bool no_digits_before_separator = false; +- if (('0' == *p) && +- !(options & +- WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES)) { +- p++; +- for (;; p++) { +- if (p >= q) { +- goto after_all; +- } else if (*p == +- ((options & +- WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) +- ? ',' +- : '.')) { +- p++; +- goto after_sep; +- } else if ((*p == 'E') || (*p == 'e')) { +- p++; +- goto after_exp; +- } else if ((*p != '_') || +- !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- } ++static inline void // ++wuffs_private_impl__u32__sat_sub_indirect(uint32_t* x, uint32_t y) { ++ *x = wuffs_base__u32__sat_sub(*x, y); ++} + +- } else if (('0' <= *p) && (*p <= '9')) { +- if (*p == '0') { +- for (; (p < q) && (*p == '0'); p++) { +- } +- } else { +- h->digits[nd++] = (uint8_t)(*p - '0'); +- dp = (int32_t)nd; +- p++; +- } ++static inline void // ++wuffs_private_impl__u64__sat_add_indirect(uint64_t* x, uint64_t y) { ++ *x = wuffs_base__u64__sat_add(*x, y); ++} + +- for (;; p++) { +- if (p >= q) { +- goto after_all; +- } else if (('0' <= *p) && (*p <= '9')) { +- if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { +- h->digits[nd++] = (uint8_t)(*p - '0'); +- dp = (int32_t)nd; +- } else if ('0' != *p) { +- // Long-tail non-zeroes set the truncated bit. +- h->truncated = true; +- } +- } else if (*p == +- ((options & +- WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) +- ? ',' +- : '.')) { +- p++; +- goto after_sep; +- } else if ((*p == 'E') || (*p == 'e')) { +- p++; +- goto after_exp; +- } else if ((*p != '_') || +- !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- } ++static inline void // ++wuffs_private_impl__u64__sat_sub_indirect(uint64_t* x, uint64_t y) { ++ *x = wuffs_base__u64__sat_sub(*x, y); ++} + +- } else if (*p == ((options & +- WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) +- ? ',' +- : '.')) { +- p++; +- no_digits_before_separator = true; ++// ---------------- Numeric Types (Utility) + +- } else { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } ++#define wuffs_base__utility__sign_extend_convert_u8_u32(a) \ ++ ((uint32_t)(int32_t)(int8_t)(a)) + +-after_sep: +- for (;; p++) { +- if (p >= q) { +- goto after_all; +- } else if ('0' == *p) { +- if (nd == 0) { +- // Track leading zeroes implicitly. +- dp--; +- } else if (nd < +- WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { +- h->digits[nd++] = (uint8_t)(*p - '0'); +- } +- } else if (('0' < *p) && (*p <= '9')) { +- if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { +- h->digits[nd++] = (uint8_t)(*p - '0'); +- } else { +- // Long-tail non-zeroes set the truncated bit. +- h->truncated = true; +- } +- } else if ((*p == 'E') || (*p == 'e')) { +- p++; +- goto after_exp; +- } else if ((*p != '_') || +- !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- } ++#define wuffs_base__utility__sign_extend_convert_u16_u32(a) \ ++ ((uint32_t)(int32_t)(int16_t)(a)) + +-after_exp: +- do { +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { +- for (;; p++) { +- if (p >= q) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } else if (*p != '_') { +- break; +- } +- } +- } ++#define wuffs_base__utility__sign_extend_rshift_u32(a, n) \ ++ ((uint32_t)(((int32_t)(a)) >> (n))) + +- int32_t exp_sign = +1; +- if (*p == '+') { +- p++; +- } else if (*p == '-') { +- exp_sign = -1; +- p++; +- } ++#define wuffs_base__utility__sign_extend_rshift_u64(a, n) \ ++ ((uint64_t)(((int64_t)(a)) >> (n))) + +- int32_t exp = 0; +- const int32_t exp_large = +- WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + +- WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION; +- bool saw_exp_digits = false; +- for (; p < q; p++) { +- if ((*p == '_') && +- (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { +- // No-op. +- } else if (('0' <= *p) && (*p <= '9')) { +- saw_exp_digits = true; +- if (exp < exp_large) { +- exp = (10 * exp) + ((int32_t)(*p - '0')); +- } +- } else { +- break; +- } +- } +- if (!saw_exp_digits) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- dp += exp_sign * exp; +- } while (0); ++#define wuffs_base__utility__make_bitvec256(e00, e01, e02, e03) \ ++ wuffs_base__make_bitvec256(e00, e01, e02, e03) + +-after_all: +- if (p != q) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- h->num_digits = nd; +- if (nd == 0) { +- if (no_digits_before_separator) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- h->decimal_point = 0; +- } else if (dp < +- -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { +- h->decimal_point = +- -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE - 1; +- } else if (dp > +- +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { +- h->decimal_point = +- +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + 1; +- } else { +- h->decimal_point = dp; +- } +- wuffs_base__private_implementation__high_prec_dec__trim(h); +- return wuffs_base__make_status(NULL); +-} ++#define wuffs_base__utility__make_optional_u63(h, v) \ ++ wuffs_base__make_optional_u63(h, v) + +-// -------- ++// ---------------- Slices and Tables + +-// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits +-// returns the number of additional decimal digits when left-shifting by shift. ++// This function basically returns (ptr + len), except that that expression is ++// Undefined Behavior in C (but not C++) when ptr is NULL, even if len is zero. + // +-// See below for preconditions. +-static uint32_t // +-wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits( +- wuffs_base__private_implementation__high_prec_dec* h, +- uint32_t shift) { +- // Masking with 0x3F should be unnecessary (assuming the preconditions) but +- // it's cheap and ensures that we don't overflow the +- // wuffs_base__private_implementation__hpd_left_shift array. +- shift &= 63; ++// Precondition: (ptr != NULL) || (len == 0). ++static inline const uint8_t* // ++wuffs_private_impl__ptr_u8_plus_len(const uint8_t* ptr, size_t len) { ++ return ptr ? (ptr + len) : NULL; ++} + +- uint32_t x_a = wuffs_base__private_implementation__hpd_left_shift[shift]; +- uint32_t x_b = wuffs_base__private_implementation__hpd_left_shift[shift + 1]; +- uint32_t num_new_digits = x_a >> 11; +- uint32_t pow5_a = 0x7FF & x_a; +- uint32_t pow5_b = 0x7FF & x_b; ++// -------- + +- const uint8_t* pow5 = +- &wuffs_base__private_implementation__powers_of_5[pow5_a]; +- uint32_t i = 0; +- uint32_t n = pow5_b - pow5_a; +- for (; i < n; i++) { +- if (i >= h->num_digits) { +- return num_new_digits - 1; +- } else if (h->digits[i] == pow5[i]) { +- continue; +- } else if (h->digits[i] < pow5[i]) { +- return num_new_digits - 1; +- } else { +- return num_new_digits; +- } ++// wuffs_private_impl__slice_u8__prefix returns up to the first up_to bytes of ++// s. ++static inline wuffs_base__slice_u8 // ++wuffs_private_impl__slice_u8__prefix(wuffs_base__slice_u8 s, uint64_t up_to) { ++ if (((uint64_t)(s.len)) > up_to) { ++ s.len = ((size_t)up_to); + } +- return num_new_digits; ++ return s; + } + +-// -------- ++// wuffs_private_impl__slice_u8__suffix returns up to the last up_to bytes of ++// s. ++static inline wuffs_base__slice_u8 // ++wuffs_private_impl__slice_u8__suffix(wuffs_base__slice_u8 s, uint64_t up_to) { ++ if (((uint64_t)(s.len)) > up_to) { ++ s.ptr += ((uint64_t)(s.len)) - up_to; ++ s.len = ((size_t)up_to); ++ } ++ return s; ++} + +-// wuffs_base__private_implementation__high_prec_dec__rounded_integer returns +-// the integral (non-fractional) part of h, provided that it is 18 or fewer +-// decimal digits. For 19 or more digits, it returns UINT64_MAX. Note that: +-// - (1 << 53) is 9007199254740992, which has 16 decimal digits. +-// - (1 << 56) is 72057594037927936, which has 17 decimal digits. +-// - (1 << 59) is 576460752303423488, which has 18 decimal digits. +-// - (1 << 63) is 9223372036854775808, which has 19 decimal digits. +-// and that IEEE 754 double precision has 52 mantissa bits. ++// wuffs_private_impl__slice_u8__copy_from_slice calls memmove(dst.ptr, ++// src.ptr, len) where len is the minimum of dst.len and src.len. + // +-// That integral part is rounded-to-even: rounding 7.5 or 8.5 both give 8. +-// +-// h's negative bit is ignored: rounding -8.6 returns 9. +-// +-// See below for preconditions. +-static uint64_t // +-wuffs_base__private_implementation__high_prec_dec__rounded_integer( +- wuffs_base__private_implementation__high_prec_dec* h) { +- if ((h->num_digits == 0) || (h->decimal_point < 0)) { +- return 0; +- } else if (h->decimal_point > 18) { +- return UINT64_MAX; ++// Passing a wuffs_base__slice_u8 with all fields NULL or zero (a valid, empty ++// slice) is valid and results in a no-op. ++static inline uint64_t // ++wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 src) { ++ size_t len = dst.len < src.len ? dst.len : src.len; ++ if (len > 0) { ++ memmove(dst.ptr, src.ptr, len); + } ++ return len; ++} + +- uint32_t dp = (uint32_t)(h->decimal_point); +- uint64_t n = 0; +- uint32_t i = 0; +- for (; i < dp; i++) { +- n = (10 * n) + ((i < h->num_digits) ? h->digits[i] : 0); ++static inline wuffs_base__empty_struct // ++wuffs_private_impl__bulk_load_host_endian(void* ptr, ++ size_t len, ++ wuffs_base__slice_u8 src) { ++ if (len && (len <= src.len)) { ++ memmove(ptr, src.ptr, len); + } ++ return wuffs_base__make_empty_struct(); ++} + +- bool round_up = false; +- if (dp < h->num_digits) { +- round_up = h->digits[dp] >= 5; +- if ((h->digits[dp] == 5) && (dp + 1 == h->num_digits)) { +- // We are exactly halfway. If we're truncated, round up, otherwise round +- // to even. +- round_up = h->truncated || // +- ((dp > 0) && (1 & h->digits[dp - 1])); +- } +- } +- if (round_up) { +- n++; ++static inline wuffs_base__empty_struct // ++wuffs_private_impl__bulk_memset(void* ptr, size_t len, uint8_t byte_value) { ++ if (len) { ++ memset(ptr, byte_value, len); + } ++ return wuffs_base__make_empty_struct(); ++} + +- return n; ++static inline wuffs_base__empty_struct // ++wuffs_private_impl__bulk_save_host_endian(void* ptr, ++ size_t len, ++ wuffs_base__slice_u8 dst) { ++ if (len && (len <= dst.len)) { ++ memmove(dst.ptr, ptr, len); ++ } ++ return wuffs_base__make_empty_struct(); + } + +-// wuffs_base__private_implementation__high_prec_dec__small_xshift shifts h's +-// number (where 'x' is 'l' or 'r' for left or right) by a small shift value. +-// +-// Preconditions: +-// - h is non-NULL. +-// - h->decimal_point is "not extreme". +-// - shift is non-zero. +-// - shift is "a small shift". +-// +-// "Not extreme" means within +-// ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE. +-// +-// "A small shift" means not more than +-// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL. +-// +-// wuffs_base__private_implementation__high_prec_dec__rounded_integer and +-// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits +-// have the same preconditions. +-// +-// wuffs_base__private_implementation__high_prec_dec__lshift keeps the first +-// two preconditions but not the last two. Its shift argument is signed and +-// does not need to be "small": zero is a no-op, positive means left shift and +-// negative means right shift. ++// -------- + +-static void // +-wuffs_base__private_implementation__high_prec_dec__small_lshift( +- wuffs_base__private_implementation__high_prec_dec* h, +- uint32_t shift) { +- if (h->num_digits == 0) { +- return; ++static inline wuffs_base__slice_u8 // ++wuffs_private_impl__table_u8__row_u32(wuffs_base__table_u8 t, uint32_t y) { ++ if (t.ptr && (y < t.height)) { ++ return wuffs_base__make_slice_u8(t.ptr + (t.stride * y), t.width); + } +- uint32_t num_new_digits = +- wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits( +- h, shift); +- uint32_t rx = h->num_digits - 1; // Read index. +- uint32_t wx = h->num_digits - 1 + num_new_digits; // Write index. +- uint64_t n = 0; ++ return wuffs_base__empty_slice_u8(); ++} + +- // Repeat: pick up a digit, put down a digit, right to left. +- while (((int32_t)rx) >= 0) { +- n += ((uint64_t)(h->digits[rx])) << shift; +- uint64_t quo = n / 10; +- uint64_t rem = n - (10 * quo); +- if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { +- h->digits[wx] = (uint8_t)rem; +- } else if (rem > 0) { +- h->truncated = true; +- } +- n = quo; +- wx--; +- rx--; +- } ++// ---------------- Slices and Tables (Utility) + +- // Put down leading digits, right to left. +- while (n > 0) { +- uint64_t quo = n / 10; +- uint64_t rem = n - (10 * quo); +- if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { +- h->digits[wx] = (uint8_t)rem; +- } else if (rem > 0) { +- h->truncated = true; +- } +- n = quo; +- wx--; +- } ++#define wuffs_base__utility__empty_slice_u8 wuffs_base__empty_slice_u8 + +- // Finish. +- h->num_digits += num_new_digits; +- if (h->num_digits > +- WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { +- h->num_digits = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION; +- } +- h->decimal_point += (int32_t)num_new_digits; +- wuffs_base__private_implementation__high_prec_dec__trim(h); ++// ---------------- Ranges and Rects ++ ++static inline uint32_t // ++wuffs_private_impl__range_ii_u32__get_min_incl( ++ const wuffs_base__range_ii_u32* r) { ++ return r->min_incl; + } + +-static void // +-wuffs_base__private_implementation__high_prec_dec__small_rshift( +- wuffs_base__private_implementation__high_prec_dec* h, +- uint32_t shift) { +- uint32_t rx = 0; // Read index. +- uint32_t wx = 0; // Write index. +- uint64_t n = 0; ++static inline uint32_t // ++wuffs_private_impl__range_ii_u32__get_max_incl( ++ const wuffs_base__range_ii_u32* r) { ++ return r->max_incl; ++} + +- // Pick up enough leading digits to cover the first shift. +- while ((n >> shift) == 0) { +- if (rx < h->num_digits) { +- // Read a digit. +- n = (10 * n) + h->digits[rx++]; +- } else if (n == 0) { +- // h's number used to be zero and remains zero. +- return; +- } else { +- // Read sufficient implicit trailing zeroes. +- while ((n >> shift) == 0) { +- n = 10 * n; +- rx++; +- } +- break; +- } +- } +- h->decimal_point -= ((int32_t)(rx - 1)); +- if (h->decimal_point < +- -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { +- // After the shift, h's number is effectively zero. +- h->num_digits = 0; +- h->decimal_point = 0; +- h->truncated = false; +- return; +- } ++static inline uint32_t // ++wuffs_private_impl__range_ie_u32__get_min_incl( ++ const wuffs_base__range_ie_u32* r) { ++ return r->min_incl; ++} + +- // Repeat: pick up a digit, put down a digit, left to right. +- uint64_t mask = (((uint64_t)(1)) << shift) - 1; +- while (rx < h->num_digits) { +- uint8_t new_digit = ((uint8_t)(n >> shift)); +- n = (10 * (n & mask)) + h->digits[rx++]; +- h->digits[wx++] = new_digit; +- } ++static inline uint32_t // ++wuffs_private_impl__range_ie_u32__get_max_excl( ++ const wuffs_base__range_ie_u32* r) { ++ return r->max_excl; ++} + +- // Put down trailing digits, left to right. +- while (n > 0) { +- uint8_t new_digit = ((uint8_t)(n >> shift)); +- n = 10 * (n & mask); +- if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { +- h->digits[wx++] = new_digit; +- } else if (new_digit > 0) { +- h->truncated = true; +- } +- } ++static inline uint64_t // ++wuffs_private_impl__range_ii_u64__get_min_incl( ++ const wuffs_base__range_ii_u64* r) { ++ return r->min_incl; ++} + +- // Finish. +- h->num_digits = wx; +- wuffs_base__private_implementation__high_prec_dec__trim(h); ++static inline uint64_t // ++wuffs_private_impl__range_ii_u64__get_max_incl( ++ const wuffs_base__range_ii_u64* r) { ++ return r->max_incl; + } + +-static void // +-wuffs_base__private_implementation__high_prec_dec__lshift( +- wuffs_base__private_implementation__high_prec_dec* h, +- int32_t shift) { +- if (shift > 0) { +- while (shift > +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) { +- wuffs_base__private_implementation__high_prec_dec__small_lshift( +- h, WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL); +- shift -= WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL; +- } +- wuffs_base__private_implementation__high_prec_dec__small_lshift( +- h, ((uint32_t)(+shift))); +- } else if (shift < 0) { +- while (shift < -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) { +- wuffs_base__private_implementation__high_prec_dec__small_rshift( +- h, WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL); +- shift += WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL; +- } +- wuffs_base__private_implementation__high_prec_dec__small_rshift( +- h, ((uint32_t)(-shift))); +- } ++static inline uint64_t // ++wuffs_private_impl__range_ie_u64__get_min_incl( ++ const wuffs_base__range_ie_u64* r) { ++ return r->min_incl; + } + +-// -------- ++static inline uint64_t // ++wuffs_private_impl__range_ie_u64__get_max_excl( ++ const wuffs_base__range_ie_u64* r) { ++ return r->max_excl; ++} + +-// wuffs_base__private_implementation__high_prec_dec__round_etc rounds h's +-// number. For those functions that take an n argument, rounding produces at +-// most n digits (which is not necessarily at most n decimal places). Negative +-// n values are ignored, as well as any n greater than or equal to h's number +-// of digits. The etc__round_just_enough function implicitly chooses an n to +-// implement WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION. +-// +-// Preconditions: +-// - h is non-NULL. +-// - h->decimal_point is "not extreme". +-// +-// "Not extreme" means within +-// ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE. ++// ---------------- Ranges and Rects (Utility) + +-static void // +-wuffs_base__private_implementation__high_prec_dec__round_down( +- wuffs_base__private_implementation__high_prec_dec* h, +- int32_t n) { +- if ((n < 0) || (h->num_digits <= (uint32_t)n)) { +- return; ++#define wuffs_base__utility__empty_range_ii_u32 wuffs_base__empty_range_ii_u32 ++#define wuffs_base__utility__empty_range_ie_u32 wuffs_base__empty_range_ie_u32 ++#define wuffs_base__utility__empty_range_ii_u64 wuffs_base__empty_range_ii_u64 ++#define wuffs_base__utility__empty_range_ie_u64 wuffs_base__empty_range_ie_u64 ++#define wuffs_base__utility__empty_rect_ii_u32 wuffs_base__empty_rect_ii_u32 ++#define wuffs_base__utility__empty_rect_ie_u32 wuffs_base__empty_rect_ie_u32 ++#define wuffs_base__utility__make_range_ii_u32 wuffs_base__make_range_ii_u32 ++#define wuffs_base__utility__make_range_ie_u32 wuffs_base__make_range_ie_u32 ++#define wuffs_base__utility__make_range_ii_u64 wuffs_base__make_range_ii_u64 ++#define wuffs_base__utility__make_range_ie_u64 wuffs_base__make_range_ie_u64 ++#define wuffs_base__utility__make_rect_ii_u32 wuffs_base__make_rect_ii_u32 ++#define wuffs_base__utility__make_rect_ie_u32 wuffs_base__make_rect_ie_u32 ++ ++// ---------------- I/O ++ ++static inline uint64_t // ++wuffs_private_impl__io__count_since(uint64_t mark, uint64_t index) { ++ if (index >= mark) { ++ return index - mark; + } +- h->num_digits = (uint32_t)(n); +- wuffs_base__private_implementation__high_prec_dec__trim(h); ++ return 0; + } + +-static void // +-wuffs_base__private_implementation__high_prec_dec__round_up( +- wuffs_base__private_implementation__high_prec_dec* h, +- int32_t n) { +- if ((n < 0) || (h->num_digits <= (uint32_t)n)) { +- return; ++// TODO: drop the "const" in "const uint8_t* ptr". Some though required about ++// the base.io_reader.since method returning a mutable "slice base.u8". ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wcast-qual" ++#endif ++static inline wuffs_base__slice_u8 // ++wuffs_private_impl__io__since(uint64_t mark, ++ uint64_t index, ++ const uint8_t* ptr) { ++ if (index >= mark) { ++ return wuffs_base__make_slice_u8(((uint8_t*)ptr) + mark, ++ ((size_t)(index - mark))); + } ++ return wuffs_base__empty_slice_u8(); ++} ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif + +- for (n--; n >= 0; n--) { +- if (h->digits[n] < 9) { +- h->digits[n]++; +- h->num_digits = (uint32_t)(n + 1); +- return; +- } +- } ++// -------- + +- // The number is all 9s. Change to a single 1 and adjust the decimal point. +- h->digits[0] = 1; +- h->num_digits = 1; +- h->decimal_point++; ++static inline void // ++wuffs_private_impl__io_reader__limit(const uint8_t** ptr_io2_r, ++ const uint8_t* iop_r, ++ uint64_t limit) { ++ if (((uint64_t)(*ptr_io2_r - iop_r)) > limit) { ++ *ptr_io2_r = iop_r + limit; ++ } + } + +-static void // +-wuffs_base__private_implementation__high_prec_dec__round_nearest( +- wuffs_base__private_implementation__high_prec_dec* h, +- int32_t n) { +- if ((n < 0) || (h->num_digits <= (uint32_t)n)) { +- return; ++static inline uint32_t // ++wuffs_private_impl__io_reader__limited_copy_u32_to_slice( ++ const uint8_t** ptr_iop_r, ++ const uint8_t* io2_r, ++ uint32_t length, ++ wuffs_base__slice_u8 dst) { ++ const uint8_t* iop_r = *ptr_iop_r; ++ size_t n = dst.len; ++ if (n > length) { ++ n = length; + } +- bool up = h->digits[n] >= 5; +- if ((h->digits[n] == 5) && ((n + 1) == ((int32_t)(h->num_digits)))) { +- up = h->truncated || // +- ((n > 0) && ((h->digits[n - 1] & 1) != 0)); ++ if (n > ((size_t)(io2_r - iop_r))) { ++ n = (size_t)(io2_r - iop_r); + } +- +- if (up) { +- wuffs_base__private_implementation__high_prec_dec__round_up(h, n); +- } else { +- wuffs_base__private_implementation__high_prec_dec__round_down(h, n); ++ if (n > 0) { ++ memmove(dst.ptr, iop_r, n); ++ *ptr_iop_r += n; + } ++ return (uint32_t)(n); + } + +-static void // +-wuffs_base__private_implementation__high_prec_dec__round_just_enough( +- wuffs_base__private_implementation__high_prec_dec* h, +- int32_t exp2, +- uint64_t mantissa) { +- // The magic numbers 52 and 53 in this function are because IEEE 754 double +- // precision has 52 mantissa bits. +- // +- // Let f be the floating point number represented by exp2 and mantissa (and +- // also the number in h): the number (mantissa * (2 ** (exp2 - 52))). +- // +- // If f is zero or a small integer, we can return early. +- if ((mantissa == 0) || +- ((exp2 < 53) && (h->decimal_point >= ((int32_t)(h->num_digits))))) { +- return; ++// wuffs_private_impl__io_reader__match7 returns whether the io_reader's ++// upcoming bytes start with the given prefix (up to 7 bytes long). It is ++// peek-like, not read-like, in that there are no side-effects. ++// ++// The low 3 bits of a hold the prefix length, n. ++// ++// The high 56 bits of a hold the prefix itself, in little-endian order. The ++// first prefix byte is in bits 8..=15, the second prefix byte is in bits ++// 16..=23, etc. The high (8 * (7 - n)) bits are ignored. ++// ++// There are three possible return values: ++// - 0 means success. ++// - 1 means inconclusive, equivalent to "$short read". ++// - 2 means failure. ++static inline uint32_t // ++wuffs_private_impl__io_reader__match7(const uint8_t* iop_r, ++ const uint8_t* io2_r, ++ wuffs_base__io_buffer* r, ++ uint64_t a) { ++ uint32_t n = a & 7; ++ a >>= 8; ++ if ((io2_r - iop_r) >= 8) { ++ uint64_t x = wuffs_base__peek_u64le__no_bounds_check(iop_r); ++ uint32_t shift = 8 * (8 - n); ++ return ((a << shift) == (x << shift)) ? 0 : 2; ++ } ++ for (; n > 0; n--) { ++ if (iop_r >= io2_r) { ++ return (r && r->meta.closed) ? 2 : 1; ++ } else if (*iop_r != ((uint8_t)(a))) { ++ return 2; ++ } ++ iop_r++; ++ a >>= 8; + } ++ return 0; ++} + +- // The smallest normal f has an exp2 of -1022 and a mantissa of (1 << 52). +- // Subnormal numbers have the same exp2 but a smaller mantissa. +- static const int32_t min_incl_normal_exp2 = -1022; +- static const uint64_t min_incl_normal_mantissa = 0x0010000000000000ul; ++static inline wuffs_base__io_buffer* // ++wuffs_private_impl__io_reader__set(wuffs_base__io_buffer* b, ++ const uint8_t** ptr_iop_r, ++ const uint8_t** ptr_io0_r, ++ const uint8_t** ptr_io1_r, ++ const uint8_t** ptr_io2_r, ++ wuffs_base__slice_u8 data, ++ uint64_t history_position) { ++ b->data = data; ++ b->meta.wi = data.len; ++ b->meta.ri = 0; ++ b->meta.pos = history_position; ++ b->meta.closed = false; + +- // Compute lower and upper bounds such that any number between them (possibly +- // inclusive) will round to f. First, the lower bound. Our number f is: +- // ((mantissa + 0) * (2 ** ( exp2 - 52))) +- // +- // The next lowest floating point number is: +- // ((mantissa - 1) * (2 ** ( exp2 - 52))) +- // unless (mantissa - 1) drops the (1 << 52) bit and exp2 is not the +- // min_incl_normal_exp2. Either way, call it: +- // ((l_mantissa) * (2 ** (l_exp2 - 52))) +- // +- // The lower bound is halfway between them (noting that 52 became 53): +- // (((2 * l_mantissa) + 1) * (2 ** (l_exp2 - 53))) +- int32_t l_exp2 = exp2; +- uint64_t l_mantissa = mantissa - 1; +- if ((exp2 > min_incl_normal_exp2) && (mantissa <= min_incl_normal_mantissa)) { +- l_exp2 = exp2 - 1; +- l_mantissa = (2 * mantissa) - 1; +- } +- wuffs_base__private_implementation__high_prec_dec lower; +- wuffs_base__private_implementation__high_prec_dec__assign( +- &lower, (2 * l_mantissa) + 1, false); +- wuffs_base__private_implementation__high_prec_dec__lshift(&lower, +- l_exp2 - 53); ++ *ptr_iop_r = data.ptr; ++ *ptr_io0_r = data.ptr; ++ *ptr_io1_r = data.ptr; ++ *ptr_io2_r = data.ptr + data.len; + +- // Next, the upper bound. Our number f is: +- // ((mantissa + 0) * (2 ** (exp2 - 52))) +- // +- // The next highest floating point number is: +- // ((mantissa + 1) * (2 ** (exp2 - 52))) +- // +- // The upper bound is halfway between them (noting that 52 became 53): +- // (((2 * mantissa) + 1) * (2 ** (exp2 - 53))) +- wuffs_base__private_implementation__high_prec_dec upper; +- wuffs_base__private_implementation__high_prec_dec__assign( +- &upper, (2 * mantissa) + 1, false); +- wuffs_base__private_implementation__high_prec_dec__lshift(&upper, exp2 - 53); ++ return b; ++} + +- // The lower and upper bounds are possible outputs only if the original +- // mantissa is even, so that IEEE round-to-even would round to the original +- // mantissa and not its neighbors. +- bool inclusive = (mantissa & 1) == 0; ++// -------- + +- // As we walk the digits, we want to know whether rounding up would fall +- // within the upper bound. This is tracked by upper_delta: +- // - When -1, the digits of h and upper are the same so far. +- // - When +0, we saw a difference of 1 between h and upper on a previous +- // digit and subsequently only 9s for h and 0s for upper. Thus, rounding +- // up may fall outside of the bound if !inclusive. +- // - When +1, the difference is greater than 1 and we know that rounding up +- // falls within the bound. +- // +- // This is a state machine with three states. The numerical value for each +- // state (-1, +0 or +1) isn't important, other than their order. +- int upper_delta = -1; ++static inline uint64_t // ++wuffs_private_impl__io_writer__copy_from_slice(uint8_t** ptr_iop_w, ++ uint8_t* io2_w, ++ wuffs_base__slice_u8 src) { ++ uint8_t* iop_w = *ptr_iop_w; ++ size_t n = src.len; ++ if (n > ((size_t)(io2_w - iop_w))) { ++ n = (size_t)(io2_w - iop_w); ++ } ++ if (n > 0) { ++ memmove(iop_w, src.ptr, n); ++ *ptr_iop_w += n; ++ } ++ return (uint64_t)(n); ++} + +- // We can now figure out the shortest number of digits required. Walk the +- // digits until h has distinguished itself from lower or upper. +- // +- // The zi and zd variables are indexes and digits, for z in l (lower), h (the +- // number) and u (upper). ++static inline void // ++wuffs_private_impl__io_writer__limit(uint8_t** ptr_io2_w, ++ uint8_t* iop_w, ++ uint64_t limit) { ++ if (((uint64_t)(*ptr_io2_w - iop_w)) > limit) { ++ *ptr_io2_w = iop_w + limit; ++ } ++} ++ ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_history( ++ uint8_t** ptr_iop_w, ++ uint8_t* io0_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ uint32_t distance) { ++ if (!distance) { ++ return 0; ++ } ++ uint8_t* p = *ptr_iop_w; ++ if ((size_t)(p - io0_w) < (size_t)(distance)) { ++ return 0; ++ } ++ uint8_t* q = p - distance; ++ size_t n = (size_t)(io2_w - p); ++ if ((size_t)(length) > n) { ++ length = (uint32_t)(n); ++ } else { ++ n = (size_t)(length); ++ } ++ // TODO: unrolling by 3 seems best for the std/deflate benchmarks, but that ++ // is mostly because 3 is the minimum length for the deflate format. This ++ // function implementation shouldn't overfit to that one format. Perhaps the ++ // limited_copy_u32_from_history Wuffs method should also take an unroll hint ++ // argument, and the cgen can look if that argument is the constant ++ // expression '3'. + // +- // The lower, h and upper numbers may have their decimal points at different +- // places. In this case, upper is the longest, so we iterate ui starting from +- // 0 and iterate li and hi starting from either 0 or -1. +- int32_t ui = 0; +- for (;; ui++) { +- // Calculate hd, the middle number's digit. +- int32_t hi = ui - upper.decimal_point + h->decimal_point; +- if (hi >= ((int32_t)(h->num_digits))) { +- break; +- } +- uint8_t hd = (((uint32_t)hi) < h->num_digits) ? h->digits[hi] : 0; ++ // See also wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast ++ // below. ++ for (; n >= 3; n -= 3) { ++ *p++ = *q++; ++ *p++ = *q++; ++ *p++ = *q++; ++ } ++ for (; n; n--) { ++ *p++ = *q++; ++ } ++ *ptr_iop_w = p; ++ return length; ++} + +- // Calculate ld, the lower bound's digit. +- int32_t li = ui - upper.decimal_point + lower.decimal_point; +- uint8_t ld = (((uint32_t)li) < lower.num_digits) ? lower.digits[li] : 0; ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast is like ++// the wuffs_private_impl__io_writer__limited_copy_u32_from_history function ++// above, but has stronger pre-conditions. ++// ++// The caller needs to prove that: ++// - length >= 1 ++// - length <= (io2_w - *ptr_iop_w) ++// - distance >= 1 ++// - distance <= (*ptr_iop_w - io0_w) ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast( ++ uint8_t** ptr_iop_w, ++ uint8_t* io0_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ uint32_t distance) { ++ uint8_t* p = *ptr_iop_w; ++ uint8_t* q = p - distance; ++ uint32_t n = length; ++ for (; n >= 3; n -= 3) { ++ *p++ = *q++; ++ *p++ = *q++; ++ *p++ = *q++; ++ } ++ for (; n; n--) { ++ *p++ = *q++; ++ } ++ *ptr_iop_w = p; ++ return length; ++} + +- // We can round down (truncate) if lower has a different digit than h or if +- // lower is inclusive and is exactly the result of rounding down (i.e. we +- // have reached the final digit of lower). +- bool can_round_down = +- (ld != hd) || // +- (inclusive && ((li + 1) == ((int32_t)(lower.num_digits)))); ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast_return_cusp ++// is like the ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast function, ++// but also returns the cusp: a byte pair (as a u16le) being the last byte of ++// and next byte after the copied history. ++// ++// For example, if history was [10, 11, 12, 13, 14, 15, 16, 17, 18] then: ++// - copying l=3, d=8 produces [11, 12, 13] and the cusp is (13, 14). ++// - copying l=3, d=2 produces [17, 18, 17] and the cusp is (17, 18). ++// ++// The caller needs to prove that: ++// - length >= 1 ++// - length <= (io2_w - *ptr_iop_w) ++// - distance >= 1 ++// - distance <= (*ptr_iop_w - io0_w) ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast_return_cusp( ++ uint8_t** ptr_iop_w, ++ uint8_t* io0_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ uint32_t distance) { ++ uint8_t* p = *ptr_iop_w; ++ uint8_t* q = p - distance; ++ uint32_t n = length; ++ for (; n >= 3; n -= 3) { ++ *p++ = *q++; ++ *p++ = *q++; ++ *p++ = *q++; ++ } ++ for (; n; n--) { ++ *p++ = *q++; ++ } ++ *ptr_iop_w = p; ++ return (uint32_t)wuffs_base__peek_u16le__no_bounds_check(q - 1); ++} + +- // Calculate ud, the upper bound's digit, and update upper_delta. +- uint8_t ud = (((uint32_t)ui) < upper.num_digits) ? upper.digits[ui] : 0; +- if (upper_delta < 0) { +- if ((hd + 1) < ud) { +- // For example: +- // h = 12345??? +- // upper = 12347??? +- upper_delta = +1; +- } else if (hd != ud) { +- // For example: +- // h = 12345??? +- // upper = 12346??? +- upper_delta = +0; +- } +- } else if (upper_delta == 0) { +- if ((hd != 9) || (ud != 0)) { +- // For example: +- // h = 1234598? +- // upper = 1234600? +- upper_delta = +1; +- } ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast ++// copies the previous byte (the one immediately before *ptr_iop_w), copying 8 ++// byte chunks at a time. Each chunk contains 8 repetitions of the same byte. ++// ++// In terms of number of bytes copied, length is rounded up to a multiple of 8. ++// As a special case, a zero length rounds up to 8 (even though 0 is already a ++// multiple of 8), since there is always at least one 8 byte chunk copied. ++// ++// In terms of advancing *ptr_iop_w, length is not rounded up. ++// ++// The caller needs to prove that: ++// - length >= 1 ++// - (length + 8) <= (io2_w - *ptr_iop_w) ++// - distance == 1 ++// - distance <= (*ptr_iop_w - io0_w) ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast( ++ uint8_t** ptr_iop_w, ++ uint8_t* io0_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ uint32_t distance) { ++ uint8_t* p = *ptr_iop_w; ++ uint64_t x = p[-1]; ++ x |= x << 8; ++ x |= x << 16; ++ x |= x << 32; ++ uint32_t n = length; ++ while (1) { ++ wuffs_base__poke_u64le__no_bounds_check(p, x); ++ if (n <= 8) { ++ p += n; ++ break; + } ++ p += 8; ++ n -= 8; ++ } ++ *ptr_iop_w = p; ++ return length; ++} + +- // We can round up if upper has a different digit than h and either upper +- // is inclusive or upper is bigger than the result of rounding up. +- bool can_round_up = +- (upper_delta > 0) || // +- ((upper_delta == 0) && // +- (inclusive || ((ui + 1) < ((int32_t)(upper.num_digits))))); +- +- // If we can round either way, round to nearest. If we can round only one +- // way, do it. If we can't round, continue the loop. +- if (can_round_down) { +- if (can_round_up) { +- wuffs_base__private_implementation__high_prec_dec__round_nearest( +- h, hi + 1); +- return; +- } else { +- wuffs_base__private_implementation__high_prec_dec__round_down(h, +- hi + 1); +- return; +- } +- } else { +- if (can_round_up) { +- wuffs_base__private_implementation__high_prec_dec__round_up(h, hi + 1); +- return; +- } ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast_return_cusp ++// copies the previous byte (the one immediately before *ptr_iop_w), copying 8 ++// byte chunks at a time. Each chunk contains 8 repetitions of the same byte. ++// It also returns the cusp: a byte pair (as a u16le) being the last byte of ++// and next byte after the copied history. ++// ++// In terms of number of bytes copied, length is rounded up to a multiple of 8. ++// As a special case, a zero length rounds up to 8 (even though 0 is already a ++// multiple of 8), since there is always at least one 8 byte chunk copied. ++// ++// In terms of advancing *ptr_iop_w, length is not rounded up. ++// ++// The caller needs to prove that: ++// - length >= 1 ++// - (length + 8) <= (io2_w - *ptr_iop_w) ++// - distance == 1 ++// - distance <= (*ptr_iop_w - io0_w) ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast_return_cusp( ++ uint8_t** ptr_iop_w, ++ uint8_t* io0_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ uint32_t distance) { ++ uint8_t* p = *ptr_iop_w; ++ uint8_t* q = p - distance; ++ uint64_t x = p[-1]; ++ x |= x << 8; ++ x |= x << 16; ++ x |= x << 32; ++ uint32_t n = length; ++ while (1) { ++ wuffs_base__poke_u64le__no_bounds_check(p, x); ++ if (n <= 8) { ++ p += n; ++ q += n; ++ break; + } ++ p += 8; ++ q += 8; ++ n -= 8; + } ++ *ptr_iop_w = p; ++ return (uint32_t)wuffs_base__peek_u16le__no_bounds_check(q - 1); + } + +-// -------- +- +-// wuffs_base__private_implementation__parse_number_f64_eisel_lemire produces +-// the IEEE 754 double-precision value for an exact mantissa and base-10 +-// exponent. For example: +-// - when parsing "12345.678e+02", man is 12345678 and exp10 is -1. +-// - when parsing "-12", man is 12 and exp10 is 0. Processing the leading +-// minus sign is the responsibility of the caller, not this function. ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast ++// is like the ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast function ++// above, but copies 8 byte chunks at a time. + // +-// On success, it returns a non-negative int64_t such that the low 63 bits hold +-// the 11-bit exponent and 52-bit mantissa. ++// In terms of number of bytes copied, length is rounded up to a multiple of 8. ++// As a special case, a zero length rounds up to 8 (even though 0 is already a ++// multiple of 8), since there is always at least one 8 byte chunk copied. + // +-// On failure, it returns a negative value. ++// In terms of advancing *ptr_iop_w, length is not rounded up. + // +-// The algorithm is based on an original idea by Michael Eisel that was refined +-// by Daniel Lemire. See +-// https://lemire.me/blog/2020/03/10/fast-float-parsing-in-practice/ +-// and +-// https://nigeltao.github.io/blog/2020/eisel-lemire.html ++// The caller needs to prove that: ++// - length >= 1 ++// - (length + 8) <= (io2_w - *ptr_iop_w) ++// - distance >= 8 ++// - distance <= (*ptr_iop_w - io0_w) ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast( ++ uint8_t** ptr_iop_w, ++ uint8_t* io0_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ uint32_t distance) { ++ uint8_t* p = *ptr_iop_w; ++ uint8_t* q = p - distance; ++ uint32_t n = length; ++ while (1) { ++ memcpy(p, q, 8); ++ if (n <= 8) { ++ p += n; ++ break; ++ } ++ p += 8; ++ q += 8; ++ n -= 8; ++ } ++ *ptr_iop_w = p; ++ return length; ++} ++ ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast_return_cusp ++// is like the ++// wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast function ++// above, but copies 8 byte chunks at a time. It also returns the cusp: a byte ++// pair (as a u16le) being the last byte of and next byte after the copied ++// history. + // +-// Preconditions: +-// - man is non-zero. +-// - exp10 is in the range [-307 ..= 288], the same range of the +-// wuffs_base__private_implementation__powers_of_10 array. ++// In terms of number of bytes copied, length is rounded up to a multiple of 8. ++// As a special case, a zero length rounds up to 8 (even though 0 is already a ++// multiple of 8), since there is always at least one 8 byte chunk copied. + // +-// The exp10 range (and the fact that man is in the range [1 ..= UINT64_MAX], +-// approximately [1 ..= 1.85e+19]) means that (man * (10 ** exp10)) is in the +-// range [1e-307 ..= 1.85e+307]. This is entirely within the range of normal +-// (neither subnormal nor non-finite) f64 values: DBL_MIN and DBL_MAX are +-// approximately 2.23e–308 and 1.80e+308. +-static int64_t // +-wuffs_base__private_implementation__parse_number_f64_eisel_lemire( +- uint64_t man, +- int32_t exp10) { +- // Look up the (possibly truncated) base-2 representation of (10 ** exp10). +- // The look-up table was constructed so that it is already normalized: the +- // table entry's mantissa's MSB (most significant bit) is on. +- const uint64_t* po10 = +- &wuffs_base__private_implementation__powers_of_10[exp10 + 307][0]; ++// In terms of advancing *ptr_iop_w, length is not rounded up. ++// ++// The caller needs to prove that: ++// - length >= 1 ++// - (length + 8) <= (io2_w - *ptr_iop_w) ++// - distance >= 8 ++// - distance <= (*ptr_iop_w - io0_w) ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast_return_cusp( ++ uint8_t** ptr_iop_w, ++ uint8_t* io0_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ uint32_t distance) { ++ uint8_t* p = *ptr_iop_w; ++ uint8_t* q = p - distance; ++ uint32_t n = length; ++ while (1) { ++ memcpy(p, q, 8); ++ if (n <= 8) { ++ p += n; ++ q += n; ++ break; ++ } ++ p += 8; ++ q += 8; ++ n -= 8; ++ } ++ *ptr_iop_w = p; ++ return (uint32_t)wuffs_base__peek_u16le__no_bounds_check(q - 1); ++} + +- // Normalize the man argument. The (man != 0) precondition means that a +- // non-zero bit exists. +- uint32_t clz = wuffs_base__count_leading_zeroes_u64(man); +- man <<= clz; ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_reader( ++ uint8_t** ptr_iop_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ const uint8_t** ptr_iop_r, ++ const uint8_t* io2_r) { ++ uint8_t* iop_w = *ptr_iop_w; ++ size_t n = length; ++ if (n > ((size_t)(io2_w - iop_w))) { ++ n = (size_t)(io2_w - iop_w); ++ } ++ const uint8_t* iop_r = *ptr_iop_r; ++ if (n > ((size_t)(io2_r - iop_r))) { ++ n = (size_t)(io2_r - iop_r); ++ } ++ if (n > 0) { ++ memmove(iop_w, iop_r, n); ++ *ptr_iop_w += n; ++ *ptr_iop_r += n; ++ } ++ return (uint32_t)(n); ++} + +- // Calculate the return value's base-2 exponent. We might tweak it by ±1 +- // later, but its initial value comes from a linear scaling of exp10, +- // converting from power-of-10 to power-of-2, and adjusting by clz. +- // +- // The magic constants are: +- // - 1087 = 1023 + 64. The 1023 is the f64 exponent bias. The 64 is because +- // the look-up table uses 64-bit mantissas. +- // - 217706 is such that the ratio 217706 / 65536 ≈ 3.321930 is close enough +- // (over the practical range of exp10) to log(10) / log(2) ≈ 3.321928. +- // - 65536 = 1<<16 is arbitrary but a power of 2, so division is a shift. +- // +- // Equality of the linearly-scaled value and the actual power-of-2, over the +- // range of exp10 arguments that this function accepts, is confirmed by +- // script/print-mpb-powers-of-10.go +- uint64_t ret_exp2 = +- ((uint64_t)(((217706 * exp10) >> 16) + 1087)) - ((uint64_t)clz); ++static inline uint32_t // ++wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ uint8_t** ptr_iop_w, ++ uint8_t* io2_w, ++ uint32_t length, ++ wuffs_base__slice_u8 src) { ++ uint8_t* iop_w = *ptr_iop_w; ++ size_t n = src.len; ++ if (n > length) { ++ n = length; ++ } ++ if (n > ((size_t)(io2_w - iop_w))) { ++ n = (size_t)(io2_w - iop_w); ++ } ++ if (n > 0) { ++ memmove(iop_w, src.ptr, n); ++ *ptr_iop_w += n; ++ } ++ return (uint32_t)(n); ++} + +- // Multiply the two mantissas. Normalization means that both mantissas are at +- // least (1<<63), so the 128-bit product must be at least (1<<126). The high +- // 64 bits of the product, x_hi, must therefore be at least (1<<62). +- // +- // As a consequence, x_hi has either 0 or 1 leading zeroes. Shifting x_hi +- // right by either 9 or 10 bits (depending on x_hi's MSB) will therefore +- // leave the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on. +- wuffs_base__multiply_u64__output x = wuffs_base__multiply_u64(man, po10[1]); +- uint64_t x_hi = x.hi; +- uint64_t x_lo = x.lo; ++static inline wuffs_base__io_buffer* // ++wuffs_private_impl__io_writer__set(wuffs_base__io_buffer* b, ++ uint8_t** ptr_iop_w, ++ uint8_t** ptr_io0_w, ++ uint8_t** ptr_io1_w, ++ uint8_t** ptr_io2_w, ++ wuffs_base__slice_u8 data, ++ uint64_t history_position) { ++ b->data = data; ++ b->meta.wi = 0; ++ b->meta.ri = 0; ++ b->meta.pos = history_position; ++ b->meta.closed = false; + +- // Before we shift right by at least 9 bits, recall that the look-up table +- // entry was possibly truncated. We have so far only calculated a lower bound +- // for the product (man * e), where e is (10 ** exp10). The upper bound would +- // add a further (man * 1) to the 128-bit product, which overflows the lower +- // 64-bit limb if ((x_lo + man) < man). +- // +- // If overflow occurs, that adds 1 to x_hi. Since we're about to shift right +- // by at least 9 bits, that carried 1 can be ignored unless the higher 64-bit +- // limb's low 9 bits are all on. +- // +- // For example, parsing "9999999999999999999" will take the if-true branch +- // here, since: +- // - x_hi = 0x4563918244F3FFFF +- // - x_lo = 0x8000000000000000 +- // - man = 0x8AC7230489E7FFFF +- if (((x_hi & 0x1FF) == 0x1FF) && ((x_lo + man) < man)) { +- // Refine our calculation of (man * e). Before, our approximation of e used +- // a "low resolution" 64-bit mantissa. Now use a "high resolution" 128-bit +- // mantissa. We've already calculated x = (man * bits_0_to_63_incl_of_e). +- // Now calculate y = (man * bits_64_to_127_incl_of_e). +- wuffs_base__multiply_u64__output y = wuffs_base__multiply_u64(man, po10[0]); +- uint64_t y_hi = y.hi; +- uint64_t y_lo = y.lo; ++ *ptr_iop_w = data.ptr; ++ *ptr_io0_w = data.ptr; ++ *ptr_io1_w = data.ptr; ++ *ptr_io2_w = data.ptr + data.len; + +- // Merge the 128-bit x and 128-bit y, which overlap by 64 bits, to +- // calculate the 192-bit product of the 64-bit man by the 128-bit e. +- // As we exit this if-block, we only care about the high 128 bits +- // (merged_hi and merged_lo) of that 192-bit product. +- // +- // For example, parsing "1.234e-45" will take the if-true branch here, +- // since: +- // - x_hi = 0x70B7E3696DB29FFF +- // - x_lo = 0xE040000000000000 +- // - y_hi = 0x33718BBEAB0E0D7A +- // - y_lo = 0xA880000000000000 +- uint64_t merged_hi = x_hi; +- uint64_t merged_lo = x_lo + y_hi; +- if (merged_lo < x_lo) { +- merged_hi++; // Carry the overflow bit. +- } ++ return b; ++} + +- // The "high resolution" approximation of e is still a lower bound. Once +- // again, see if the upper bound is large enough to produce a different +- // result. This time, if it does, give up instead of reaching for an even +- // more precise approximation to e. +- // +- // This three-part check is similar to the two-part check that guarded the +- // if block that we're now in, but it has an extra term for the middle 64 +- // bits (checking that adding 1 to merged_lo would overflow). +- // +- // For example, parsing "5.9604644775390625e-8" will take the if-true +- // branch here, since: +- // - merged_hi = 0x7FFFFFFFFFFFFFFF +- // - merged_lo = 0xFFFFFFFFFFFFFFFF +- // - y_lo = 0x4DB3FFC120988200 +- // - man = 0xD3C21BCECCEDA100 +- if (((merged_hi & 0x1FF) == 0x1FF) && ((merged_lo + 1) == 0) && +- (y_lo + man < man)) { +- return -1; +- } ++// ---------------- I/O (Utility) + +- // Replace the 128-bit x with merged. +- x_hi = merged_hi; +- x_lo = merged_lo; +- } ++#define wuffs_base__utility__empty_io_reader wuffs_base__empty_io_reader ++#define wuffs_base__utility__empty_io_writer wuffs_base__empty_io_writer + +- // As mentioned above, shifting x_hi right by either 9 or 10 bits will leave +- // the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on. If the +- // MSB (before shifting) was on, adjust ret_exp2 for the larger shift. +- // +- // Having bit 53 on (and higher bits off) means that ret_mantissa is a 54-bit +- // number. +- uint64_t msb = x_hi >> 63; +- uint64_t ret_mantissa = x_hi >> (msb + 9); +- ret_exp2 -= 1 ^ msb; ++// ---------------- Tokens + +- // IEEE 754 rounds to-nearest with ties rounded to-even. Rounding to-even can +- // be tricky. If we're half-way between two exactly representable numbers +- // (x's low 73 bits are zero and the next 2 bits that matter are "01"), give +- // up instead of trying to pick the winner. +- // +- // Technically, we could tighten the condition by changing "73" to "73 or 74, +- // depending on msb", but a flat "73" is simpler. +- // +- // For example, parsing "1e+23" will take the if-true branch here, since: +- // - x_hi = 0x54B40B1F852BDA00 +- // - ret_mantissa = 0x002A5A058FC295ED +- if ((x_lo == 0) && ((x_hi & 0x1FF) == 0) && ((ret_mantissa & 3) == 1)) { +- return -1; +- } ++// ---------------- Tokens (Utility) + +- // If we're not halfway then it's rounding to-nearest. Starting with a 54-bit +- // number, carry the lowest bit (bit 0) up if it's on. Regardless of whether +- // it was on or off, shifting right by one then produces a 53-bit number. If +- // carrying up overflowed, shift again. +- ret_mantissa += ret_mantissa & 1; +- ret_mantissa >>= 1; +- // This if block is equivalent to (but benchmarks slightly faster than) the +- // following branchless form: +- // uint64_t overflow_adjustment = ret_mantissa >> 53; +- // ret_mantissa >>= overflow_adjustment; +- // ret_exp2 += overflow_adjustment; +- // +- // For example, parsing "7.2057594037927933e+16" will take the if-true +- // branch here, since: +- // - x_hi = 0x7FFFFFFFFFFFFE80 +- // - ret_mantissa = 0x0020000000000000 +- if ((ret_mantissa >> 53) > 0) { +- ret_mantissa >>= 1; +- ret_exp2++; +- } ++// ---------------- Memory Allocation + +- // Starting with a 53-bit number, IEEE 754 double-precision normal numbers +- // have an implicit mantissa bit. Mask that away and keep the low 52 bits. +- ret_mantissa &= 0x000FFFFFFFFFFFFF; ++// ---------------- Images + +- // Pack the bits and return. +- return ((int64_t)(ret_mantissa | (ret_exp2 << 52))); +-} ++WUFFS_BASE__MAYBE_STATIC uint64_t // ++wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader( ++ const wuffs_base__pixel_swizzler* p, ++ uint32_t up_to_num_pixels, ++ wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 dst_palette, ++ const uint8_t** ptr_iop_r, ++ const uint8_t* io2_r); + +-// -------- ++WUFFS_BASE__MAYBE_STATIC uint64_t // ++wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( ++ const wuffs_base__pixel_swizzler* p, ++ wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 dst_palette, ++ const uint8_t** ptr_iop_r, ++ const uint8_t* io2_r); + +-static wuffs_base__result_f64 // +-wuffs_base__private_implementation__parse_number_f64_special( +- wuffs_base__slice_u8 s, +- uint32_t options) { +- do { +- if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) { +- goto fail; +- } ++WUFFS_BASE__MAYBE_STATIC uint64_t // ++wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black( ++ const wuffs_base__pixel_swizzler* p, ++ wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 dst_palette, ++ uint64_t num_pixels); + +- uint8_t* p = s.ptr; +- uint8_t* q = s.ptr + s.len; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status // ++wuffs_base__pixel_swizzler__swizzle_ycck( ++ const wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_buffer* dst, ++ wuffs_base__slice_u8 dst_palette, ++ uint32_t x_min_incl, ++ uint32_t x_max_excl, ++ uint32_t y_min_incl, ++ uint32_t y_max_excl, ++ wuffs_base__slice_u8 src0, ++ wuffs_base__slice_u8 src1, ++ wuffs_base__slice_u8 src2, ++ wuffs_base__slice_u8 src3, ++ uint32_t width0, ++ uint32_t width1, ++ uint32_t width2, ++ uint32_t width3, ++ uint32_t height0, ++ uint32_t height1, ++ uint32_t height2, ++ uint32_t height3, ++ uint32_t stride0, ++ uint32_t stride1, ++ uint32_t stride2, ++ uint32_t stride3, ++ uint8_t h0, ++ uint8_t h1, ++ uint8_t h2, ++ uint8_t h3, ++ uint8_t v0, ++ uint8_t v1, ++ uint8_t v2, ++ uint8_t v3, ++ bool is_rgb_or_cmyk, ++ bool triangle_filter_for_2to1, ++ wuffs_base__slice_u8 scratch_buffer_2k); + +- for (; (p < q) && (*p == '_'); p++) { +- } +- if (p >= q) { +- goto fail; +- } ++// ---------------- Images (Utility) + +- // Parse sign. +- bool negative = false; +- do { +- if (*p == '+') { +- p++; +- } else if (*p == '-') { +- negative = true; +- p++; +- } else { +- break; +- } +- for (; (p < q) && (*p == '_'); p++) { +- } +- } while (0); +- if (p >= q) { +- goto fail; +- } ++#define wuffs_base__utility__make_pixel_format wuffs_base__make_pixel_format + +- bool nan = false; +- switch (p[0]) { +- case 'I': +- case 'i': +- if (((q - p) < 3) || // +- ((p[1] != 'N') && (p[1] != 'n')) || // +- ((p[2] != 'F') && (p[2] != 'f'))) { +- goto fail; +- } +- p += 3; ++// ---------------- String Conversions + +- if ((p >= q) || (*p == '_')) { +- break; +- } else if (((q - p) < 5) || // +- ((p[0] != 'I') && (p[0] != 'i')) || // +- ((p[1] != 'N') && (p[1] != 'n')) || // +- ((p[2] != 'I') && (p[2] != 'i')) || // +- ((p[3] != 'T') && (p[3] != 't')) || // +- ((p[4] != 'Y') && (p[4] != 'y'))) { +- goto fail; +- } +- p += 5; ++// ---------------- Unicode and UTF-8 + +- if ((p >= q) || (*p == '_')) { +- break; +- } +- goto fail; ++// ---------------- + +- case 'N': +- case 'n': +- if (((q - p) < 3) || // +- ((p[1] != 'A') && (p[1] != 'a')) || // +- ((p[2] != 'N') && (p[2] != 'n'))) { +- goto fail; +- } +- p += 3; ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ ++ defined(WUFFS_CONFIG__MODULE__BASE__CORE) + +- if ((p >= q) || (*p == '_')) { +- nan = true; +- break; +- } +- goto fail; ++const uint8_t wuffs_private_impl__low_bits_mask__u8[8] = { ++ 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, ++}; + +- default: +- goto fail; +- } ++const uint16_t wuffs_private_impl__low_bits_mask__u16[16] = { ++ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, ++ 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, ++}; + +- // Finish. +- for (; (p < q) && (*p == '_'); p++) { +- } +- if (p != q) { +- goto fail; +- } +- wuffs_base__result_f64 ret; +- ret.status.repr = NULL; +- ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64( +- (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) | +- (negative ? 0x8000000000000000 : 0)); +- return ret; +- } while (0); ++const uint32_t wuffs_private_impl__low_bits_mask__u32[32] = { ++ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, ++ 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, ++ 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, ++ 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, ++ 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, ++ 0x3FFFFFFF, 0x7FFFFFFF, ++}; + +-fail: +- do { +- wuffs_base__result_f64 ret; +- ret.status.repr = wuffs_base__error__bad_argument; +- ret.value = 0; +- return ret; +- } while (0); +-} ++const uint64_t wuffs_private_impl__low_bits_mask__u64[64] = { ++ 0x0000000000000000, 0x0000000000000001, 0x0000000000000003, ++ 0x0000000000000007, 0x000000000000000F, 0x000000000000001F, ++ 0x000000000000003F, 0x000000000000007F, 0x00000000000000FF, ++ 0x00000000000001FF, 0x00000000000003FF, 0x00000000000007FF, ++ 0x0000000000000FFF, 0x0000000000001FFF, 0x0000000000003FFF, ++ 0x0000000000007FFF, 0x000000000000FFFF, 0x000000000001FFFF, ++ 0x000000000003FFFF, 0x000000000007FFFF, 0x00000000000FFFFF, ++ 0x00000000001FFFFF, 0x00000000003FFFFF, 0x00000000007FFFFF, ++ 0x0000000000FFFFFF, 0x0000000001FFFFFF, 0x0000000003FFFFFF, ++ 0x0000000007FFFFFF, 0x000000000FFFFFFF, 0x000000001FFFFFFF, ++ 0x000000003FFFFFFF, 0x000000007FFFFFFF, 0x00000000FFFFFFFF, ++ 0x00000001FFFFFFFF, 0x00000003FFFFFFFF, 0x00000007FFFFFFFF, ++ 0x0000000FFFFFFFFF, 0x0000001FFFFFFFFF, 0x0000003FFFFFFFFF, ++ 0x0000007FFFFFFFFF, 0x000000FFFFFFFFFF, 0x000001FFFFFFFFFF, ++ 0x000003FFFFFFFFFF, 0x000007FFFFFFFFFF, 0x00000FFFFFFFFFFF, ++ 0x00001FFFFFFFFFFF, 0x00003FFFFFFFFFFF, 0x00007FFFFFFFFFFF, ++ 0x0000FFFFFFFFFFFF, 0x0001FFFFFFFFFFFF, 0x0003FFFFFFFFFFFF, ++ 0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x001FFFFFFFFFFFFF, ++ 0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF, ++ 0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF, ++ 0x0FFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF, ++ 0x7FFFFFFFFFFFFFFF, ++}; + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 // +-wuffs_base__private_implementation__high_prec_dec__to_f64( +- wuffs_base__private_implementation__high_prec_dec* h, +- uint32_t options) { +- do { +- // powers converts decimal powers of 10 to binary powers of 2. For example, +- // (10000 >> 13) is 1. It stops before the elements exceed 60, also known +- // as WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL. +- // +- // This rounds down (1<<13 is a lower bound for 1e4). Adding 1 to the array +- // element value rounds up (1<<14 is an upper bound for 1e4) while staying +- // at or below WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL. +- // +- // When starting in the range [1e+1 .. 1e+2] (i.e. h->decimal_point == +2), +- // powers[2] == 6 and so: +- // - Right shifting by 6+0 produces the range [10/64 .. 100/64] = +- // [0.156250 .. 1.56250]. The resultant h->decimal_point is +0 or +1. +- // - Right shifting by 6+1 produces the range [10/128 .. 100/128] = +- // [0.078125 .. 0.78125]. The resultant h->decimal_point is -1 or -0. +- // +- // When starting in the range [1e-3 .. 1e-2] (i.e. h->decimal_point == -2), +- // powers[2] == 6 and so: +- // - Left shifting by 6+0 produces the range [0.001*64 .. 0.01*64] = +- // [0.064 .. 0.64]. The resultant h->decimal_point is -1 or -0. +- // - Left shifting by 6+1 produces the range [0.001*128 .. 0.01*128] = +- // [0.128 .. 1.28]. The resultant h->decimal_point is +0 or +1. +- // +- // Thus, when targeting h->decimal_point being +0 or +1, use (powers[n]+0) +- // when right shifting but (powers[n]+1) when left shifting. +- static const uint32_t num_powers = 19; +- static const uint8_t powers[19] = { +- 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, // +- 33, 36, 39, 43, 46, 49, 53, 56, 59, // +- }; ++const uint32_t wuffs_private_impl__pixel_format__bits_per_channel[16] = { ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40, ++}; + +- // Handle zero and obvious extremes. The largest and smallest positive +- // finite f64 values are approximately 1.8e+308 and 4.9e-324. +- if ((h->num_digits == 0) || (h->decimal_point < -326)) { +- goto zero; +- } else if (h->decimal_point > 310) { +- goto infinity; +- } ++const char wuffs_base__note__i_o_redirect[] = "@base: I/O redirect"; ++const char wuffs_base__note__end_of_data[] = "@base: end of data"; ++const char wuffs_base__note__metadata_reported[] = "@base: metadata reported"; ++const char wuffs_base__suspension__even_more_information[] = "$base: even more information"; ++const char wuffs_base__suspension__mispositioned_read[] = "$base: mispositioned read"; ++const char wuffs_base__suspension__mispositioned_write[] = "$base: mispositioned write"; ++const char wuffs_base__suspension__short_read[] = "$base: short read"; ++const char wuffs_base__suspension__short_workbuf[] = "$base: short workbuf"; ++const char wuffs_base__suspension__short_write[] = "$base: short write"; ++const char wuffs_base__error__bad_i_o_position[] = "#base: bad I/O position"; ++const char wuffs_base__error__bad_argument_length_too_short[] = "#base: bad argument (length too short)"; ++const char wuffs_base__error__bad_argument[] = "#base: bad argument"; ++const char wuffs_base__error__bad_call_sequence[] = "#base: bad call sequence"; ++const char wuffs_base__error__bad_data[] = "#base: bad data"; ++const char wuffs_base__error__bad_receiver[] = "#base: bad receiver"; ++const char wuffs_base__error__bad_restart[] = "#base: bad restart"; ++const char wuffs_base__error__bad_sizeof_receiver[] = "#base: bad sizeof receiver"; ++const char wuffs_base__error__bad_vtable[] = "#base: bad vtable"; ++const char wuffs_base__error__bad_workbuf_length[] = "#base: bad workbuf length"; ++const char wuffs_base__error__bad_wuffs_version[] = "#base: bad wuffs version"; ++const char wuffs_base__error__cannot_return_a_suspension[] = "#base: cannot return a suspension"; ++const char wuffs_base__error__disabled_by_wuffs_config_dst_pixel_format_enable_allowlist[] = "#base: disabled by WUFFS_CONFIG__DST_PIXEL_FORMAT__ENABLE_ALLOWLIST"; ++const char wuffs_base__error__disabled_by_previous_error[] = "#base: disabled by previous error"; ++const char wuffs_base__error__initialize_falsely_claimed_already_zeroed[] = "#base: initialize falsely claimed already zeroed"; ++const char wuffs_base__error__initialize_not_called[] = "#base: initialize not called"; ++const char wuffs_base__error__insufficient_history[] = "#base: insufficient history"; ++const char wuffs_base__error__interleaved_coroutine_calls[] = "#base: interleaved coroutine calls"; ++const char wuffs_base__error__no_more_information[] = "#base: no more information"; ++const char wuffs_base__error__not_enough_data[] = "#base: not enough data"; ++const char wuffs_base__error__out_of_bounds[] = "#base: out of bounds"; ++const char wuffs_base__error__unsupported_image_dimension[] = "#base: unsupported image dimension"; ++const char wuffs_base__error__unsupported_method[] = "#base: unsupported method"; ++const char wuffs_base__error__unsupported_option[] = "#base: unsupported option"; ++const char wuffs_base__error__unsupported_pixel_swizzler_option[] = "#base: unsupported pixel swizzler option"; ++const char wuffs_base__error__too_much_data[] = "#base: too much data"; + +- // Try the fast Eisel-Lemire algorithm again. Calculating the (man, exp10) +- // pair from the high_prec_dec h is more correct but slower than the +- // approach taken in wuffs_base__parse_number_f64. The latter is optimized +- // for the common cases (e.g. assuming no underscores or a leading '+' +- // sign) rather than the full set of cases allowed by the Wuffs API. +- // +- // When we have 19 or fewer mantissa digits, run Eisel-Lemire once (trying +- // for an exact result). When we have more than 19 mantissa digits, run it +- // twice to get a lower and upper bound. We still have an exact result +- // (within f64's rounding margin) if both bounds are equal (and valid). +- uint32_t i_max = h->num_digits; +- if (i_max > 19) { +- i_max = 19; +- } +- int32_t exp10 = h->decimal_point - ((int32_t)i_max); +- if ((-307 <= exp10) && (exp10 <= 288)) { +- uint64_t man = 0; +- uint32_t i; +- for (i = 0; i < i_max; i++) { +- man = (10 * man) + h->digits[i]; +- } +- while (man != 0) { // The 'while' is just an 'if' that we can 'break'. +- int64_t r0 = +- wuffs_base__private_implementation__parse_number_f64_eisel_lemire( +- man + 0, exp10); +- if (r0 < 0) { +- break; +- } else if (h->num_digits > 19) { +- int64_t r1 = +- wuffs_base__private_implementation__parse_number_f64_eisel_lemire( +- man + 1, exp10); +- if (r1 != r0) { +- break; +- } +- } +- wuffs_base__result_f64 ret; +- ret.status.repr = NULL; +- ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64( +- ((uint64_t)r0) | (((uint64_t)(h->negative)) << 63)); +- return ret; +- } +- } ++const char wuffs_base__hasher_u32__vtable_name[] = "{vtable}wuffs_base__hasher_u32"; ++const char wuffs_base__hasher_u64__vtable_name[] = "{vtable}wuffs_base__hasher_u64"; ++const char wuffs_base__hasher_bitvec256__vtable_name[] = "{vtable}wuffs_base__hasher_bitvec256"; ++const char wuffs_base__image_decoder__vtable_name[] = "{vtable}wuffs_base__image_decoder"; ++const char wuffs_base__io_transformer__vtable_name[] = "{vtable}wuffs_base__io_transformer"; ++const char wuffs_base__token_decoder__vtable_name[] = "{vtable}wuffs_base__token_decoder"; + +- // When Eisel-Lemire fails, fall back to Simple Decimal Conversion. See +- // https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html +- // +- // Scale by powers of 2 until we're in the range [0.1 .. 10]. Equivalently, +- // that h->decimal_point is +0 or +1. +- // +- // First we shift right while at or above 10... +- const int32_t f64_bias = -1023; +- int32_t exp2 = 0; +- while (h->decimal_point > 1) { +- uint32_t n = (uint32_t)(+h->decimal_point); +- uint32_t shift = +- (n < num_powers) +- ? powers[n] +- : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL; +- +- wuffs_base__private_implementation__high_prec_dec__small_rshift(h, shift); +- if (h->decimal_point < +- -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { +- goto zero; +- } +- exp2 += (int32_t)shift; +- } +- // ...then we shift left while below 0.1. +- while (h->decimal_point < 0) { +- uint32_t shift; +- uint32_t n = (uint32_t)(-h->decimal_point); +- shift = (n < num_powers) +- // The +1 is per "when targeting h->decimal_point being +0 or +- // +1... when left shifting" in the powers comment above. +- ? (powers[n] + 1) +- : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL; ++#endif // !defined(WUFFS_CONFIG__MODULES) || ++ // defined(WUFFS_CONFIG__MODULE__BASE) || ++ // defined(WUFFS_CONFIG__MODULE__BASE__CORE) + +- wuffs_base__private_implementation__high_prec_dec__small_lshift(h, shift); +- if (h->decimal_point > +- +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { +- goto infinity; +- } +- exp2 -= (int32_t)shift; +- } ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ ++ defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES) + +- // To get from "in the range [0.1 .. 10]" to "in the range [1 .. 2]" (which +- // will give us our exponent in base-2), the mantissa's first 3 digits will +- // determine the final left shift, equal to 52 (the number of explicit f64 +- // bits) plus an additional adjustment. +- int man3 = (100 * h->digits[0]) + +- ((h->num_digits > 1) ? (10 * h->digits[1]) : 0) + +- ((h->num_digits > 2) ? h->digits[2] : 0); +- int32_t additional_lshift = 0; +- if (h->decimal_point == 0) { // The value is in [0.1 .. 1]. +- if (man3 < 125) { +- additional_lshift = +4; +- } else if (man3 < 250) { +- additional_lshift = +3; +- } else if (man3 < 500) { +- additional_lshift = +2; +- } else { +- additional_lshift = +1; +- } +- } else { // The value is in [1 .. 10]. +- if (man3 < 200) { +- additional_lshift = -0; +- } else if (man3 < 400) { +- additional_lshift = -1; +- } else if (man3 < 800) { +- additional_lshift = -2; +- } else { +- additional_lshift = -3; +- } +- } +- exp2 -= additional_lshift; +- uint32_t final_lshift = (uint32_t)(52 + additional_lshift); ++// ---------------- Interface Definitions. + +- // The minimum normal exponent is (f64_bias + 1). +- while ((f64_bias + 1) > exp2) { +- uint32_t n = (uint32_t)((f64_bias + 1) - exp2); +- if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) { +- n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL; +- } +- wuffs_base__private_implementation__high_prec_dec__small_rshift(h, n); +- exp2 += (int32_t)n; +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_base__hasher_u32__checksum_u32( ++ const wuffs_base__hasher_u32* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +- // Check for overflow. +- if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1. +- goto infinity; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { ++ const wuffs_base__hasher_u32__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->checksum_u32)(self); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- // Extract 53 bits for the mantissa (in base-2). +- wuffs_base__private_implementation__high_prec_dec__small_lshift( +- h, final_lshift); +- uint64_t man2 = +- wuffs_base__private_implementation__high_prec_dec__rounded_integer(h); ++ return 0; ++} + +- // Rounding might have added one bit. If so, shift and re-check overflow. +- if ((man2 >> 53) != 0) { +- man2 >>= 1; +- exp2++; +- if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1. +- goto infinity; +- } +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__hasher_u32__get_quirk( ++ const wuffs_base__hasher_u32* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +- // Handle subnormal numbers. +- if ((man2 >> 52) == 0) { +- exp2 = f64_bias; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { ++ const wuffs_base__hasher_u32__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->get_quirk)(self, a_key); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- // Pack the bits and return. +- uint64_t exp2_bits = +- (uint64_t)((exp2 - f64_bias) & 0x07FF); // (1 << 11) - 1. +- uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) | // (1 << 52) - 1. +- (exp2_bits << 52) | // +- (h->negative ? 0x8000000000000000 : 0); // (1 << 63). +- +- wuffs_base__result_f64 ret; +- ret.status.repr = NULL; +- ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits); +- return ret; +- } while (0); +- +-zero: +- do { +- uint64_t bits = h->negative ? 0x8000000000000000 : 0; ++ return 0; ++} + +- wuffs_base__result_f64 ret; +- ret.status.repr = NULL; +- ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits); +- return ret; +- } while (0); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__hasher_u32__set_quirk( ++ wuffs_base__hasher_u32* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +-infinity: +- do { +- if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) { +- wuffs_base__result_f64 ret; +- ret.status.repr = wuffs_base__error__bad_argument; +- ret.value = 0; +- return ret; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { ++ const wuffs_base__hasher_u32__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->set_quirk)(self, a_key, a_value); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- uint64_t bits = h->negative ? 0xFFF0000000000000 : 0x7FF0000000000000; +- +- wuffs_base__result_f64 ret; +- ret.status.repr = NULL; +- ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits); +- return ret; +- } while (0); ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); + } + +-static inline bool // +-wuffs_base__private_implementation__is_decimal_digit(uint8_t c) { +- return ('0' <= c) && (c <= '9'); +-} ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_base__hasher_u32__update( ++ wuffs_base__hasher_u32* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); ++ } + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 // +-wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options) { +- // In practice, almost all "dd.ddddE±xxx" numbers can be represented +- // losslessly by a uint64_t mantissa "dddddd" and an int32_t base-10 +- // exponent, adjusting "xxx" for the position (if present) of the decimal +- // separator '.' or ','. +- // +- // This (u64 man, i32 exp10) data structure is superficially similar to the +- // "Do It Yourself Floating Point" type from Loitsch (†), but the exponent +- // here is base-10, not base-2. +- // +- // If s's number fits in a (man, exp10), parse that pair with the +- // Eisel-Lemire algorithm. If not, or if Eisel-Lemire fails, parsing s with +- // the fallback algorithm is slower but comprehensive. +- // +- // † "Printing Floating-Point Numbers Quickly and Accurately with Integers" +- // (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf). +- // Florian Loitsch is also the primary contributor to +- // https://github.com/google/double-conversion +- do { +- // Calculating that (man, exp10) pair needs to stay within s's bounds. +- // Provided that s isn't extremely long, work on a NUL-terminated copy of +- // s's contents. The NUL byte isn't a valid part of "±dd.ddddE±xxx". +- // +- // As the pointer p walks the contents, it's faster to repeatedly check "is +- // *p a valid digit" than "is p within bounds and *p a valid digit". +- if (s.len >= 256) { +- goto fallback; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { ++ const wuffs_base__hasher_u32__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->update)(self, a_x); ++ } else if (v->vtable_name == NULL) { ++ break; + } +- uint8_t z[256]; +- memcpy(&z[0], s.ptr, s.len); +- z[s.len] = 0; +- const uint8_t* p = &z[0]; ++ v++; ++ } + +- // Look for a leading minus sign. Technically, we could also look for an +- // optional plus sign, but the "script/process-json-numbers.c with -p" +- // benchmark is noticably slower if we do. It's optional and, in practice, +- // usually absent. Let the fallback catch it. +- bool negative = (*p == '-'); +- if (negative) { +- p++; +- } ++ return wuffs_base__make_empty_struct(); ++} + +- // After walking "dd.dddd", comparing p later with p now will produce the +- // number of "d"s and "."s. +- const uint8_t* const start_of_digits_ptr = p; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_base__hasher_u32__update_u32( ++ wuffs_base__hasher_u32* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return 0; ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return 0; ++ } + +- // Walk the "d"s before a '.', 'E', NUL byte, etc. If it starts with '0', +- // it must be a single '0'. If it starts with a non-zero decimal digit, it +- // can be a sequence of decimal digits. +- // +- // Update the man variable during the walk. It's OK if man overflows now. +- // We'll detect that later. +- uint64_t man; +- if (*p == '0') { +- man = 0; +- p++; +- if (wuffs_base__private_implementation__is_decimal_digit(*p)) { +- goto fallback; +- } +- } else if (wuffs_base__private_implementation__is_decimal_digit(*p)) { +- man = ((uint8_t)(*p - '0')); +- p++; +- for (; wuffs_base__private_implementation__is_decimal_digit(*p); p++) { +- man = (10 * man) + ((uint8_t)(*p - '0')); +- } +- } else { +- goto fallback; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) { ++ const wuffs_base__hasher_u32__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->update_u32)(self, a_x); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- // Walk the "d"s after the optional decimal separator ('.' or ','), +- // updating the man and exp10 variables. +- int32_t exp10 = 0; +- if (*p == +- ((options & WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) +- ? ',' +- : '.')) { +- p++; +- const uint8_t* first_after_separator_ptr = p; +- if (!wuffs_base__private_implementation__is_decimal_digit(*p)) { +- goto fallback; +- } +- man = (10 * man) + ((uint8_t)(*p - '0')); +- p++; +- for (; wuffs_base__private_implementation__is_decimal_digit(*p); p++) { +- man = (10 * man) + ((uint8_t)(*p - '0')); +- } +- exp10 = ((int32_t)(first_after_separator_ptr - p)); +- } ++ return 0; ++} + +- // Count the number of digits: +- // - for an input of "314159", digit_count is 6. +- // - for an input of "3.14159", digit_count is 7. +- // +- // This is off-by-one if there is a decimal separator. That's OK for now. +- // We'll correct for that later. The "script/process-json-numbers.c with +- // -p" benchmark is noticably slower if we try to correct for that now. +- uint32_t digit_count = (uint32_t)(p - start_of_digits_ptr); ++// -------- + +- // Update exp10 for the optional exponent, starting with 'E' or 'e'. +- if ((*p | 0x20) == 'e') { +- p++; +- int32_t exp_sign = +1; +- if (*p == '-') { +- p++; +- exp_sign = -1; +- } else if (*p == '+') { +- p++; +- } +- if (!wuffs_base__private_implementation__is_decimal_digit(*p)) { +- goto fallback; +- } +- int32_t exp_num = ((uint8_t)(*p - '0')); +- p++; +- // The rest of the exp_num walking has a peculiar control flow but, once +- // again, the "script/process-json-numbers.c with -p" benchmark is +- // sensitive to alternative formulations. +- if (wuffs_base__private_implementation__is_decimal_digit(*p)) { +- exp_num = (10 * exp_num) + ((uint8_t)(*p - '0')); +- p++; +- } +- if (wuffs_base__private_implementation__is_decimal_digit(*p)) { +- exp_num = (10 * exp_num) + ((uint8_t)(*p - '0')); +- p++; +- } +- while (wuffs_base__private_implementation__is_decimal_digit(*p)) { +- if (exp_num > 0x1000000) { +- goto fallback; +- } +- exp_num = (10 * exp_num) + ((uint8_t)(*p - '0')); +- p++; +- } +- exp10 += exp_sign * exp_num; +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__hasher_u64__checksum_u64( ++ const wuffs_base__hasher_u64* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +- // The Wuffs API is that the original slice has no trailing data. It also +- // allows underscores, which we don't catch here but the fallback should. +- if (p != &z[s.len]) { +- goto fallback; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { ++ const wuffs_base__hasher_u64__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->checksum_u64)(self); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- // Check that the uint64_t typed man variable has not overflowed, based on +- // digit_count. +- // +- // For reference: +- // - (1 << 63) is 9223372036854775808, which has 19 decimal digits. +- // - (1 << 64) is 18446744073709551616, which has 20 decimal digits. +- // - 19 nines, 9999999999999999999, is 0x8AC7230489E7FFFF, which has 64 +- // bits and 16 hexadecimal digits. +- // - 20 nines, 99999999999999999999, is 0x56BC75E2D630FFFFF, which has 67 +- // bits and 17 hexadecimal digits. +- if (digit_count > 19) { +- // Even if we have more than 19 pseudo-digits, it's not yet definitely an +- // overflow. Recall that digit_count might be off-by-one (too large) if +- // there's a decimal separator. It will also over-report the number of +- // meaningful digits if the input looks something like "0.000dddExxx". +- // +- // We adjust by the number of leading '0's and '.'s and re-compare to 19. +- // Once again, technically, we could skip ','s too, but that perturbs the +- // "script/process-json-numbers.c with -p" benchmark. +- const uint8_t* q = start_of_digits_ptr; +- for (; (*q == '0') || (*q == '.'); q++) { +- } +- digit_count -= (uint32_t)(q - start_of_digits_ptr); +- if (digit_count > 19) { +- goto fallback; +- } +- } ++ return 0; ++} + +- // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire +- // preconditions include that exp10 is in the range [-307 ..= 288]. +- if ((exp10 < -307) || (288 < exp10)) { +- goto fallback; +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__hasher_u64__get_quirk( ++ const wuffs_base__hasher_u64* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +- // If both man and (10 ** exp10) are exactly representable by a double, we +- // don't need to run the Eisel-Lemire algorithm. +- if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) { +- double d = (double)man; +- if (exp10 >= 0) { +- d *= wuffs_base__private_implementation__f64_powers_of_10[+exp10]; +- } else { +- d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10]; +- } +- wuffs_base__result_f64 ret; +- ret.status.repr = NULL; +- ret.value = negative ? -d : +d; +- return ret; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { ++ const wuffs_base__hasher_u64__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->get_quirk)(self, a_key); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire +- // preconditions include that man is non-zero. Parsing "0" should be caught +- // by the "If both man and (10 ** exp10)" above, but "0e99" might not. +- if (man == 0) { +- goto fallback; +- } ++ return 0; ++} + +- // Our man and exp10 are in range. Run the Eisel-Lemire algorithm. +- int64_t r = +- wuffs_base__private_implementation__parse_number_f64_eisel_lemire( +- man, exp10); +- if (r < 0) { +- goto fallback; +- } +- wuffs_base__result_f64 ret; +- ret.status.repr = NULL; +- ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64( +- ((uint64_t)r) | (((uint64_t)negative) << 63)); +- return ret; +- } while (0); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__hasher_u64__set_quirk( ++ wuffs_base__hasher_u64* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +-fallback: +- do { +- wuffs_base__private_implementation__high_prec_dec h; +- wuffs_base__status status = +- wuffs_base__private_implementation__high_prec_dec__parse(&h, s, +- options); +- if (status.repr) { +- return wuffs_base__private_implementation__parse_number_f64_special( +- s, options); ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { ++ const wuffs_base__hasher_u64__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->set_quirk)(self, a_key, a_value); ++ } else if (v->vtable_name == NULL) { ++ break; + } +- return wuffs_base__private_implementation__high_prec_dec__to_f64(&h, +- options); +- } while (0); +-} ++ v++; ++ } + +-// -------- ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); ++} + +-static inline size_t // +-wuffs_base__private_implementation__render_inf(wuffs_base__slice_u8 dst, +- bool neg, +- uint32_t options) { +- if (neg) { +- if (dst.len < 4) { +- return 0; +- } +- wuffs_base__poke_u32le__no_bounds_check(dst.ptr, 0x666E492D); // '-Inf'le. +- return 4; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_base__hasher_u64__update( ++ wuffs_base__hasher_u64* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); + } + +- if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) { +- if (dst.len < 4) { +- return 0; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { ++ const wuffs_base__hasher_u64__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->update)(self, a_x); ++ } else if (v->vtable_name == NULL) { ++ break; + } +- wuffs_base__poke_u32le__no_bounds_check(dst.ptr, 0x666E492B); // '+Inf'le. +- return 4; ++ v++; + } + +- if (dst.len < 3) { +- return 0; +- } +- wuffs_base__poke_u24le__no_bounds_check(dst.ptr, 0x666E49); // 'Inf'le. +- return 3; ++ return wuffs_base__make_empty_struct(); + } + +-static inline size_t // +-wuffs_base__private_implementation__render_nan(wuffs_base__slice_u8 dst) { +- if (dst.len < 3) { ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__hasher_u64__update_u64( ++ wuffs_base__hasher_u64* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { + return 0; + } +- wuffs_base__poke_u24le__no_bounds_check(dst.ptr, 0x4E614E); // 'NaN'le. +- return 3; +-} +- +-static size_t // +-wuffs_base__private_implementation__high_prec_dec__render_exponent_absent( +- wuffs_base__slice_u8 dst, +- wuffs_base__private_implementation__high_prec_dec* h, +- uint32_t precision, +- uint32_t options) { +- size_t n = (h->negative || +- (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN)) +- ? 1 +- : 0; +- if (h->decimal_point <= 0) { +- n += 1; +- } else { +- n += (size_t)(h->decimal_point); +- } +- if (precision > 0) { +- n += precision + 1; // +1 for the '.'. ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return 0; + } + +- // Don't modify dst if the formatted number won't fit. +- if (n > dst.len) { +- return 0; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_u64__vtable_name) { ++ const wuffs_base__hasher_u64__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_u64__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->update_u64)(self, a_x); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } + +- // Align-left or align-right. +- uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT) +- ? &dst.ptr[dst.len - n] +- : &dst.ptr[0]; ++ return 0; ++} + +- // Leading "±". +- if (h->negative) { +- *ptr++ = '-'; +- } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) { +- *ptr++ = '+'; +- } ++// -------- + +- // Integral digits. +- if (h->decimal_point <= 0) { +- *ptr++ = '0'; +- } else { +- uint32_t m = +- wuffs_base__u32__min(h->num_digits, (uint32_t)(h->decimal_point)); +- uint32_t i = 0; +- for (; i < m; i++) { +- *ptr++ = (uint8_t)('0' | h->digits[i]); +- } +- for (; i < (uint32_t)(h->decimal_point); i++) { +- *ptr++ = '0'; +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__bitvec256 ++wuffs_base__hasher_bitvec256__checksum_bitvec256( ++ const wuffs_base__hasher_bitvec256* self) { ++ if (!self) { ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); + } + +- // Separator and then fractional digits. +- if (precision > 0) { +- *ptr++ = +- (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) +- ? ',' +- : '.'; +- uint32_t i = 0; +- for (; i < precision; i++) { +- uint32_t j = ((uint32_t)(h->decimal_point)) + i; +- *ptr++ = (uint8_t)('0' | ((j < h->num_digits) ? h->digits[j] : 0)); ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_bitvec256__vtable_name) { ++ const wuffs_base__hasher_bitvec256__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_bitvec256__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->checksum_bitvec256)(self); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; + } + +- return n; ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); + } + +-static size_t // +-wuffs_base__private_implementation__high_prec_dec__render_exponent_present( +- wuffs_base__slice_u8 dst, +- wuffs_base__private_implementation__high_prec_dec* h, +- uint32_t precision, +- uint32_t options) { +- int32_t exp = 0; +- if (h->num_digits > 0) { +- exp = h->decimal_point - 1; +- } +- bool negative_exp = exp < 0; +- if (negative_exp) { +- exp = -exp; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__hasher_bitvec256__get_quirk( ++ const wuffs_base__hasher_bitvec256* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; + } +- +- size_t n = (h->negative || +- (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN)) +- ? 4 +- : 3; // Mininum 3 bytes: first digit and then "e±". +- if (precision > 0) { +- n += precision + 1; // +1 for the '.'. ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } +- n += (exp < 100) ? 2 : 3; + +- // Don't modify dst if the formatted number won't fit. +- if (n > dst.len) { +- return 0; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_bitvec256__vtable_name) { ++ const wuffs_base__hasher_bitvec256__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_bitvec256__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->get_quirk)(self, a_key); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } + +- // Align-left or align-right. +- uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT) +- ? &dst.ptr[dst.len - n] +- : &dst.ptr[0]; ++ return 0; ++} + +- // Leading "±". +- if (h->negative) { +- *ptr++ = '-'; +- } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) { +- *ptr++ = '+'; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__hasher_bitvec256__set_quirk( ++ wuffs_base__hasher_bitvec256* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- +- // Integral digit. +- if (h->num_digits > 0) { +- *ptr++ = (uint8_t)('0' | h->digits[0]); +- } else { +- *ptr++ = '0'; ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } + +- // Separator and then fractional digits. +- if (precision > 0) { +- *ptr++ = +- (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) +- ? ',' +- : '.'; +- uint32_t i = 1; +- uint32_t j = wuffs_base__u32__min(h->num_digits, precision + 1); +- for (; i < j; i++) { +- *ptr++ = (uint8_t)('0' | h->digits[i]); +- } +- for (; i <= precision; i++) { +- *ptr++ = '0'; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_bitvec256__vtable_name) { ++ const wuffs_base__hasher_bitvec256__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_bitvec256__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->set_quirk)(self, a_key, a_value); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; + } + +- // Exponent: "e±" and then 2 or 3 digits. +- *ptr++ = 'e'; +- *ptr++ = negative_exp ? '-' : '+'; +- if (exp < 10) { +- *ptr++ = '0'; +- *ptr++ = (uint8_t)('0' | exp); +- } else if (exp < 100) { +- *ptr++ = (uint8_t)('0' | (exp / 10)); +- *ptr++ = (uint8_t)('0' | (exp % 10)); +- } else { +- int32_t e = exp / 100; +- exp -= e * 100; +- *ptr++ = (uint8_t)('0' | e); +- *ptr++ = (uint8_t)('0' | (exp / 10)); +- *ptr++ = (uint8_t)('0' | (exp % 10)); +- } +- +- return n; ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); + } + +-WUFFS_BASE__MAYBE_STATIC size_t // +-wuffs_base__render_number_f64(wuffs_base__slice_u8 dst, +- double x, +- uint32_t precision, +- uint32_t options) { +- // Decompose x (64 bits) into negativity (1 bit), base-2 exponent (11 bits +- // with a -1023 bias) and mantissa (52 bits). +- uint64_t bits = wuffs_base__ieee_754_bit_representation__from_f64_to_u64(x); +- bool neg = (bits >> 63) != 0; +- int32_t exp2 = ((int32_t)(bits >> 52)) & 0x7FF; +- uint64_t man = bits & 0x000FFFFFFFFFFFFFul; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_base__hasher_bitvec256__update( ++ wuffs_base__hasher_bitvec256* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); ++ } + +- // Apply the exponent bias and set the implicit top bit of the mantissa, +- // unless x is subnormal. Also take care of Inf and NaN. +- if (exp2 == 0x7FF) { +- if (man != 0) { +- return wuffs_base__private_implementation__render_nan(dst); ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_bitvec256__vtable_name) { ++ const wuffs_base__hasher_bitvec256__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_bitvec256__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->update)(self, a_x); ++ } else if (v->vtable_name == NULL) { ++ break; + } +- return wuffs_base__private_implementation__render_inf(dst, neg, options); +- } else if (exp2 == 0) { +- exp2 = -1022; +- } else { +- exp2 -= 1023; +- man |= 0x0010000000000000ul; ++ v++; + } + +- // Ensure that precision isn't too large. +- if (precision > 4095) { +- precision = 4095; ++ return wuffs_base__make_empty_struct(); ++} ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__bitvec256 ++wuffs_base__hasher_bitvec256__update_bitvec256( ++ wuffs_base__hasher_bitvec256* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); + } + +- // Convert from the (neg, exp2, man) tuple to an HPD. +- wuffs_base__private_implementation__high_prec_dec h; +- wuffs_base__private_implementation__high_prec_dec__assign(&h, man, neg); +- if (h.num_digits > 0) { +- wuffs_base__private_implementation__high_prec_dec__lshift( +- &h, exp2 - 52); // 52 mantissa bits. ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__hasher_bitvec256__vtable_name) { ++ const wuffs_base__hasher_bitvec256__func_ptrs* func_ptrs = ++ (const wuffs_base__hasher_bitvec256__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->update_bitvec256)(self, a_x); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } + +- // Handle the "%e" and "%f" formats. +- switch (options & (WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT | +- WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT)) { +- case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT: // The "%"f" format. +- if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) { +- wuffs_base__private_implementation__high_prec_dec__round_just_enough( +- &h, exp2, man); +- int32_t p = ((int32_t)(h.num_digits)) - h.decimal_point; +- precision = ((uint32_t)(wuffs_base__i32__max(0, p))); +- } else { +- wuffs_base__private_implementation__high_prec_dec__round_nearest( +- &h, ((int32_t)precision) + h.decimal_point); +- } +- return wuffs_base__private_implementation__high_prec_dec__render_exponent_absent( +- dst, &h, precision, options); ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); ++} + +- case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT: // The "%e" format. +- if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) { +- wuffs_base__private_implementation__high_prec_dec__round_just_enough( +- &h, exp2, man); +- precision = (h.num_digits > 0) ? (h.num_digits - 1) : 0; +- } else { +- wuffs_base__private_implementation__high_prec_dec__round_nearest( +- &h, ((int32_t)precision) + 1); +- } +- return wuffs_base__private_implementation__high_prec_dec__render_exponent_present( +- dst, &h, precision, options); ++// -------- ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__image_decoder__decode_frame( ++ wuffs_base__image_decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } + +- // We have the "%g" format and so precision means the number of significant +- // digits, not the number of digits after the decimal separator. Perform +- // rounding and determine whether to use "%e" or "%f". +- int32_t e_threshold = 0; +- if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) { +- wuffs_base__private_implementation__high_prec_dec__round_just_enough( +- &h, exp2, man); +- precision = h.num_digits; +- e_threshold = 6; +- } else { +- if (precision == 0) { +- precision = 1; +- } +- wuffs_base__private_implementation__high_prec_dec__round_nearest( +- &h, ((int32_t)precision)); +- e_threshold = ((int32_t)precision); +- int32_t nd = ((int32_t)(h.num_digits)); +- if ((e_threshold > nd) && (nd >= h.decimal_point)) { +- e_threshold = nd; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->decode_frame)(self, a_dst, a_src, a_blend, a_workbuf, a_opts); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; + } + +- // Use the "%e" format if the exponent is large. +- int32_t e = h.decimal_point - 1; +- if ((e < -4) || (e_threshold <= e)) { +- uint32_t p = wuffs_base__u32__min(precision, h.num_digits); +- return wuffs_base__private_implementation__high_prec_dec__render_exponent_present( +- dst, &h, (p > 0) ? (p - 1) : 0, options); ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); ++} ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__image_decoder__decode_frame_config( ++ wuffs_base__image_decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } + +- // Use the "%f" format otherwise. +- int32_t p = ((int32_t)precision); +- if (p > h.decimal_point) { +- p = ((int32_t)(h.num_digits)); ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->decode_frame_config)(self, a_dst, a_src); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } +- precision = ((uint32_t)(wuffs_base__i32__max(0, p - h.decimal_point))); +- return wuffs_base__private_implementation__high_prec_dec__render_exponent_absent( +- dst, &h, precision, options); ++ ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || +- // defined(WUFFS_CONFIG__MODULE__BASE) || +- // defined(WUFFS_CONFIG__MODULE__BASE__FLOATCONV) ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__image_decoder__decode_image_config( ++ wuffs_base__image_decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ +- defined(WUFFS_CONFIG__MODULE__BASE__INTCONV) ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->decode_image_config)(self, a_dst, a_src); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } + +-// ---------------- Integer ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); ++} + +-// wuffs_base__parse_number__foo_digits entries are 0x00 for invalid digits, +-// and (0x80 | v) for valid digits, where v is the 4 bit value. ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_base__image_decoder__frame_dirty_rect( ++ const wuffs_base__image_decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } + +-static const uint8_t wuffs_base__parse_number__decimal_digits[256] = { +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F. +- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // 0x30 ..= 0x37. '0'-'7'. +- 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. '8'-'9'. ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->frame_dirty_rect)(self); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } + +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 ..= 0x47. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 ..= 0x67. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F. ++ return wuffs_base__utility__empty_rect_ie_u32(); ++} + +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 ..= 0x87. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 ..= 0x8F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 ..= 0x97. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 ..= 0x9F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 ..= 0xA7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 ..= 0xAF. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 ..= 0xB7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 ..= 0xBF. ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__image_decoder__get_quirk( ++ const wuffs_base__image_decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 ..= 0xC7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 ..= 0xCF. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 ..= 0xD7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 ..= 0xDF. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 ..= 0xE7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 ..= 0xEF. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 ..= 0xF7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF8 ..= 0xFF. +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +-}; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->get_quirk)(self, a_key); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } + +-static const uint8_t wuffs_base__parse_number__hexadecimal_digits[256] = { +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F. +- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // 0x30 ..= 0x37. '0'-'7'. +- 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. '8'-'9'. ++ return 0; ++} + +- 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00, // 0x40 ..= 0x47. 'A'-'F'. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F. +- 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00, // 0x60 ..= 0x67. 'a'-'f'. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F. ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_base__image_decoder__num_animation_loops( ++ const wuffs_base__image_decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 ..= 0x87. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 ..= 0x8F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 ..= 0x97. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 ..= 0x9F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 ..= 0xA7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 ..= 0xAF. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 ..= 0xB7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 ..= 0xBF. ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->num_animation_loops)(self); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } + +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 ..= 0xC7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 ..= 0xCF. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 ..= 0xD7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 ..= 0xDF. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 ..= 0xE7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 ..= 0xEF. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 ..= 0xF7. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF8 ..= 0xFF. +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +-}; ++ return 0; ++} + +-static const uint8_t wuffs_base__private_implementation__encode_base16[16] = { +- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 0x00 ..= 0x07. +- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, // 0x08 ..= 0x0F. +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__image_decoder__num_decoded_frame_configs( ++ const wuffs_base__image_decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +-// -------- ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->num_decoded_frame_configs)(self); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__result_i64 // +-wuffs_base__parse_number_i64(wuffs_base__slice_u8 s, uint32_t options) { +- uint8_t* p = s.ptr; +- uint8_t* q = s.ptr + s.len; ++ return 0; ++} + +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { +- for (; (p < q) && (*p == '_'); p++) { +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__image_decoder__num_decoded_frames( ++ const wuffs_base__image_decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } + +- bool negative = false; +- if (p >= q) { +- goto fail_bad_argument; +- } else if (*p == '-') { +- p++; +- negative = true; +- } else if (*p == '+') { +- p++; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->num_decoded_frames)(self); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } + +- do { +- wuffs_base__result_u64 r = wuffs_base__parse_number_u64( +- wuffs_base__make_slice_u8(p, (size_t)(q - p)), options); +- if (r.status.repr != NULL) { +- wuffs_base__result_i64 ret; +- ret.status.repr = r.status.repr; +- ret.value = 0; +- return ret; +- } else if (negative) { +- if (r.value < 0x8000000000000000) { +- wuffs_base__result_i64 ret; +- ret.status.repr = NULL; +- ret.value = -(int64_t)(r.value); +- return ret; +- } else if (r.value == 0x8000000000000000) { +- wuffs_base__result_i64 ret; +- ret.status.repr = NULL; +- ret.value = INT64_MIN; +- return ret; +- } +- goto fail_out_of_bounds; +- } else if (r.value > 0x7FFFFFFFFFFFFFFF) { +- goto fail_out_of_bounds; +- } else { +- wuffs_base__result_i64 ret; +- ret.status.repr = NULL; +- ret.value = +(int64_t)(r.value); +- return ret; +- } +- } while (0); +- +-fail_bad_argument: +- do { +- wuffs_base__result_i64 ret; +- ret.status.repr = wuffs_base__error__bad_argument; +- ret.value = 0; +- return ret; +- } while (0); +- +-fail_out_of_bounds: +- do { +- wuffs_base__result_i64 ret; +- ret.status.repr = wuffs_base__error__out_of_bounds; +- ret.value = 0; +- return ret; +- } while (0); ++ return 0; + } + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__result_u64 // +-wuffs_base__parse_number_u64(wuffs_base__slice_u8 s, uint32_t options) { +- uint8_t* p = s.ptr; +- uint8_t* q = s.ptr + s.len; +- +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { +- for (; (p < q) && (*p == '_'); p++) { +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__image_decoder__restart_frame( ++ wuffs_base__image_decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } + +- if (p >= q) { +- goto fail_bad_argument; +- +- } else if (*p == '0') { +- p++; +- if (p >= q) { +- goto ok_zero; +- } +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { +- if (*p == '_') { +- p++; +- for (; p < q; p++) { +- if (*p != '_') { +- if (options & +- WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES) { +- goto decimal; +- } +- goto fail_bad_argument; +- } +- } +- goto ok_zero; +- } ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->restart_frame)(self, a_index, a_io_position); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- if ((*p == 'x') || (*p == 'X')) { +- p++; +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { +- for (; (p < q) && (*p == '_'); p++) { +- } +- } +- if (p < q) { +- goto hexadecimal; +- } ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); ++} + +- } else if ((*p == 'd') || (*p == 'D')) { +- p++; +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { +- for (; (p < q) && (*p == '_'); p++) { +- } +- } +- if (p < q) { +- goto decimal; +- } +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__image_decoder__set_quirk( ++ wuffs_base__image_decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +- if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES) { +- goto decimal; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->set_quirk)(self, a_key, a_value); ++ } else if (v->vtable_name == NULL) { ++ break; + } +- goto fail_bad_argument; ++ v++; + } + +-decimal: +- do { +- uint64_t v = wuffs_base__parse_number__decimal_digits[*p++]; +- if (v == 0) { +- goto fail_bad_argument; +- } +- v &= 0x0F; ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); ++} + +- // UINT64_MAX is 18446744073709551615, which is ((10 * max10) + max1). +- const uint64_t max10 = 1844674407370955161u; +- const uint8_t max1 = 5; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_base__image_decoder__set_report_metadata( ++ wuffs_base__image_decoder* self, ++ uint32_t a_fourcc, ++ bool a_report) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); ++ } + +- for (; p < q; p++) { +- if ((*p == '_') && +- (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { +- continue; +- } +- uint8_t digit = wuffs_base__parse_number__decimal_digits[*p]; +- if (digit == 0) { +- goto fail_bad_argument; +- } +- digit &= 0x0F; +- if ((v > max10) || ((v == max10) && (digit > max1))) { +- goto fail_out_of_bounds; +- } +- v = (10 * v) + ((uint64_t)(digit)); ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->set_report_metadata)(self, a_fourcc, a_report); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- wuffs_base__result_u64 ret; +- ret.status.repr = NULL; +- ret.value = v; +- return ret; +- } while (0); ++ return wuffs_base__make_empty_struct(); ++} + +-hexadecimal: +- do { +- uint64_t v = wuffs_base__parse_number__hexadecimal_digits[*p++]; +- if (v == 0) { +- goto fail_bad_argument; +- } +- v &= 0x0F; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__image_decoder__tell_me_more( ++ wuffs_base__image_decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +- for (; p < q; p++) { +- if ((*p == '_') && +- (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { +- continue; +- } +- uint8_t digit = wuffs_base__parse_number__hexadecimal_digits[*p]; +- if (digit == 0) { +- goto fail_bad_argument; +- } +- digit &= 0x0F; +- if ((v >> 60) != 0) { +- goto fail_out_of_bounds; +- } +- v = (v << 4) | ((uint64_t)(digit)); ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->tell_me_more)(self, a_dst, a_minfo, a_src); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; ++ } + +- wuffs_base__result_u64 ret; +- ret.status.repr = NULL; +- ret.value = v; +- return ret; +- } while (0); ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); ++} + +-ok_zero: +- do { +- wuffs_base__result_u64 ret; +- ret.status.repr = NULL; +- ret.value = 0; +- return ret; +- } while (0); ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_base__image_decoder__workbuf_len( ++ const wuffs_base__image_decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } + +-fail_bad_argument: +- do { +- wuffs_base__result_u64 ret; +- ret.status.repr = wuffs_base__error__bad_argument; +- ret.value = 0; +- return ret; +- } while (0); ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) { ++ const wuffs_base__image_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->workbuf_len)(self); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } + +-fail_out_of_bounds: +- do { +- wuffs_base__result_u64 ret; +- ret.status.repr = wuffs_base__error__out_of_bounds; +- ret.value = 0; +- return ret; +- } while (0); ++ return wuffs_base__utility__empty_range_ii_u64(); + } + + // -------- + +-// wuffs_base__render_number__first_hundred contains the decimal encodings of +-// the first one hundred numbers [0 ..= 99]. +-static const uint8_t wuffs_base__render_number__first_hundred[200] = { +- '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', // +- '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', // +- '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', // +- '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', // +- '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', // +- '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', // +- '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', // +- '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', // +- '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', // +- '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', // +- '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', // +- '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', // +- '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', // +- '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', // +- '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', // +- '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', // +- '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', // +- '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', // +- '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', // +- '9', '5', '9', '6', '9', '7', '9', '8', '9', '9', // +-}; +- +-static size_t // +-wuffs_base__private_implementation__render_number_u64(wuffs_base__slice_u8 dst, +- uint64_t x, +- uint32_t options, +- bool neg) { +- uint8_t buf[WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL]; +- uint8_t* ptr = &buf[0] + sizeof(buf); +- +- while (x >= 100) { +- size_t index = ((size_t)((x % 100) * 2)); +- x /= 100; +- uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0]; +- uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1]; +- ptr -= 2; +- ptr[0] = s0; +- ptr[1] = s1; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_base__io_transformer__dst_history_retain_length( ++ const wuffs_base__io_transformer* self) { ++ if (!self) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); + } +- +- if (x < 10) { +- ptr -= 1; +- ptr[0] = (uint8_t)('0' + x); +- } else { +- size_t index = ((size_t)(x * 2)); +- uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0]; +- uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1]; +- ptr -= 2; +- ptr[0] = s0; +- ptr[1] = s1; ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); + } + +- if (neg) { +- ptr -= 1; +- ptr[0] = '-'; +- } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) { +- ptr -= 1; +- ptr[0] = '+'; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { ++ const wuffs_base__io_transformer__func_ptrs* func_ptrs = ++ (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->dst_history_retain_length)(self); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } + +- size_t n = sizeof(buf) - ((size_t)(ptr - &buf[0])); +- if (n > dst.len) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++} ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__io_transformer__get_quirk( ++ const wuffs_base__io_transformer* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { + return 0; + } +- memcpy(dst.ptr + ((options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT) +- ? (dst.len - n) +- : 0), +- ptr, n); +- return n; +-} + +-WUFFS_BASE__MAYBE_STATIC size_t // +-wuffs_base__render_number_i64(wuffs_base__slice_u8 dst, +- int64_t x, +- uint32_t options) { +- uint64_t u = (uint64_t)x; +- bool neg = x < 0; +- if (neg) { +- u = 1 + ~u; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { ++ const wuffs_base__io_transformer__func_ptrs* func_ptrs = ++ (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->get_quirk)(self, a_key); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } +- return wuffs_base__private_implementation__render_number_u64(dst, u, options, +- neg); +-} + +-WUFFS_BASE__MAYBE_STATIC size_t // +-wuffs_base__render_number_u64(wuffs_base__slice_u8 dst, +- uint64_t x, +- uint32_t options) { +- return wuffs_base__private_implementation__render_number_u64(dst, x, options, +- false); ++ return 0; + } + +-// ---------------- Base-16 ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__io_transformer__set_quirk( ++ wuffs_base__io_transformer* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +-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; +- 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; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { ++ const wuffs_base__io_transformer__func_ptrs* func_ptrs = ++ (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->set_quirk)(self, a_key, a_value); ++ } else if (v->vtable_name == NULL) { ++ break; + } ++ v++; + } + +- uint8_t* d = dst.ptr; +- uint8_t* s = src.ptr; +- size_t n = len; ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); ++} + +- while (n--) { +- *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) | +- (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F)); +- d += 1; +- s += 2; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__io_transformer__transform_io( ++ wuffs_base__io_transformer* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } + +- o.num_dst = len; +- o.num_src = len * 2; +- return o; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { ++ const wuffs_base__io_transformer__func_ptrs* func_ptrs = ++ (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->transform_io)(self, a_dst, a_src, a_workbuf); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } ++ ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); + } + +-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; +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_base__io_transformer__workbuf_len( ++ const wuffs_base__io_transformer* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); + } + +- uint8_t* d = dst.ptr; +- uint8_t* s = src.ptr; +- size_t n = len; +- +- while (n--) { +- *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) | +- (wuffs_base__parse_number__hexadecimal_digits[s[3]] & 0x0F)); +- d += 1; +- s += 4; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__io_transformer__vtable_name) { ++ const wuffs_base__io_transformer__func_ptrs* func_ptrs = ++ (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->workbuf_len)(self); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } + +- o.num_dst = len; +- o.num_src = len * 4; +- return o; ++ return wuffs_base__utility__empty_range_ii_u64(); + } + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output // +-wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 src, +- bool src_closed, +- uint32_t options) { +- wuffs_base__transform__output o; +- size_t dst_len2 = dst.len / 2; +- size_t len; +- if (dst_len2 < src.len) { +- len = dst_len2; +- o.status.repr = wuffs_base__suspension__short_write; +- } else { +- len = src.len; +- if (!src_closed) { +- o.status.repr = wuffs_base__suspension__short_read; +- } else { +- o.status.repr = NULL; +- } +- } ++// -------- + +- uint8_t* d = dst.ptr; +- uint8_t* s = src.ptr; +- size_t n = len; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__token_decoder__decode_tokens( ++ wuffs_base__token_decoder* self, ++ wuffs_base__token_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +- while (n--) { +- uint8_t c = *s; +- d[0] = wuffs_base__private_implementation__encode_base16[c >> 4]; +- d[1] = wuffs_base__private_implementation__encode_base16[c & 0x0F]; +- d += 2; +- s += 1; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { ++ const wuffs_base__token_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->decode_tokens)(self, a_dst, a_src, a_workbuf); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } + +- o.num_dst = len * 2; +- o.num_src = len; +- return o; ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); + } + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output // +-wuffs_base__base_16__encode4(wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 src, +- bool src_closed, +- uint32_t options) { +- wuffs_base__transform__output o; +- size_t dst_len4 = dst.len / 4; +- size_t len; +- if (dst_len4 < src.len) { +- len = dst_len4; +- o.status.repr = wuffs_base__suspension__short_write; +- } else { +- len = src.len; +- if (!src_closed) { +- o.status.repr = wuffs_base__suspension__short_read; +- } else { +- o.status.repr = NULL; +- } ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_base__token_decoder__get_quirk( ++ const wuffs_base__token_decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } + +- uint8_t* d = dst.ptr; +- uint8_t* s = src.ptr; +- size_t n = len; +- +- while (n--) { +- uint8_t c = *s; +- d[0] = '\\'; +- d[1] = 'x'; +- d[2] = wuffs_base__private_implementation__encode_base16[c >> 4]; +- d[3] = wuffs_base__private_implementation__encode_base16[c & 0x0F]; +- d += 4; +- s += 1; ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { ++ const wuffs_base__token_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->get_quirk)(self, a_key); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; + } + +- o.num_dst = len * 4; +- o.num_src = len; +- return o; ++ return 0; + } + +-// ---------------- Base-64 ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_base__token_decoder__set_quirk( ++ wuffs_base__token_decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +-// The two base-64 alphabets, std and url, differ only in the last two codes. +-// - std: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" +-// - url: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { ++ const wuffs_base__token_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->set_quirk)(self, a_key, a_value); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } + +-static const uint8_t wuffs_base__base_64__decode_std[256] = { +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27. +- 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, // 0x28 ..= 0x2F. +- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37. +- 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F. ++ return wuffs_base__make_status(wuffs_base__error__bad_vtable); ++} + +- 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47. +- 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F. +- 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57. +- 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x58 ..= 0x5F. +- 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67. +- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F. +- 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77. +- 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F. ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_base__token_decoder__workbuf_len( ++ const wuffs_base__token_decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } + +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB0 ..= 0xB7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB8 ..= 0xBF. ++ const wuffs_base__vtable* v = &self->private_impl.first_vtable; ++ int i; ++ for (i = 0; i < 63; i++) { ++ if (v->vtable_name == wuffs_base__token_decoder__vtable_name) { ++ const wuffs_base__token_decoder__func_ptrs* func_ptrs = ++ (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers); ++ return (*func_ptrs->workbuf_len)(self); ++ } else if (v->vtable_name == NULL) { ++ break; ++ } ++ v++; ++ } + +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC0 ..= 0xC7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC8 ..= 0xCF. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD0 ..= 0xD7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD8 ..= 0xDF. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE0 ..= 0xE7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE8 ..= 0xEF. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF. +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +-}; ++ return wuffs_base__utility__empty_range_ii_u64(); ++} + +-static const uint8_t wuffs_base__base_64__decode_url[256] = { +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, // 0x28 ..= 0x2F. +- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37. +- 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F. ++#endif // !defined(WUFFS_CONFIG__MODULES) || ++ // defined(WUFFS_CONFIG__MODULE__BASE) || ++ // defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES) + +- 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47. +- 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F. +- 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57. +- 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x3F, // 0x58 ..= 0x5F. +- 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67. +- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F. +- 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77. +- 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F. ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ ++ defined(WUFFS_CONFIG__MODULE__BASE__FLOATCONV) + +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB0 ..= 0xB7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB8 ..= 0xBF. ++// ---------------- IEEE 754 Floating Point + +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC0 ..= 0xC7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC8 ..= 0xCF. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD0 ..= 0xD7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD8 ..= 0xDF. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE0 ..= 0xE7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE8 ..= 0xEF. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF. +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F ++// The etc__hpd_left_shift and etc__powers_of_5 tables were printed by ++// script/print-hpd-left-shift.go. That script has an optional -comments flag, ++// whose output is not copied here, which prints further detail. ++// ++// These tables are used in ++// wuffs_private_impl__high_prec_dec__lshift_num_new_digits. ++ ++// wuffs_private_impl__hpd_left_shift[i] encodes the number of new digits ++// created after multiplying a positive integer by (1 << i): the additional ++// length in the decimal representation. For example, shifting "234" by 3 ++// (equivalent to multiplying by 8) will produce "1872". Going from a 3-length ++// string to a 4-length string means that 1 new digit was added (and existing ++// digits may have changed). ++// ++// Shifting by i can add either N or N-1 new digits, depending on whether the ++// original positive integer compares >= or < to the i'th power of 5 (as 10 ++// equals 2 * 5). Comparison is lexicographic, not numerical. ++// ++// For example, shifting by 4 (i.e. multiplying by 16) can add 1 or 2 new ++// digits, depending on a lexicographic comparison to (5 ** 4), i.e. "625": ++// - ("1" << 4) is "16", which adds 1 new digit. ++// - ("5678" << 4) is "90848", which adds 1 new digit. ++// - ("624" << 4) is "9984", which adds 1 new digit. ++// - ("62498" << 4) is "999968", which adds 1 new digit. ++// - ("625" << 4) is "10000", which adds 2 new digits. ++// - ("625001" << 4) is "10000016", which adds 2 new digits. ++// - ("7008" << 4) is "112128", which adds 2 new digits. ++// - ("99" << 4) is "1584", which adds 2 new digits. ++// ++// Thus, when i is 4, N is 2 and (5 ** i) is "625". This etc__hpd_left_shift ++// array encodes this as: ++// - etc__hpd_left_shift[4] is 0x1006 = (2 << 11) | 0x0006. ++// - etc__hpd_left_shift[5] is 0x1009 = (? << 11) | 0x0009. ++// where the ? isn't relevant for i == 4. ++// ++// The high 5 bits of etc__hpd_left_shift[i] is N, the higher of the two ++// possible number of new digits. The low 11 bits are an offset into the ++// etc__powers_of_5 array (of length 0x051C, so offsets fit in 11 bits). When i ++// is 4, its offset and the next one is 6 and 9, and etc__powers_of_5[6 .. 9] ++// is the string "\x06\x02\x05", so the relevant power of 5 is "625". ++// ++// Thanks to Ken Thompson for the original idea. ++static const uint16_t wuffs_private_impl__hpd_left_shift[65] = { ++ 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, ++ 0x181D, 0x2024, 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, ++ 0x3073, 0x3080, 0x388E, 0x389C, 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, ++ 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, 0x5180, 0x5998, 0x59B0, ++ 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, 0x72AA, ++ 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, ++ 0x8C02, 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, ++ 0x051C, 0x051C, + }; + +-static const uint8_t wuffs_base__base_64__encode_std[64] = { +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // 0x00 ..= 0x07. +- 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, // 0x08 ..= 0x0F. +- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, // 0x10 ..= 0x17. +- 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 0x18 ..= 0x1F. +- 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, // 0x20 ..= 0x27. +- 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, // 0x28 ..= 0x2F. +- 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, // 0x30 ..= 0x37. +- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F, // 0x38 ..= 0x3F. ++// wuffs_private_impl__powers_of_5 contains the powers of 5, concatenated ++// together: "5", "25", "125", "625", "3125", etc. ++static const uint8_t wuffs_private_impl__powers_of_5[0x051C] = { ++ 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, ++ 0, 6, 2, 5, 1, 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, ++ 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, 1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, ++ 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, 5, 1, 5, 2, 5, 8, 7, 8, 9, 0, ++ 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6, 9, 7, 2, 6, 5, ++ 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1, ++ 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, ++ 1, 8, 5, 7, 9, 1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, ++ 8, 1, 2, 5, 5, 9, 6, 0, 4, 6, 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, ++ 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1, 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, ++ 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2, 3, 8, 2, 8, 1, ++ 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6, ++ 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, ++ 7, 4, 6, 1, 5, 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, ++ 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, 5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, ++ 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5, 3, 2, 1, 8, 2, 6, 9, 3, 4, 8, ++ 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4, 6, 7, 4, 0, 7, ++ 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6, ++ 1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, ++ 0, 6, 6, 4, 0, 6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, ++ 0, 3, 3, 2, 0, 3, 1, 2, 5, 3, 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, ++ 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, ++ 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, 7, 0, 1, 7, 7, ++ 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5, ++ 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, ++ 7, 3, 6, 7, 5, 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, ++ 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, 7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, ++ 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8, 8, 6, 0, 8, 0, 8, 0, 1, 4, 8, ++ 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0, 9, 4, 3, 0, 4, ++ 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0, ++ 8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, ++ 6, 2, 5, 7, 1, 0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, ++ 2, 4, 2, 6, 7, 5, 7, 8, 1, 2, 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, ++ 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, ++ 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0, 6, 6, 8, 9, 4, ++ 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3, ++ 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, ++ 5, 0, 0, 6, 2, 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, ++ 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, 9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, ++ 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1, 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, ++ 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8, 2, 0, 3, 1, 2, ++ 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, ++ 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, ++ 6, 2, 8, 9, 1, 3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, ++ 1, 2, 5, 1, 3, 8, 7, 7, 7, 8, 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, ++ 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, 6, 2, 5, 6, 9, 3, 8, 8, 9, 3, ++ 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, 5, 5, 6, 7, 6, ++ 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1, ++ 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, ++ 7, 3, 4, 7, 2, 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, ++ 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, 8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, ++ 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2, 2, 4, 0, 6, 9, 5, 9, 5, 3, 3, ++ 6, 9, 1, 4, 0, 6, 2, 5, + }; + +-static const uint8_t wuffs_base__base_64__encode_url[64] = { +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // 0x00 ..= 0x07. +- 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, // 0x08 ..= 0x0F. +- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, // 0x10 ..= 0x17. +- 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 0x18 ..= 0x1F. +- 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, // 0x20 ..= 0x27. +- 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, // 0x28 ..= 0x2F. +- 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, // 0x30 ..= 0x37. +- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2D, 0x5F, // 0x38 ..= 0x3F. ++// -------- ++ ++// wuffs_private_impl__powers_of_10 contains truncated approximations to the ++// powers of 10, ranging from 1e-307 to 1e+288 inclusive, as 596 pairs of ++// uint64_t values (a 128-bit mantissa). ++// ++// There's also an implicit third column (implied by a linear formula involving ++// the base-10 exponent) that is the base-2 exponent, biased by a magic ++// constant. That constant (1214 or 0x04BE) equals 1023 + 191. 1023 is the bias ++// for IEEE 754 double-precision floating point. 191 is ((3 * 64) - 1) and ++// wuffs_private_impl__parse_number_f64_eisel_lemire works with ++// multiples-of-64-bit mantissas. ++// ++// For example, the third row holds the approximation to 1e-305: ++// 0xE0B62E29_29ABA83C_331ACDAB_FE94DE87 * (2 ** (0x0049 - 0x04BE)) ++// ++// Similarly, 1e+4 is approximated by: ++// 0x9C400000_00000000_00000000_00000000 * (2 ** (0x044C - 0x04BE)) ++// ++// Similarly, 1e+68 is approximated by: ++// 0xED63A231_D4C4FB27_4CA7AAA8_63EE4BDD * (2 ** (0x0520 - 0x04BE)) ++// ++// This table was generated by by script/print-mpb-powers-of-10.go ++static const uint64_t wuffs_private_impl__powers_of_10[596][2] = { ++ {0xA5D3B6D479F8E056, 0x8FD0C16206306BAB}, // 1e-307 ++ {0x8F48A4899877186C, 0xB3C4F1BA87BC8696}, // 1e-306 ++ {0x331ACDABFE94DE87, 0xE0B62E2929ABA83C}, // 1e-305 ++ {0x9FF0C08B7F1D0B14, 0x8C71DCD9BA0B4925}, // 1e-304 ++ {0x07ECF0AE5EE44DD9, 0xAF8E5410288E1B6F}, // 1e-303 ++ {0xC9E82CD9F69D6150, 0xDB71E91432B1A24A}, // 1e-302 ++ {0xBE311C083A225CD2, 0x892731AC9FAF056E}, // 1e-301 ++ {0x6DBD630A48AAF406, 0xAB70FE17C79AC6CA}, // 1e-300 ++ {0x092CBBCCDAD5B108, 0xD64D3D9DB981787D}, // 1e-299 ++ {0x25BBF56008C58EA5, 0x85F0468293F0EB4E}, // 1e-298 ++ {0xAF2AF2B80AF6F24E, 0xA76C582338ED2621}, // 1e-297 ++ {0x1AF5AF660DB4AEE1, 0xD1476E2C07286FAA}, // 1e-296 ++ {0x50D98D9FC890ED4D, 0x82CCA4DB847945CA}, // 1e-295 ++ {0xE50FF107BAB528A0, 0xA37FCE126597973C}, // 1e-294 ++ {0x1E53ED49A96272C8, 0xCC5FC196FEFD7D0C}, // 1e-293 ++ {0x25E8E89C13BB0F7A, 0xFF77B1FCBEBCDC4F}, // 1e-292 ++ {0x77B191618C54E9AC, 0x9FAACF3DF73609B1}, // 1e-291 ++ {0xD59DF5B9EF6A2417, 0xC795830D75038C1D}, // 1e-290 ++ {0x4B0573286B44AD1D, 0xF97AE3D0D2446F25}, // 1e-289 ++ {0x4EE367F9430AEC32, 0x9BECCE62836AC577}, // 1e-288 ++ {0x229C41F793CDA73F, 0xC2E801FB244576D5}, // 1e-287 ++ {0x6B43527578C1110F, 0xF3A20279ED56D48A}, // 1e-286 ++ {0x830A13896B78AAA9, 0x9845418C345644D6}, // 1e-285 ++ {0x23CC986BC656D553, 0xBE5691EF416BD60C}, // 1e-284 ++ {0x2CBFBE86B7EC8AA8, 0xEDEC366B11C6CB8F}, // 1e-283 ++ {0x7BF7D71432F3D6A9, 0x94B3A202EB1C3F39}, // 1e-282 ++ {0xDAF5CCD93FB0CC53, 0xB9E08A83A5E34F07}, // 1e-281 ++ {0xD1B3400F8F9CFF68, 0xE858AD248F5C22C9}, // 1e-280 ++ {0x23100809B9C21FA1, 0x91376C36D99995BE}, // 1e-279 ++ {0xABD40A0C2832A78A, 0xB58547448FFFFB2D}, // 1e-278 ++ {0x16C90C8F323F516C, 0xE2E69915B3FFF9F9}, // 1e-277 ++ {0xAE3DA7D97F6792E3, 0x8DD01FAD907FFC3B}, // 1e-276 ++ {0x99CD11CFDF41779C, 0xB1442798F49FFB4A}, // 1e-275 ++ {0x40405643D711D583, 0xDD95317F31C7FA1D}, // 1e-274 ++ {0x482835EA666B2572, 0x8A7D3EEF7F1CFC52}, // 1e-273 ++ {0xDA3243650005EECF, 0xAD1C8EAB5EE43B66}, // 1e-272 ++ {0x90BED43E40076A82, 0xD863B256369D4A40}, // 1e-271 ++ {0x5A7744A6E804A291, 0x873E4F75E2224E68}, // 1e-270 ++ {0x711515D0A205CB36, 0xA90DE3535AAAE202}, // 1e-269 ++ {0x0D5A5B44CA873E03, 0xD3515C2831559A83}, // 1e-268 ++ {0xE858790AFE9486C2, 0x8412D9991ED58091}, // 1e-267 ++ {0x626E974DBE39A872, 0xA5178FFF668AE0B6}, // 1e-266 ++ {0xFB0A3D212DC8128F, 0xCE5D73FF402D98E3}, // 1e-265 ++ {0x7CE66634BC9D0B99, 0x80FA687F881C7F8E}, // 1e-264 ++ {0x1C1FFFC1EBC44E80, 0xA139029F6A239F72}, // 1e-263 ++ {0xA327FFB266B56220, 0xC987434744AC874E}, // 1e-262 ++ {0x4BF1FF9F0062BAA8, 0xFBE9141915D7A922}, // 1e-261 ++ {0x6F773FC3603DB4A9, 0x9D71AC8FADA6C9B5}, // 1e-260 ++ {0xCB550FB4384D21D3, 0xC4CE17B399107C22}, // 1e-259 ++ {0x7E2A53A146606A48, 0xF6019DA07F549B2B}, // 1e-258 ++ {0x2EDA7444CBFC426D, 0x99C102844F94E0FB}, // 1e-257 ++ {0xFA911155FEFB5308, 0xC0314325637A1939}, // 1e-256 ++ {0x793555AB7EBA27CA, 0xF03D93EEBC589F88}, // 1e-255 ++ {0x4BC1558B2F3458DE, 0x96267C7535B763B5}, // 1e-254 ++ {0x9EB1AAEDFB016F16, 0xBBB01B9283253CA2}, // 1e-253 ++ {0x465E15A979C1CADC, 0xEA9C227723EE8BCB}, // 1e-252 ++ {0x0BFACD89EC191EC9, 0x92A1958A7675175F}, // 1e-251 ++ {0xCEF980EC671F667B, 0xB749FAED14125D36}, // 1e-250 ++ {0x82B7E12780E7401A, 0xE51C79A85916F484}, // 1e-249 ++ {0xD1B2ECB8B0908810, 0x8F31CC0937AE58D2}, // 1e-248 ++ {0x861FA7E6DCB4AA15, 0xB2FE3F0B8599EF07}, // 1e-247 ++ {0x67A791E093E1D49A, 0xDFBDCECE67006AC9}, // 1e-246 ++ {0xE0C8BB2C5C6D24E0, 0x8BD6A141006042BD}, // 1e-245 ++ {0x58FAE9F773886E18, 0xAECC49914078536D}, // 1e-244 ++ {0xAF39A475506A899E, 0xDA7F5BF590966848}, // 1e-243 ++ {0x6D8406C952429603, 0x888F99797A5E012D}, // 1e-242 ++ {0xC8E5087BA6D33B83, 0xAAB37FD7D8F58178}, // 1e-241 ++ {0xFB1E4A9A90880A64, 0xD5605FCDCF32E1D6}, // 1e-240 ++ {0x5CF2EEA09A55067F, 0x855C3BE0A17FCD26}, // 1e-239 ++ {0xF42FAA48C0EA481E, 0xA6B34AD8C9DFC06F}, // 1e-238 ++ {0xF13B94DAF124DA26, 0xD0601D8EFC57B08B}, // 1e-237 ++ {0x76C53D08D6B70858, 0x823C12795DB6CE57}, // 1e-236 ++ {0x54768C4B0C64CA6E, 0xA2CB1717B52481ED}, // 1e-235 ++ {0xA9942F5DCF7DFD09, 0xCB7DDCDDA26DA268}, // 1e-234 ++ {0xD3F93B35435D7C4C, 0xFE5D54150B090B02}, // 1e-233 ++ {0xC47BC5014A1A6DAF, 0x9EFA548D26E5A6E1}, // 1e-232 ++ {0x359AB6419CA1091B, 0xC6B8E9B0709F109A}, // 1e-231 ++ {0xC30163D203C94B62, 0xF867241C8CC6D4C0}, // 1e-230 ++ {0x79E0DE63425DCF1D, 0x9B407691D7FC44F8}, // 1e-229 ++ {0x985915FC12F542E4, 0xC21094364DFB5636}, // 1e-228 ++ {0x3E6F5B7B17B2939D, 0xF294B943E17A2BC4}, // 1e-227 ++ {0xA705992CEECF9C42, 0x979CF3CA6CEC5B5A}, // 1e-226 ++ {0x50C6FF782A838353, 0xBD8430BD08277231}, // 1e-225 ++ {0xA4F8BF5635246428, 0xECE53CEC4A314EBD}, // 1e-224 ++ {0x871B7795E136BE99, 0x940F4613AE5ED136}, // 1e-223 ++ {0x28E2557B59846E3F, 0xB913179899F68584}, // 1e-222 ++ {0x331AEADA2FE589CF, 0xE757DD7EC07426E5}, // 1e-221 ++ {0x3FF0D2C85DEF7621, 0x9096EA6F3848984F}, // 1e-220 ++ {0x0FED077A756B53A9, 0xB4BCA50B065ABE63}, // 1e-219 ++ {0xD3E8495912C62894, 0xE1EBCE4DC7F16DFB}, // 1e-218 ++ {0x64712DD7ABBBD95C, 0x8D3360F09CF6E4BD}, // 1e-217 ++ {0xBD8D794D96AACFB3, 0xB080392CC4349DEC}, // 1e-216 ++ {0xECF0D7A0FC5583A0, 0xDCA04777F541C567}, // 1e-215 ++ {0xF41686C49DB57244, 0x89E42CAAF9491B60}, // 1e-214 ++ {0x311C2875C522CED5, 0xAC5D37D5B79B6239}, // 1e-213 ++ {0x7D633293366B828B, 0xD77485CB25823AC7}, // 1e-212 ++ {0xAE5DFF9C02033197, 0x86A8D39EF77164BC}, // 1e-211 ++ {0xD9F57F830283FDFC, 0xA8530886B54DBDEB}, // 1e-210 ++ {0xD072DF63C324FD7B, 0xD267CAA862A12D66}, // 1e-209 ++ {0x4247CB9E59F71E6D, 0x8380DEA93DA4BC60}, // 1e-208 ++ {0x52D9BE85F074E608, 0xA46116538D0DEB78}, // 1e-207 ++ {0x67902E276C921F8B, 0xCD795BE870516656}, // 1e-206 ++ {0x00BA1CD8A3DB53B6, 0x806BD9714632DFF6}, // 1e-205 ++ {0x80E8A40ECCD228A4, 0xA086CFCD97BF97F3}, // 1e-204 ++ {0x6122CD128006B2CD, 0xC8A883C0FDAF7DF0}, // 1e-203 ++ {0x796B805720085F81, 0xFAD2A4B13D1B5D6C}, // 1e-202 ++ {0xCBE3303674053BB0, 0x9CC3A6EEC6311A63}, // 1e-201 ++ {0xBEDBFC4411068A9C, 0xC3F490AA77BD60FC}, // 1e-200 ++ {0xEE92FB5515482D44, 0xF4F1B4D515ACB93B}, // 1e-199 ++ {0x751BDD152D4D1C4A, 0x991711052D8BF3C5}, // 1e-198 ++ {0xD262D45A78A0635D, 0xBF5CD54678EEF0B6}, // 1e-197 ++ {0x86FB897116C87C34, 0xEF340A98172AACE4}, // 1e-196 ++ {0xD45D35E6AE3D4DA0, 0x9580869F0E7AAC0E}, // 1e-195 ++ {0x8974836059CCA109, 0xBAE0A846D2195712}, // 1e-194 ++ {0x2BD1A438703FC94B, 0xE998D258869FACD7}, // 1e-193 ++ {0x7B6306A34627DDCF, 0x91FF83775423CC06}, // 1e-192 ++ {0x1A3BC84C17B1D542, 0xB67F6455292CBF08}, // 1e-191 ++ {0x20CABA5F1D9E4A93, 0xE41F3D6A7377EECA}, // 1e-190 ++ {0x547EB47B7282EE9C, 0x8E938662882AF53E}, // 1e-189 ++ {0xE99E619A4F23AA43, 0xB23867FB2A35B28D}, // 1e-188 ++ {0x6405FA00E2EC94D4, 0xDEC681F9F4C31F31}, // 1e-187 ++ {0xDE83BC408DD3DD04, 0x8B3C113C38F9F37E}, // 1e-186 ++ {0x9624AB50B148D445, 0xAE0B158B4738705E}, // 1e-185 ++ {0x3BADD624DD9B0957, 0xD98DDAEE19068C76}, // 1e-184 ++ {0xE54CA5D70A80E5D6, 0x87F8A8D4CFA417C9}, // 1e-183 ++ {0x5E9FCF4CCD211F4C, 0xA9F6D30A038D1DBC}, // 1e-182 ++ {0x7647C3200069671F, 0xD47487CC8470652B}, // 1e-181 ++ {0x29ECD9F40041E073, 0x84C8D4DFD2C63F3B}, // 1e-180 ++ {0xF468107100525890, 0xA5FB0A17C777CF09}, // 1e-179 ++ {0x7182148D4066EEB4, 0xCF79CC9DB955C2CC}, // 1e-178 ++ {0xC6F14CD848405530, 0x81AC1FE293D599BF}, // 1e-177 ++ {0xB8ADA00E5A506A7C, 0xA21727DB38CB002F}, // 1e-176 ++ {0xA6D90811F0E4851C, 0xCA9CF1D206FDC03B}, // 1e-175 ++ {0x908F4A166D1DA663, 0xFD442E4688BD304A}, // 1e-174 ++ {0x9A598E4E043287FE, 0x9E4A9CEC15763E2E}, // 1e-173 ++ {0x40EFF1E1853F29FD, 0xC5DD44271AD3CDBA}, // 1e-172 ++ {0xD12BEE59E68EF47C, 0xF7549530E188C128}, // 1e-171 ++ {0x82BB74F8301958CE, 0x9A94DD3E8CF578B9}, // 1e-170 ++ {0xE36A52363C1FAF01, 0xC13A148E3032D6E7}, // 1e-169 ++ {0xDC44E6C3CB279AC1, 0xF18899B1BC3F8CA1}, // 1e-168 ++ {0x29AB103A5EF8C0B9, 0x96F5600F15A7B7E5}, // 1e-167 ++ {0x7415D448F6B6F0E7, 0xBCB2B812DB11A5DE}, // 1e-166 ++ {0x111B495B3464AD21, 0xEBDF661791D60F56}, // 1e-165 ++ {0xCAB10DD900BEEC34, 0x936B9FCEBB25C995}, // 1e-164 ++ {0x3D5D514F40EEA742, 0xB84687C269EF3BFB}, // 1e-163 ++ {0x0CB4A5A3112A5112, 0xE65829B3046B0AFA}, // 1e-162 ++ {0x47F0E785EABA72AB, 0x8FF71A0FE2C2E6DC}, // 1e-161 ++ {0x59ED216765690F56, 0xB3F4E093DB73A093}, // 1e-160 ++ {0x306869C13EC3532C, 0xE0F218B8D25088B8}, // 1e-159 ++ {0x1E414218C73A13FB, 0x8C974F7383725573}, // 1e-158 ++ {0xE5D1929EF90898FA, 0xAFBD2350644EEACF}, // 1e-157 ++ {0xDF45F746B74ABF39, 0xDBAC6C247D62A583}, // 1e-156 ++ {0x6B8BBA8C328EB783, 0x894BC396CE5DA772}, // 1e-155 ++ {0x066EA92F3F326564, 0xAB9EB47C81F5114F}, // 1e-154 ++ {0xC80A537B0EFEFEBD, 0xD686619BA27255A2}, // 1e-153 ++ {0xBD06742CE95F5F36, 0x8613FD0145877585}, // 1e-152 ++ {0x2C48113823B73704, 0xA798FC4196E952E7}, // 1e-151 ++ {0xF75A15862CA504C5, 0xD17F3B51FCA3A7A0}, // 1e-150 ++ {0x9A984D73DBE722FB, 0x82EF85133DE648C4}, // 1e-149 ++ {0xC13E60D0D2E0EBBA, 0xA3AB66580D5FDAF5}, // 1e-148 ++ {0x318DF905079926A8, 0xCC963FEE10B7D1B3}, // 1e-147 ++ {0xFDF17746497F7052, 0xFFBBCFE994E5C61F}, // 1e-146 ++ {0xFEB6EA8BEDEFA633, 0x9FD561F1FD0F9BD3}, // 1e-145 ++ {0xFE64A52EE96B8FC0, 0xC7CABA6E7C5382C8}, // 1e-144 ++ {0x3DFDCE7AA3C673B0, 0xF9BD690A1B68637B}, // 1e-143 ++ {0x06BEA10CA65C084E, 0x9C1661A651213E2D}, // 1e-142 ++ {0x486E494FCFF30A62, 0xC31BFA0FE5698DB8}, // 1e-141 ++ {0x5A89DBA3C3EFCCFA, 0xF3E2F893DEC3F126}, // 1e-140 ++ {0xF89629465A75E01C, 0x986DDB5C6B3A76B7}, // 1e-139 ++ {0xF6BBB397F1135823, 0xBE89523386091465}, // 1e-138 ++ {0x746AA07DED582E2C, 0xEE2BA6C0678B597F}, // 1e-137 ++ {0xA8C2A44EB4571CDC, 0x94DB483840B717EF}, // 1e-136 ++ {0x92F34D62616CE413, 0xBA121A4650E4DDEB}, // 1e-135 ++ {0x77B020BAF9C81D17, 0xE896A0D7E51E1566}, // 1e-134 ++ {0x0ACE1474DC1D122E, 0x915E2486EF32CD60}, // 1e-133 ++ {0x0D819992132456BA, 0xB5B5ADA8AAFF80B8}, // 1e-132 ++ {0x10E1FFF697ED6C69, 0xE3231912D5BF60E6}, // 1e-131 ++ {0xCA8D3FFA1EF463C1, 0x8DF5EFABC5979C8F}, // 1e-130 ++ {0xBD308FF8A6B17CB2, 0xB1736B96B6FD83B3}, // 1e-129 ++ {0xAC7CB3F6D05DDBDE, 0xDDD0467C64BCE4A0}, // 1e-128 ++ {0x6BCDF07A423AA96B, 0x8AA22C0DBEF60EE4}, // 1e-127 ++ {0x86C16C98D2C953C6, 0xAD4AB7112EB3929D}, // 1e-126 ++ {0xE871C7BF077BA8B7, 0xD89D64D57A607744}, // 1e-125 ++ {0x11471CD764AD4972, 0x87625F056C7C4A8B}, // 1e-124 ++ {0xD598E40D3DD89BCF, 0xA93AF6C6C79B5D2D}, // 1e-123 ++ {0x4AFF1D108D4EC2C3, 0xD389B47879823479}, // 1e-122 ++ {0xCEDF722A585139BA, 0x843610CB4BF160CB}, // 1e-121 ++ {0xC2974EB4EE658828, 0xA54394FE1EEDB8FE}, // 1e-120 ++ {0x733D226229FEEA32, 0xCE947A3DA6A9273E}, // 1e-119 ++ {0x0806357D5A3F525F, 0x811CCC668829B887}, // 1e-118 ++ {0xCA07C2DCB0CF26F7, 0xA163FF802A3426A8}, // 1e-117 ++ {0xFC89B393DD02F0B5, 0xC9BCFF6034C13052}, // 1e-116 ++ {0xBBAC2078D443ACE2, 0xFC2C3F3841F17C67}, // 1e-115 ++ {0xD54B944B84AA4C0D, 0x9D9BA7832936EDC0}, // 1e-114 ++ {0x0A9E795E65D4DF11, 0xC5029163F384A931}, // 1e-113 ++ {0x4D4617B5FF4A16D5, 0xF64335BCF065D37D}, // 1e-112 ++ {0x504BCED1BF8E4E45, 0x99EA0196163FA42E}, // 1e-111 ++ {0xE45EC2862F71E1D6, 0xC06481FB9BCF8D39}, // 1e-110 ++ {0x5D767327BB4E5A4C, 0xF07DA27A82C37088}, // 1e-109 ++ {0x3A6A07F8D510F86F, 0x964E858C91BA2655}, // 1e-108 ++ {0x890489F70A55368B, 0xBBE226EFB628AFEA}, // 1e-107 ++ {0x2B45AC74CCEA842E, 0xEADAB0ABA3B2DBE5}, // 1e-106 ++ {0x3B0B8BC90012929D, 0x92C8AE6B464FC96F}, // 1e-105 ++ {0x09CE6EBB40173744, 0xB77ADA0617E3BBCB}, // 1e-104 ++ {0xCC420A6A101D0515, 0xE55990879DDCAABD}, // 1e-103 ++ {0x9FA946824A12232D, 0x8F57FA54C2A9EAB6}, // 1e-102 ++ {0x47939822DC96ABF9, 0xB32DF8E9F3546564}, // 1e-101 ++ {0x59787E2B93BC56F7, 0xDFF9772470297EBD}, // 1e-100 ++ {0x57EB4EDB3C55B65A, 0x8BFBEA76C619EF36}, // 1e-99 ++ {0xEDE622920B6B23F1, 0xAEFAE51477A06B03}, // 1e-98 ++ {0xE95FAB368E45ECED, 0xDAB99E59958885C4}, // 1e-97 ++ {0x11DBCB0218EBB414, 0x88B402F7FD75539B}, // 1e-96 ++ {0xD652BDC29F26A119, 0xAAE103B5FCD2A881}, // 1e-95 ++ {0x4BE76D3346F0495F, 0xD59944A37C0752A2}, // 1e-94 ++ {0x6F70A4400C562DDB, 0x857FCAE62D8493A5}, // 1e-93 ++ {0xCB4CCD500F6BB952, 0xA6DFBD9FB8E5B88E}, // 1e-92 ++ {0x7E2000A41346A7A7, 0xD097AD07A71F26B2}, // 1e-91 ++ {0x8ED400668C0C28C8, 0x825ECC24C873782F}, // 1e-90 ++ {0x728900802F0F32FA, 0xA2F67F2DFA90563B}, // 1e-89 ++ {0x4F2B40A03AD2FFB9, 0xCBB41EF979346BCA}, // 1e-88 ++ {0xE2F610C84987BFA8, 0xFEA126B7D78186BC}, // 1e-87 ++ {0x0DD9CA7D2DF4D7C9, 0x9F24B832E6B0F436}, // 1e-86 ++ {0x91503D1C79720DBB, 0xC6EDE63FA05D3143}, // 1e-85 ++ {0x75A44C6397CE912A, 0xF8A95FCF88747D94}, // 1e-84 ++ {0xC986AFBE3EE11ABA, 0x9B69DBE1B548CE7C}, // 1e-83 ++ {0xFBE85BADCE996168, 0xC24452DA229B021B}, // 1e-82 ++ {0xFAE27299423FB9C3, 0xF2D56790AB41C2A2}, // 1e-81 ++ {0xDCCD879FC967D41A, 0x97C560BA6B0919A5}, // 1e-80 ++ {0x5400E987BBC1C920, 0xBDB6B8E905CB600F}, // 1e-79 ++ {0x290123E9AAB23B68, 0xED246723473E3813}, // 1e-78 ++ {0xF9A0B6720AAF6521, 0x9436C0760C86E30B}, // 1e-77 ++ {0xF808E40E8D5B3E69, 0xB94470938FA89BCE}, // 1e-76 ++ {0xB60B1D1230B20E04, 0xE7958CB87392C2C2}, // 1e-75 ++ {0xB1C6F22B5E6F48C2, 0x90BD77F3483BB9B9}, // 1e-74 ++ {0x1E38AEB6360B1AF3, 0xB4ECD5F01A4AA828}, // 1e-73 ++ {0x25C6DA63C38DE1B0, 0xE2280B6C20DD5232}, // 1e-72 ++ {0x579C487E5A38AD0E, 0x8D590723948A535F}, // 1e-71 ++ {0x2D835A9DF0C6D851, 0xB0AF48EC79ACE837}, // 1e-70 ++ {0xF8E431456CF88E65, 0xDCDB1B2798182244}, // 1e-69 ++ {0x1B8E9ECB641B58FF, 0x8A08F0F8BF0F156B}, // 1e-68 ++ {0xE272467E3D222F3F, 0xAC8B2D36EED2DAC5}, // 1e-67 ++ {0x5B0ED81DCC6ABB0F, 0xD7ADF884AA879177}, // 1e-66 ++ {0x98E947129FC2B4E9, 0x86CCBB52EA94BAEA}, // 1e-65 ++ {0x3F2398D747B36224, 0xA87FEA27A539E9A5}, // 1e-64 ++ {0x8EEC7F0D19A03AAD, 0xD29FE4B18E88640E}, // 1e-63 ++ {0x1953CF68300424AC, 0x83A3EEEEF9153E89}, // 1e-62 ++ {0x5FA8C3423C052DD7, 0xA48CEAAAB75A8E2B}, // 1e-61 ++ {0x3792F412CB06794D, 0xCDB02555653131B6}, // 1e-60 ++ {0xE2BBD88BBEE40BD0, 0x808E17555F3EBF11}, // 1e-59 ++ {0x5B6ACEAEAE9D0EC4, 0xA0B19D2AB70E6ED6}, // 1e-58 ++ {0xF245825A5A445275, 0xC8DE047564D20A8B}, // 1e-57 ++ {0xEED6E2F0F0D56712, 0xFB158592BE068D2E}, // 1e-56 ++ {0x55464DD69685606B, 0x9CED737BB6C4183D}, // 1e-55 ++ {0xAA97E14C3C26B886, 0xC428D05AA4751E4C}, // 1e-54 ++ {0xD53DD99F4B3066A8, 0xF53304714D9265DF}, // 1e-53 ++ {0xE546A8038EFE4029, 0x993FE2C6D07B7FAB}, // 1e-52 ++ {0xDE98520472BDD033, 0xBF8FDB78849A5F96}, // 1e-51 ++ {0x963E66858F6D4440, 0xEF73D256A5C0F77C}, // 1e-50 ++ {0xDDE7001379A44AA8, 0x95A8637627989AAD}, // 1e-49 ++ {0x5560C018580D5D52, 0xBB127C53B17EC159}, // 1e-48 ++ {0xAAB8F01E6E10B4A6, 0xE9D71B689DDE71AF}, // 1e-47 ++ {0xCAB3961304CA70E8, 0x9226712162AB070D}, // 1e-46 ++ {0x3D607B97C5FD0D22, 0xB6B00D69BB55C8D1}, // 1e-45 ++ {0x8CB89A7DB77C506A, 0xE45C10C42A2B3B05}, // 1e-44 ++ {0x77F3608E92ADB242, 0x8EB98A7A9A5B04E3}, // 1e-43 ++ {0x55F038B237591ED3, 0xB267ED1940F1C61C}, // 1e-42 ++ {0x6B6C46DEC52F6688, 0xDF01E85F912E37A3}, // 1e-41 ++ {0x2323AC4B3B3DA015, 0x8B61313BBABCE2C6}, // 1e-40 ++ {0xABEC975E0A0D081A, 0xAE397D8AA96C1B77}, // 1e-39 ++ {0x96E7BD358C904A21, 0xD9C7DCED53C72255}, // 1e-38 ++ {0x7E50D64177DA2E54, 0x881CEA14545C7575}, // 1e-37 ++ {0xDDE50BD1D5D0B9E9, 0xAA242499697392D2}, // 1e-36 ++ {0x955E4EC64B44E864, 0xD4AD2DBFC3D07787}, // 1e-35 ++ {0xBD5AF13BEF0B113E, 0x84EC3C97DA624AB4}, // 1e-34 ++ {0xECB1AD8AEACDD58E, 0xA6274BBDD0FADD61}, // 1e-33 ++ {0x67DE18EDA5814AF2, 0xCFB11EAD453994BA}, // 1e-32 ++ {0x80EACF948770CED7, 0x81CEB32C4B43FCF4}, // 1e-31 ++ {0xA1258379A94D028D, 0xA2425FF75E14FC31}, // 1e-30 ++ {0x096EE45813A04330, 0xCAD2F7F5359A3B3E}, // 1e-29 ++ {0x8BCA9D6E188853FC, 0xFD87B5F28300CA0D}, // 1e-28 ++ {0x775EA264CF55347D, 0x9E74D1B791E07E48}, // 1e-27 ++ {0x95364AFE032A819D, 0xC612062576589DDA}, // 1e-26 ++ {0x3A83DDBD83F52204, 0xF79687AED3EEC551}, // 1e-25 ++ {0xC4926A9672793542, 0x9ABE14CD44753B52}, // 1e-24 ++ {0x75B7053C0F178293, 0xC16D9A0095928A27}, // 1e-23 ++ {0x5324C68B12DD6338, 0xF1C90080BAF72CB1}, // 1e-22 ++ {0xD3F6FC16EBCA5E03, 0x971DA05074DA7BEE}, // 1e-21 ++ {0x88F4BB1CA6BCF584, 0xBCE5086492111AEA}, // 1e-20 ++ {0x2B31E9E3D06C32E5, 0xEC1E4A7DB69561A5}, // 1e-19 ++ {0x3AFF322E62439FCF, 0x9392EE8E921D5D07}, // 1e-18 ++ {0x09BEFEB9FAD487C2, 0xB877AA3236A4B449}, // 1e-17 ++ {0x4C2EBE687989A9B3, 0xE69594BEC44DE15B}, // 1e-16 ++ {0x0F9D37014BF60A10, 0x901D7CF73AB0ACD9}, // 1e-15 ++ {0x538484C19EF38C94, 0xB424DC35095CD80F}, // 1e-14 ++ {0x2865A5F206B06FB9, 0xE12E13424BB40E13}, // 1e-13 ++ {0xF93F87B7442E45D3, 0x8CBCCC096F5088CB}, // 1e-12 ++ {0xF78F69A51539D748, 0xAFEBFF0BCB24AAFE}, // 1e-11 ++ {0xB573440E5A884D1B, 0xDBE6FECEBDEDD5BE}, // 1e-10 ++ {0x31680A88F8953030, 0x89705F4136B4A597}, // 1e-9 ++ {0xFDC20D2B36BA7C3D, 0xABCC77118461CEFC}, // 1e-8 ++ {0x3D32907604691B4C, 0xD6BF94D5E57A42BC}, // 1e-7 ++ {0xA63F9A49C2C1B10F, 0x8637BD05AF6C69B5}, // 1e-6 ++ {0x0FCF80DC33721D53, 0xA7C5AC471B478423}, // 1e-5 ++ {0xD3C36113404EA4A8, 0xD1B71758E219652B}, // 1e-4 ++ {0x645A1CAC083126E9, 0x83126E978D4FDF3B}, // 1e-3 ++ {0x3D70A3D70A3D70A3, 0xA3D70A3D70A3D70A}, // 1e-2 ++ {0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC}, // 1e-1 ++ {0x0000000000000000, 0x8000000000000000}, // 1e0 ++ {0x0000000000000000, 0xA000000000000000}, // 1e1 ++ {0x0000000000000000, 0xC800000000000000}, // 1e2 ++ {0x0000000000000000, 0xFA00000000000000}, // 1e3 ++ {0x0000000000000000, 0x9C40000000000000}, // 1e4 ++ {0x0000000000000000, 0xC350000000000000}, // 1e5 ++ {0x0000000000000000, 0xF424000000000000}, // 1e6 ++ {0x0000000000000000, 0x9896800000000000}, // 1e7 ++ {0x0000000000000000, 0xBEBC200000000000}, // 1e8 ++ {0x0000000000000000, 0xEE6B280000000000}, // 1e9 ++ {0x0000000000000000, 0x9502F90000000000}, // 1e10 ++ {0x0000000000000000, 0xBA43B74000000000}, // 1e11 ++ {0x0000000000000000, 0xE8D4A51000000000}, // 1e12 ++ {0x0000000000000000, 0x9184E72A00000000}, // 1e13 ++ {0x0000000000000000, 0xB5E620F480000000}, // 1e14 ++ {0x0000000000000000, 0xE35FA931A0000000}, // 1e15 ++ {0x0000000000000000, 0x8E1BC9BF04000000}, // 1e16 ++ {0x0000000000000000, 0xB1A2BC2EC5000000}, // 1e17 ++ {0x0000000000000000, 0xDE0B6B3A76400000}, // 1e18 ++ {0x0000000000000000, 0x8AC7230489E80000}, // 1e19 ++ {0x0000000000000000, 0xAD78EBC5AC620000}, // 1e20 ++ {0x0000000000000000, 0xD8D726B7177A8000}, // 1e21 ++ {0x0000000000000000, 0x878678326EAC9000}, // 1e22 ++ {0x0000000000000000, 0xA968163F0A57B400}, // 1e23 ++ {0x0000000000000000, 0xD3C21BCECCEDA100}, // 1e24 ++ {0x0000000000000000, 0x84595161401484A0}, // 1e25 ++ {0x0000000000000000, 0xA56FA5B99019A5C8}, // 1e26 ++ {0x0000000000000000, 0xCECB8F27F4200F3A}, // 1e27 ++ {0x4000000000000000, 0x813F3978F8940984}, // 1e28 ++ {0x5000000000000000, 0xA18F07D736B90BE5}, // 1e29 ++ {0xA400000000000000, 0xC9F2C9CD04674EDE}, // 1e30 ++ {0x4D00000000000000, 0xFC6F7C4045812296}, // 1e31 ++ {0xF020000000000000, 0x9DC5ADA82B70B59D}, // 1e32 ++ {0x6C28000000000000, 0xC5371912364CE305}, // 1e33 ++ {0xC732000000000000, 0xF684DF56C3E01BC6}, // 1e34 ++ {0x3C7F400000000000, 0x9A130B963A6C115C}, // 1e35 ++ {0x4B9F100000000000, 0xC097CE7BC90715B3}, // 1e36 ++ {0x1E86D40000000000, 0xF0BDC21ABB48DB20}, // 1e37 ++ {0x1314448000000000, 0x96769950B50D88F4}, // 1e38 ++ {0x17D955A000000000, 0xBC143FA4E250EB31}, // 1e39 ++ {0x5DCFAB0800000000, 0xEB194F8E1AE525FD}, // 1e40 ++ {0x5AA1CAE500000000, 0x92EFD1B8D0CF37BE}, // 1e41 ++ {0xF14A3D9E40000000, 0xB7ABC627050305AD}, // 1e42 ++ {0x6D9CCD05D0000000, 0xE596B7B0C643C719}, // 1e43 ++ {0xE4820023A2000000, 0x8F7E32CE7BEA5C6F}, // 1e44 ++ {0xDDA2802C8A800000, 0xB35DBF821AE4F38B}, // 1e45 ++ {0xD50B2037AD200000, 0xE0352F62A19E306E}, // 1e46 ++ {0x4526F422CC340000, 0x8C213D9DA502DE45}, // 1e47 ++ {0x9670B12B7F410000, 0xAF298D050E4395D6}, // 1e48 ++ {0x3C0CDD765F114000, 0xDAF3F04651D47B4C}, // 1e49 ++ {0xA5880A69FB6AC800, 0x88D8762BF324CD0F}, // 1e50 ++ {0x8EEA0D047A457A00, 0xAB0E93B6EFEE0053}, // 1e51 ++ {0x72A4904598D6D880, 0xD5D238A4ABE98068}, // 1e52 ++ {0x47A6DA2B7F864750, 0x85A36366EB71F041}, // 1e53 ++ {0x999090B65F67D924, 0xA70C3C40A64E6C51}, // 1e54 ++ {0xFFF4B4E3F741CF6D, 0xD0CF4B50CFE20765}, // 1e55 ++ {0xBFF8F10E7A8921A4, 0x82818F1281ED449F}, // 1e56 ++ {0xAFF72D52192B6A0D, 0xA321F2D7226895C7}, // 1e57 ++ {0x9BF4F8A69F764490, 0xCBEA6F8CEB02BB39}, // 1e58 ++ {0x02F236D04753D5B4, 0xFEE50B7025C36A08}, // 1e59 ++ {0x01D762422C946590, 0x9F4F2726179A2245}, // 1e60 ++ {0x424D3AD2B7B97EF5, 0xC722F0EF9D80AAD6}, // 1e61 ++ {0xD2E0898765A7DEB2, 0xF8EBAD2B84E0D58B}, // 1e62 ++ {0x63CC55F49F88EB2F, 0x9B934C3B330C8577}, // 1e63 ++ {0x3CBF6B71C76B25FB, 0xC2781F49FFCFA6D5}, // 1e64 ++ {0x8BEF464E3945EF7A, 0xF316271C7FC3908A}, // 1e65 ++ {0x97758BF0E3CBB5AC, 0x97EDD871CFDA3A56}, // 1e66 ++ {0x3D52EEED1CBEA317, 0xBDE94E8E43D0C8EC}, // 1e67 ++ {0x4CA7AAA863EE4BDD, 0xED63A231D4C4FB27}, // 1e68 ++ {0x8FE8CAA93E74EF6A, 0x945E455F24FB1CF8}, // 1e69 ++ {0xB3E2FD538E122B44, 0xB975D6B6EE39E436}, // 1e70 ++ {0x60DBBCA87196B616, 0xE7D34C64A9C85D44}, // 1e71 ++ {0xBC8955E946FE31CD, 0x90E40FBEEA1D3A4A}, // 1e72 ++ {0x6BABAB6398BDBE41, 0xB51D13AEA4A488DD}, // 1e73 ++ {0xC696963C7EED2DD1, 0xE264589A4DCDAB14}, // 1e74 ++ {0xFC1E1DE5CF543CA2, 0x8D7EB76070A08AEC}, // 1e75 ++ {0x3B25A55F43294BCB, 0xB0DE65388CC8ADA8}, // 1e76 ++ {0x49EF0EB713F39EBE, 0xDD15FE86AFFAD912}, // 1e77 ++ {0x6E3569326C784337, 0x8A2DBF142DFCC7AB}, // 1e78 ++ {0x49C2C37F07965404, 0xACB92ED9397BF996}, // 1e79 ++ {0xDC33745EC97BE906, 0xD7E77A8F87DAF7FB}, // 1e80 ++ {0x69A028BB3DED71A3, 0x86F0AC99B4E8DAFD}, // 1e81 ++ {0xC40832EA0D68CE0C, 0xA8ACD7C0222311BC}, // 1e82 ++ {0xF50A3FA490C30190, 0xD2D80DB02AABD62B}, // 1e83 ++ {0x792667C6DA79E0FA, 0x83C7088E1AAB65DB}, // 1e84 ++ {0x577001B891185938, 0xA4B8CAB1A1563F52}, // 1e85 ++ {0xED4C0226B55E6F86, 0xCDE6FD5E09ABCF26}, // 1e86 ++ {0x544F8158315B05B4, 0x80B05E5AC60B6178}, // 1e87 ++ {0x696361AE3DB1C721, 0xA0DC75F1778E39D6}, // 1e88 ++ {0x03BC3A19CD1E38E9, 0xC913936DD571C84C}, // 1e89 ++ {0x04AB48A04065C723, 0xFB5878494ACE3A5F}, // 1e90 ++ {0x62EB0D64283F9C76, 0x9D174B2DCEC0E47B}, // 1e91 ++ {0x3BA5D0BD324F8394, 0xC45D1DF942711D9A}, // 1e92 ++ {0xCA8F44EC7EE36479, 0xF5746577930D6500}, // 1e93 ++ {0x7E998B13CF4E1ECB, 0x9968BF6ABBE85F20}, // 1e94 ++ {0x9E3FEDD8C321A67E, 0xBFC2EF456AE276E8}, // 1e95 ++ {0xC5CFE94EF3EA101E, 0xEFB3AB16C59B14A2}, // 1e96 ++ {0xBBA1F1D158724A12, 0x95D04AEE3B80ECE5}, // 1e97 ++ {0x2A8A6E45AE8EDC97, 0xBB445DA9CA61281F}, // 1e98 ++ {0xF52D09D71A3293BD, 0xEA1575143CF97226}, // 1e99 ++ {0x593C2626705F9C56, 0x924D692CA61BE758}, // 1e100 ++ {0x6F8B2FB00C77836C, 0xB6E0C377CFA2E12E}, // 1e101 ++ {0x0B6DFB9C0F956447, 0xE498F455C38B997A}, // 1e102 ++ {0x4724BD4189BD5EAC, 0x8EDF98B59A373FEC}, // 1e103 ++ {0x58EDEC91EC2CB657, 0xB2977EE300C50FE7}, // 1e104 ++ {0x2F2967B66737E3ED, 0xDF3D5E9BC0F653E1}, // 1e105 ++ {0xBD79E0D20082EE74, 0x8B865B215899F46C}, // 1e106 ++ {0xECD8590680A3AA11, 0xAE67F1E9AEC07187}, // 1e107 ++ {0xE80E6F4820CC9495, 0xDA01EE641A708DE9}, // 1e108 ++ {0x3109058D147FDCDD, 0x884134FE908658B2}, // 1e109 ++ {0xBD4B46F0599FD415, 0xAA51823E34A7EEDE}, // 1e110 ++ {0x6C9E18AC7007C91A, 0xD4E5E2CDC1D1EA96}, // 1e111 ++ {0x03E2CF6BC604DDB0, 0x850FADC09923329E}, // 1e112 ++ {0x84DB8346B786151C, 0xA6539930BF6BFF45}, // 1e113 ++ {0xE612641865679A63, 0xCFE87F7CEF46FF16}, // 1e114 ++ {0x4FCB7E8F3F60C07E, 0x81F14FAE158C5F6E}, // 1e115 ++ {0xE3BE5E330F38F09D, 0xA26DA3999AEF7749}, // 1e116 ++ {0x5CADF5BFD3072CC5, 0xCB090C8001AB551C}, // 1e117 ++ {0x73D9732FC7C8F7F6, 0xFDCB4FA002162A63}, // 1e118 ++ {0x2867E7FDDCDD9AFA, 0x9E9F11C4014DDA7E}, // 1e119 ++ {0xB281E1FD541501B8, 0xC646D63501A1511D}, // 1e120 ++ {0x1F225A7CA91A4226, 0xF7D88BC24209A565}, // 1e121 ++ {0x3375788DE9B06958, 0x9AE757596946075F}, // 1e122 ++ {0x0052D6B1641C83AE, 0xC1A12D2FC3978937}, // 1e123 ++ {0xC0678C5DBD23A49A, 0xF209787BB47D6B84}, // 1e124 ++ {0xF840B7BA963646E0, 0x9745EB4D50CE6332}, // 1e125 ++ {0xB650E5A93BC3D898, 0xBD176620A501FBFF}, // 1e126 ++ {0xA3E51F138AB4CEBE, 0xEC5D3FA8CE427AFF}, // 1e127 ++ {0xC66F336C36B10137, 0x93BA47C980E98CDF}, // 1e128 ++ {0xB80B0047445D4184, 0xB8A8D9BBE123F017}, // 1e129 ++ {0xA60DC059157491E5, 0xE6D3102AD96CEC1D}, // 1e130 ++ {0x87C89837AD68DB2F, 0x9043EA1AC7E41392}, // 1e131 ++ {0x29BABE4598C311FB, 0xB454E4A179DD1877}, // 1e132 ++ {0xF4296DD6FEF3D67A, 0xE16A1DC9D8545E94}, // 1e133 ++ {0x1899E4A65F58660C, 0x8CE2529E2734BB1D}, // 1e134 ++ {0x5EC05DCFF72E7F8F, 0xB01AE745B101E9E4}, // 1e135 ++ {0x76707543F4FA1F73, 0xDC21A1171D42645D}, // 1e136 ++ {0x6A06494A791C53A8, 0x899504AE72497EBA}, // 1e137 ++ {0x0487DB9D17636892, 0xABFA45DA0EDBDE69}, // 1e138 ++ {0x45A9D2845D3C42B6, 0xD6F8D7509292D603}, // 1e139 ++ {0x0B8A2392BA45A9B2, 0x865B86925B9BC5C2}, // 1e140 ++ {0x8E6CAC7768D7141E, 0xA7F26836F282B732}, // 1e141 ++ {0x3207D795430CD926, 0xD1EF0244AF2364FF}, // 1e142 ++ {0x7F44E6BD49E807B8, 0x8335616AED761F1F}, // 1e143 ++ {0x5F16206C9C6209A6, 0xA402B9C5A8D3A6E7}, // 1e144 ++ {0x36DBA887C37A8C0F, 0xCD036837130890A1}, // 1e145 ++ {0xC2494954DA2C9789, 0x802221226BE55A64}, // 1e146 ++ {0xF2DB9BAA10B7BD6C, 0xA02AA96B06DEB0FD}, // 1e147 ++ {0x6F92829494E5ACC7, 0xC83553C5C8965D3D}, // 1e148 ++ {0xCB772339BA1F17F9, 0xFA42A8B73ABBF48C}, // 1e149 ++ {0xFF2A760414536EFB, 0x9C69A97284B578D7}, // 1e150 ++ {0xFEF5138519684ABA, 0xC38413CF25E2D70D}, // 1e151 ++ {0x7EB258665FC25D69, 0xF46518C2EF5B8CD1}, // 1e152 ++ {0xEF2F773FFBD97A61, 0x98BF2F79D5993802}, // 1e153 ++ {0xAAFB550FFACFD8FA, 0xBEEEFB584AFF8603}, // 1e154 ++ {0x95BA2A53F983CF38, 0xEEAABA2E5DBF6784}, // 1e155 ++ {0xDD945A747BF26183, 0x952AB45CFA97A0B2}, // 1e156 ++ {0x94F971119AEEF9E4, 0xBA756174393D88DF}, // 1e157 ++ {0x7A37CD5601AAB85D, 0xE912B9D1478CEB17}, // 1e158 ++ {0xAC62E055C10AB33A, 0x91ABB422CCB812EE}, // 1e159 ++ {0x577B986B314D6009, 0xB616A12B7FE617AA}, // 1e160 ++ {0xED5A7E85FDA0B80B, 0xE39C49765FDF9D94}, // 1e161 ++ {0x14588F13BE847307, 0x8E41ADE9FBEBC27D}, // 1e162 ++ {0x596EB2D8AE258FC8, 0xB1D219647AE6B31C}, // 1e163 ++ {0x6FCA5F8ED9AEF3BB, 0xDE469FBD99A05FE3}, // 1e164 ++ {0x25DE7BB9480D5854, 0x8AEC23D680043BEE}, // 1e165 ++ {0xAF561AA79A10AE6A, 0xADA72CCC20054AE9}, // 1e166 ++ {0x1B2BA1518094DA04, 0xD910F7FF28069DA4}, // 1e167 ++ {0x90FB44D2F05D0842, 0x87AA9AFF79042286}, // 1e168 ++ {0x353A1607AC744A53, 0xA99541BF57452B28}, // 1e169 ++ {0x42889B8997915CE8, 0xD3FA922F2D1675F2}, // 1e170 ++ {0x69956135FEBADA11, 0x847C9B5D7C2E09B7}, // 1e171 ++ {0x43FAB9837E699095, 0xA59BC234DB398C25}, // 1e172 ++ {0x94F967E45E03F4BB, 0xCF02B2C21207EF2E}, // 1e173 ++ {0x1D1BE0EEBAC278F5, 0x8161AFB94B44F57D}, // 1e174 ++ {0x6462D92A69731732, 0xA1BA1BA79E1632DC}, // 1e175 ++ {0x7D7B8F7503CFDCFE, 0xCA28A291859BBF93}, // 1e176 ++ {0x5CDA735244C3D43E, 0xFCB2CB35E702AF78}, // 1e177 ++ {0x3A0888136AFA64A7, 0x9DEFBF01B061ADAB}, // 1e178 ++ {0x088AAA1845B8FDD0, 0xC56BAEC21C7A1916}, // 1e179 ++ {0x8AAD549E57273D45, 0xF6C69A72A3989F5B}, // 1e180 ++ {0x36AC54E2F678864B, 0x9A3C2087A63F6399}, // 1e181 ++ {0x84576A1BB416A7DD, 0xC0CB28A98FCF3C7F}, // 1e182 ++ {0x656D44A2A11C51D5, 0xF0FDF2D3F3C30B9F}, // 1e183 ++ {0x9F644AE5A4B1B325, 0x969EB7C47859E743}, // 1e184 ++ {0x873D5D9F0DDE1FEE, 0xBC4665B596706114}, // 1e185 ++ {0xA90CB506D155A7EA, 0xEB57FF22FC0C7959}, // 1e186 ++ {0x09A7F12442D588F2, 0x9316FF75DD87CBD8}, // 1e187 ++ {0x0C11ED6D538AEB2F, 0xB7DCBF5354E9BECE}, // 1e188 ++ {0x8F1668C8A86DA5FA, 0xE5D3EF282A242E81}, // 1e189 ++ {0xF96E017D694487BC, 0x8FA475791A569D10}, // 1e190 ++ {0x37C981DCC395A9AC, 0xB38D92D760EC4455}, // 1e191 ++ {0x85BBE253F47B1417, 0xE070F78D3927556A}, // 1e192 ++ {0x93956D7478CCEC8E, 0x8C469AB843B89562}, // 1e193 ++ {0x387AC8D1970027B2, 0xAF58416654A6BABB}, // 1e194 ++ {0x06997B05FCC0319E, 0xDB2E51BFE9D0696A}, // 1e195 ++ {0x441FECE3BDF81F03, 0x88FCF317F22241E2}, // 1e196 ++ {0xD527E81CAD7626C3, 0xAB3C2FDDEEAAD25A}, // 1e197 ++ {0x8A71E223D8D3B074, 0xD60B3BD56A5586F1}, // 1e198 ++ {0xF6872D5667844E49, 0x85C7056562757456}, // 1e199 ++ {0xB428F8AC016561DB, 0xA738C6BEBB12D16C}, // 1e200 ++ {0xE13336D701BEBA52, 0xD106F86E69D785C7}, // 1e201 ++ {0xECC0024661173473, 0x82A45B450226B39C}, // 1e202 ++ {0x27F002D7F95D0190, 0xA34D721642B06084}, // 1e203 ++ {0x31EC038DF7B441F4, 0xCC20CE9BD35C78A5}, // 1e204 ++ {0x7E67047175A15271, 0xFF290242C83396CE}, // 1e205 ++ {0x0F0062C6E984D386, 0x9F79A169BD203E41}, // 1e206 ++ {0x52C07B78A3E60868, 0xC75809C42C684DD1}, // 1e207 ++ {0xA7709A56CCDF8A82, 0xF92E0C3537826145}, // 1e208 ++ {0x88A66076400BB691, 0x9BBCC7A142B17CCB}, // 1e209 ++ {0x6ACFF893D00EA435, 0xC2ABF989935DDBFE}, // 1e210 ++ {0x0583F6B8C4124D43, 0xF356F7EBF83552FE}, // 1e211 ++ {0xC3727A337A8B704A, 0x98165AF37B2153DE}, // 1e212 ++ {0x744F18C0592E4C5C, 0xBE1BF1B059E9A8D6}, // 1e213 ++ {0x1162DEF06F79DF73, 0xEDA2EE1C7064130C}, // 1e214 ++ {0x8ADDCB5645AC2BA8, 0x9485D4D1C63E8BE7}, // 1e215 ++ {0x6D953E2BD7173692, 0xB9A74A0637CE2EE1}, // 1e216 ++ {0xC8FA8DB6CCDD0437, 0xE8111C87C5C1BA99}, // 1e217 ++ {0x1D9C9892400A22A2, 0x910AB1D4DB9914A0}, // 1e218 ++ {0x2503BEB6D00CAB4B, 0xB54D5E4A127F59C8}, // 1e219 ++ {0x2E44AE64840FD61D, 0xE2A0B5DC971F303A}, // 1e220 ++ {0x5CEAECFED289E5D2, 0x8DA471A9DE737E24}, // 1e221 ++ {0x7425A83E872C5F47, 0xB10D8E1456105DAD}, // 1e222 ++ {0xD12F124E28F77719, 0xDD50F1996B947518}, // 1e223 ++ {0x82BD6B70D99AAA6F, 0x8A5296FFE33CC92F}, // 1e224 ++ {0x636CC64D1001550B, 0xACE73CBFDC0BFB7B}, // 1e225 ++ {0x3C47F7E05401AA4E, 0xD8210BEFD30EFA5A}, // 1e226 ++ {0x65ACFAEC34810A71, 0x8714A775E3E95C78}, // 1e227 ++ {0x7F1839A741A14D0D, 0xA8D9D1535CE3B396}, // 1e228 ++ {0x1EDE48111209A050, 0xD31045A8341CA07C}, // 1e229 ++ {0x934AED0AAB460432, 0x83EA2B892091E44D}, // 1e230 ++ {0xF81DA84D5617853F, 0xA4E4B66B68B65D60}, // 1e231 ++ {0x36251260AB9D668E, 0xCE1DE40642E3F4B9}, // 1e232 ++ {0xC1D72B7C6B426019, 0x80D2AE83E9CE78F3}, // 1e233 ++ {0xB24CF65B8612F81F, 0xA1075A24E4421730}, // 1e234 ++ {0xDEE033F26797B627, 0xC94930AE1D529CFC}, // 1e235 ++ {0x169840EF017DA3B1, 0xFB9B7CD9A4A7443C}, // 1e236 ++ {0x8E1F289560EE864E, 0x9D412E0806E88AA5}, // 1e237 ++ {0xF1A6F2BAB92A27E2, 0xC491798A08A2AD4E}, // 1e238 ++ {0xAE10AF696774B1DB, 0xF5B5D7EC8ACB58A2}, // 1e239 ++ {0xACCA6DA1E0A8EF29, 0x9991A6F3D6BF1765}, // 1e240 ++ {0x17FD090A58D32AF3, 0xBFF610B0CC6EDD3F}, // 1e241 ++ {0xDDFC4B4CEF07F5B0, 0xEFF394DCFF8A948E}, // 1e242 ++ {0x4ABDAF101564F98E, 0x95F83D0A1FB69CD9}, // 1e243 ++ {0x9D6D1AD41ABE37F1, 0xBB764C4CA7A4440F}, // 1e244 ++ {0x84C86189216DC5ED, 0xEA53DF5FD18D5513}, // 1e245 ++ {0x32FD3CF5B4E49BB4, 0x92746B9BE2F8552C}, // 1e246 ++ {0x3FBC8C33221DC2A1, 0xB7118682DBB66A77}, // 1e247 ++ {0x0FABAF3FEAA5334A, 0xE4D5E82392A40515}, // 1e248 ++ {0x29CB4D87F2A7400E, 0x8F05B1163BA6832D}, // 1e249 ++ {0x743E20E9EF511012, 0xB2C71D5BCA9023F8}, // 1e250 ++ {0x914DA9246B255416, 0xDF78E4B2BD342CF6}, // 1e251 ++ {0x1AD089B6C2F7548E, 0x8BAB8EEFB6409C1A}, // 1e252 ++ {0xA184AC2473B529B1, 0xAE9672ABA3D0C320}, // 1e253 ++ {0xC9E5D72D90A2741E, 0xDA3C0F568CC4F3E8}, // 1e254 ++ {0x7E2FA67C7A658892, 0x8865899617FB1871}, // 1e255 ++ {0xDDBB901B98FEEAB7, 0xAA7EEBFB9DF9DE8D}, // 1e256 ++ {0x552A74227F3EA565, 0xD51EA6FA85785631}, // 1e257 ++ {0xD53A88958F87275F, 0x8533285C936B35DE}, // 1e258 ++ {0x8A892ABAF368F137, 0xA67FF273B8460356}, // 1e259 ++ {0x2D2B7569B0432D85, 0xD01FEF10A657842C}, // 1e260 ++ {0x9C3B29620E29FC73, 0x8213F56A67F6B29B}, // 1e261 ++ {0x8349F3BA91B47B8F, 0xA298F2C501F45F42}, // 1e262 ++ {0x241C70A936219A73, 0xCB3F2F7642717713}, // 1e263 ++ {0xED238CD383AA0110, 0xFE0EFB53D30DD4D7}, // 1e264 ++ {0xF4363804324A40AA, 0x9EC95D1463E8A506}, // 1e265 ++ {0xB143C6053EDCD0D5, 0xC67BB4597CE2CE48}, // 1e266 ++ {0xDD94B7868E94050A, 0xF81AA16FDC1B81DA}, // 1e267 ++ {0xCA7CF2B4191C8326, 0x9B10A4E5E9913128}, // 1e268 ++ {0xFD1C2F611F63A3F0, 0xC1D4CE1F63F57D72}, // 1e269 ++ {0xBC633B39673C8CEC, 0xF24A01A73CF2DCCF}, // 1e270 ++ {0xD5BE0503E085D813, 0x976E41088617CA01}, // 1e271 ++ {0x4B2D8644D8A74E18, 0xBD49D14AA79DBC82}, // 1e272 ++ {0xDDF8E7D60ED1219E, 0xEC9C459D51852BA2}, // 1e273 ++ {0xCABB90E5C942B503, 0x93E1AB8252F33B45}, // 1e274 ++ {0x3D6A751F3B936243, 0xB8DA1662E7B00A17}, // 1e275 ++ {0x0CC512670A783AD4, 0xE7109BFBA19C0C9D}, // 1e276 ++ {0x27FB2B80668B24C5, 0x906A617D450187E2}, // 1e277 ++ {0xB1F9F660802DEDF6, 0xB484F9DC9641E9DA}, // 1e278 ++ {0x5E7873F8A0396973, 0xE1A63853BBD26451}, // 1e279 ++ {0xDB0B487B6423E1E8, 0x8D07E33455637EB2}, // 1e280 ++ {0x91CE1A9A3D2CDA62, 0xB049DC016ABC5E5F}, // 1e281 ++ {0x7641A140CC7810FB, 0xDC5C5301C56B75F7}, // 1e282 ++ {0xA9E904C87FCB0A9D, 0x89B9B3E11B6329BA}, // 1e283 ++ {0x546345FA9FBDCD44, 0xAC2820D9623BF429}, // 1e284 ++ {0xA97C177947AD4095, 0xD732290FBACAF133}, // 1e285 ++ {0x49ED8EABCCCC485D, 0x867F59A9D4BED6C0}, // 1e286 ++ {0x5C68F256BFFF5A74, 0xA81F301449EE8C70}, // 1e287 ++ {0x73832EEC6FFF3111, 0xD226FC195C6A2F8C}, // 1e288 + }; + +-// -------- ++// wuffs_private_impl__f64_powers_of_10 holds powers of 10 that can be exactly ++// represented by a float64 (what C calls a double). ++static const double wuffs_private_impl__f64_powers_of_10[23] = { ++ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, ++ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, ++}; + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output // +-wuffs_base__base_64__decode(wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 src, +- bool src_closed, +- uint32_t options) { +- const uint8_t* alphabet = (options & WUFFS_BASE__BASE_64__URL_ALPHABET) +- ? wuffs_base__base_64__decode_url +- : wuffs_base__base_64__decode_std; +- wuffs_base__transform__output o; +- uint8_t* d_ptr = dst.ptr; +- size_t d_len = dst.len; +- const uint8_t* s_ptr = src.ptr; +- size_t s_len = src.len; +- bool pad = false; ++// ---------------- IEEE 754 Floating Point + +- while (s_len >= 4) { +- uint32_t s = wuffs_base__peek_u32le__no_bounds_check(s_ptr); +- uint32_t s0 = alphabet[0xFF & (s >> 0)]; +- uint32_t s1 = alphabet[0xFF & (s >> 8)]; +- uint32_t s2 = alphabet[0xFF & (s >> 16)]; +- uint32_t s3 = alphabet[0xFF & (s >> 24)]; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16 // ++wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f) { ++ uint64_t u = 0; ++ if (sizeof(uint64_t) == sizeof(double)) { ++ memcpy(&u, &f, sizeof(uint64_t)); ++ } ++ uint16_t neg = ((uint16_t)((u >> 63) << 15)); ++ u &= 0x7FFFFFFFFFFFFFFF; ++ uint64_t exp = u >> 52; ++ uint64_t man = u & 0x000FFFFFFFFFFFFF; + +- if (((s0 | s1 | s2 | s3) & 0xC0) != 0) { +- if (s_len > 4) { +- o.status.repr = wuffs_base__error__bad_data; +- goto done; +- } else if (!src_closed) { +- o.status.repr = wuffs_base__suspension__short_read; +- goto done; +- } else if ((options & WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING) && +- (s_ptr[3] == '=')) { +- pad = true; +- if (s_ptr[2] == '=') { +- goto src2; +- } +- goto src3; +- } +- o.status.repr = wuffs_base__error__bad_data; +- goto done; ++ if (exp == 0x7FF) { ++ if (man == 0) { // Infinity. ++ wuffs_base__lossy_value_u16 ret; ++ ret.value = neg | 0x7C00; ++ ret.lossy = false; ++ return ret; + } ++ // NaN. Shift the 52 mantissa bits to 10 mantissa bits, keeping the most ++ // significant mantissa bit (quiet vs signaling NaNs). Also set the low 9 ++ // bits of ret.value so that the 10-bit mantissa is non-zero. ++ wuffs_base__lossy_value_u16 ret; ++ ret.value = neg | 0x7DFF | ((uint16_t)(man >> 42)); ++ ret.lossy = false; ++ return ret; + +- if (d_len < 3) { +- o.status.repr = wuffs_base__suspension__short_write; +- goto done; +- } ++ } else if (exp > 0x40E) { // Truncate to the largest finite f16. ++ wuffs_base__lossy_value_u16 ret; ++ ret.value = neg | 0x7BFF; ++ ret.lossy = true; ++ return ret; + +- s_ptr += 4; +- s_len -= 4; +- s = (s0 << 18) | (s1 << 12) | (s2 << 6) | (s3 << 0); +- *d_ptr++ = (uint8_t)(s >> 16); +- *d_ptr++ = (uint8_t)(s >> 8); +- *d_ptr++ = (uint8_t)(s >> 0); +- d_len -= 3; +- } +- +- if (!src_closed) { +- o.status.repr = wuffs_base__suspension__short_read; +- goto done; +- } ++ } else if (exp <= 0x3E6) { // Truncate to zero. ++ wuffs_base__lossy_value_u16 ret; ++ ret.value = neg; ++ ret.lossy = (u != 0); ++ return ret; + +- if (s_len == 0) { +- o.status.repr = NULL; +- goto done; +- } else if (s_len == 1) { +- o.status.repr = wuffs_base__error__bad_data; +- goto done; +- } else if (s_len == 2) { +- goto src2; ++ } else if (exp <= 0x3F0) { // Normal f64, subnormal f16. ++ // Convert from a 53-bit mantissa (after realizing the implicit bit) to a ++ // 10-bit mantissa and then adjust for the exponent. ++ man |= 0x0010000000000000; ++ uint32_t shift = ((uint32_t)(1051 - exp)); // 1051 = 0x3F0 + 53 - 10. ++ uint64_t shifted_man = man >> shift; ++ wuffs_base__lossy_value_u16 ret; ++ ret.value = neg | ((uint16_t)shifted_man); ++ ret.lossy = (shifted_man << shift) != man; ++ return ret; + } + +-src3: +- do { +- uint32_t s = wuffs_base__peek_u24le__no_bounds_check(s_ptr); +- uint32_t s0 = alphabet[0xFF & (s >> 0)]; +- uint32_t s1 = alphabet[0xFF & (s >> 8)]; +- uint32_t s2 = alphabet[0xFF & (s >> 16)]; +- if ((s0 & 0xC0) || (s1 & 0xC0) || (s2 & 0xC3)) { +- o.status.repr = wuffs_base__error__bad_data; +- goto done; +- } +- if (d_len < 2) { +- o.status.repr = wuffs_base__suspension__short_write; +- goto done; +- } +- s_ptr += pad ? 4 : 3; +- s = (s0 << 18) | (s1 << 12) | (s2 << 6); +- *d_ptr++ = (uint8_t)(s >> 16); +- *d_ptr++ = (uint8_t)(s >> 8); +- o.status.repr = NULL; +- goto done; +- } while (0); ++ // Normal f64, normal f16. + +-src2: +- do { +- uint32_t s = wuffs_base__peek_u16le__no_bounds_check(s_ptr); +- uint32_t s0 = alphabet[0xFF & (s >> 0)]; +- uint32_t s1 = alphabet[0xFF & (s >> 8)]; +- if ((s0 & 0xC0) || (s1 & 0xCF)) { +- o.status.repr = wuffs_base__error__bad_data; +- goto done; +- } +- if (d_len < 1) { +- o.status.repr = wuffs_base__suspension__short_write; +- goto done; +- } +- s_ptr += pad ? 4 : 2; +- s = (s0 << 18) | (s1 << 12); +- *d_ptr++ = (uint8_t)(s >> 16); +- o.status.repr = NULL; +- goto done; +- } while (0); ++ // Re-bias from 1023 to 15 and shift above f16's 10 mantissa bits. ++ exp = (exp - 1008) << 10; // 1008 = 1023 - 15 = 0x3FF - 0xF. + +-done: +- o.num_dst = (size_t)(d_ptr - dst.ptr); +- o.num_src = (size_t)(s_ptr - src.ptr); +- return o; ++ // Convert from a 52-bit mantissa (excluding the implicit bit) to a 10-bit ++ // mantissa (again excluding the implicit bit). We lose some information if ++ // any of the bottom 42 bits are non-zero. ++ wuffs_base__lossy_value_u16 ret; ++ ret.value = neg | ((uint16_t)exp) | ((uint16_t)(man >> 42)); ++ ret.lossy = (man << 22) != 0; ++ return ret; + } + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output // +-wuffs_base__base_64__encode(wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 src, +- bool src_closed, +- uint32_t options) { +- const uint8_t* alphabet = (options & WUFFS_BASE__BASE_64__URL_ALPHABET) +- ? wuffs_base__base_64__encode_url +- : wuffs_base__base_64__encode_std; +- wuffs_base__transform__output o; +- uint8_t* d_ptr = dst.ptr; +- size_t d_len = dst.len; +- const uint8_t* s_ptr = src.ptr; +- size_t s_len = src.len; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32 // ++wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f) { ++ uint64_t u = 0; ++ if (sizeof(uint64_t) == sizeof(double)) { ++ memcpy(&u, &f, sizeof(uint64_t)); ++ } ++ uint32_t neg = ((uint32_t)(u >> 63)) << 31; ++ u &= 0x7FFFFFFFFFFFFFFF; ++ uint64_t exp = u >> 52; ++ uint64_t man = u & 0x000FFFFFFFFFFFFF; + +- do { +- while (s_len >= 3) { +- if (d_len < 4) { +- o.status.repr = wuffs_base__suspension__short_write; +- goto done; +- } +- uint32_t s = wuffs_base__peek_u24be__no_bounds_check(s_ptr); +- s_ptr += 3; +- s_len -= 3; +- *d_ptr++ = alphabet[0x3F & (s >> 18)]; +- *d_ptr++ = alphabet[0x3F & (s >> 12)]; +- *d_ptr++ = alphabet[0x3F & (s >> 6)]; +- *d_ptr++ = alphabet[0x3F & (s >> 0)]; +- d_len -= 4; ++ if (exp == 0x7FF) { ++ if (man == 0) { // Infinity. ++ wuffs_base__lossy_value_u32 ret; ++ ret.value = neg | 0x7F800000; ++ ret.lossy = false; ++ return ret; + } ++ // NaN. Shift the 52 mantissa bits to 23 mantissa bits, keeping the most ++ // significant mantissa bit (quiet vs signaling NaNs). Also set the low 22 ++ // bits of ret.value so that the 23-bit mantissa is non-zero. ++ wuffs_base__lossy_value_u32 ret; ++ ret.value = neg | 0x7FBFFFFF | ((uint32_t)(man >> 29)); ++ ret.lossy = false; ++ return ret; + +- if (!src_closed) { +- o.status.repr = wuffs_base__suspension__short_read; +- goto done; +- } ++ } else if (exp > 0x47E) { // Truncate to the largest finite f32. ++ wuffs_base__lossy_value_u32 ret; ++ ret.value = neg | 0x7F7FFFFF; ++ ret.lossy = true; ++ return ret; + +- if (s_len == 2) { +- if (d_len < +- ((options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) ? 4 : 3)) { +- o.status.repr = wuffs_base__suspension__short_write; +- goto done; +- } +- uint32_t s = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(s_ptr))) +- << 8; +- s_ptr += 2; +- *d_ptr++ = alphabet[0x3F & (s >> 18)]; +- *d_ptr++ = alphabet[0x3F & (s >> 12)]; +- *d_ptr++ = alphabet[0x3F & (s >> 6)]; +- if (options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) { +- *d_ptr++ = '='; +- } +- o.status.repr = NULL; +- goto done; ++ } else if (exp <= 0x369) { // Truncate to zero. ++ wuffs_base__lossy_value_u32 ret; ++ ret.value = neg; ++ ret.lossy = (u != 0); ++ return ret; + +- } else if (s_len == 1) { +- if (d_len < +- ((options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) ? 4 : 2)) { +- o.status.repr = wuffs_base__suspension__short_write; +- goto done; +- } +- uint32_t s = ((uint32_t)(wuffs_base__peek_u8__no_bounds_check(s_ptr))) +- << 16; +- s_ptr += 1; +- *d_ptr++ = alphabet[0x3F & (s >> 18)]; +- *d_ptr++ = alphabet[0x3F & (s >> 12)]; +- if (options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) { +- *d_ptr++ = '='; +- *d_ptr++ = '='; +- } +- o.status.repr = NULL; +- goto done; ++ } else if (exp <= 0x380) { // Normal f64, subnormal f32. ++ // Convert from a 53-bit mantissa (after realizing the implicit bit) to a ++ // 23-bit mantissa and then adjust for the exponent. ++ man |= 0x0010000000000000; ++ uint32_t shift = ((uint32_t)(926 - exp)); // 926 = 0x380 + 53 - 23. ++ uint64_t shifted_man = man >> shift; ++ wuffs_base__lossy_value_u32 ret; ++ ret.value = neg | ((uint32_t)shifted_man); ++ ret.lossy = (shifted_man << shift) != man; ++ return ret; ++ } + +- } else { +- o.status.repr = NULL; +- goto done; +- } +- } while (0); ++ // Normal f64, normal f32. + +-done: +- o.num_dst = (size_t)(d_ptr - dst.ptr); +- o.num_src = (size_t)(s_ptr - src.ptr); +- return o; ++ // Re-bias from 1023 to 127 and shift above f32's 23 mantissa bits. ++ exp = (exp - 896) << 23; // 896 = 1023 - 127 = 0x3FF - 0x7F. ++ ++ // Convert from a 52-bit mantissa (excluding the implicit bit) to a 23-bit ++ // mantissa (again excluding the implicit bit). We lose some information if ++ // any of the bottom 29 bits are non-zero. ++ wuffs_base__lossy_value_u32 ret; ++ ret.value = neg | ((uint32_t)exp) | ((uint32_t)(man >> 29)); ++ ret.lossy = (man << 35) != 0; ++ return ret; + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || +- // defined(WUFFS_CONFIG__MODULE__BASE) || +- // defined(WUFFS_CONFIG__MODULE__BASE__INTCONV) ++// -------- + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ +- defined(WUFFS_CONFIG__MODULE__BASE__MAGIC) ++#define WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE 2047 ++#define WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION 800 + +-// ---------------- Magic Numbers ++// WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL is the largest N such that ++// ((10 << N) < (1 << 64)). ++#define WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL 60 + +-// ICO doesn't start with a magic identifier. Instead, see if the opening bytes +-// are plausibly ICO. ++// wuffs_private_impl__high_prec_dec (abbreviated as HPD) is a fixed precision ++// floating point decimal number, augmented with ±infinity values, but it ++// cannot represent NaN (Not a Number). + // +-// Callers should have already verified that (prefix_data.len >= 2) and the +-// first two bytes are 0x00. ++// "High precision" means that the mantissa holds 800 decimal digits. 800 is ++// WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION. + // +-// See: +-// - https://docs.fileformat.com/image/ico/ +-static int32_t // +-wuffs_base__magic_number_guess_fourcc__maybe_ico( +- wuffs_base__slice_u8 prefix_data, +- bool prefix_closed) { +- // Allow-list for the Image Type field. +- if (prefix_data.len < 4) { +- return prefix_closed ? 0 : -1; +- } else if (prefix_data.ptr[3] != 0) { +- return 0; +- } +- switch (prefix_data.ptr[2]) { +- case 0x01: // ICO +- case 0x02: // CUR +- break; +- default: +- return 0; +- } +- +- // The Number Of Images should be positive. +- if (prefix_data.len < 6) { +- return prefix_closed ? 0 : -1; +- } else if ((prefix_data.ptr[4] == 0) && (prefix_data.ptr[5] == 0)) { +- return 0; +- } ++// An HPD isn't for general purpose arithmetic, only for conversions to and ++// from IEEE 754 double-precision floating point, where the largest and ++// smallest positive, finite values are approximately 1.8e+308 and 4.9e-324. ++// HPD exponents above +2047 mean infinity, below -2047 mean zero. The ±2047 ++// bounds are further away from zero than ±(324 + 800), where 800 and 2047 is ++// WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION and ++// WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE. ++// ++// digits[.. num_digits] are the number's digits in big-endian order. The ++// uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7' ++// is the ASCII value 0x37. ++// ++// decimal_point is the index (within digits) of the decimal point. It may be ++// negative or be larger than num_digits, in which case the explicit digits are ++// padded with implicit zeroes. ++// ++// For example, if num_digits is 3 and digits is "\x07\x08\x09": ++// - A decimal_point of -2 means ".00789" ++// - A decimal_point of -1 means ".0789" ++// - A decimal_point of +0 means ".789" ++// - A decimal_point of +1 means "7.89" ++// - A decimal_point of +2 means "78.9" ++// - A decimal_point of +3 means "789." ++// - A decimal_point of +4 means "7890." ++// - A decimal_point of +5 means "78900." ++// ++// As above, a decimal_point higher than +2047 means that the overall value is ++// infinity, lower than -2047 means zero. ++// ++// negative is a sign bit. An HPD can distinguish positive and negative zero. ++// ++// truncated is whether there are more than ++// WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION digits, and at least one of those ++// extra digits are non-zero. The existence of long-tail digits can affect ++// rounding. ++// ++// The "all fields are zero" value is valid, and represents the number +0. ++typedef struct wuffs_private_impl__high_prec_dec__struct { ++ uint32_t num_digits; ++ int32_t decimal_point; ++ bool negative; ++ bool truncated; ++ uint8_t digits[WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION]; ++} wuffs_private_impl__high_prec_dec; + +- // The first ICONDIRENTRY's fourth byte should be zero. +- if (prefix_data.len < 10) { +- return prefix_closed ? 0 : -1; +- } else if (prefix_data.ptr[9] != 0) { +- return 0; ++// wuffs_private_impl__high_prec_dec__trim trims trailing zeroes from the ++// h->digits[.. h->num_digits] slice. They have no benefit, since we explicitly ++// track h->decimal_point. ++// ++// Preconditions: ++// - h is non-NULL. ++static inline void // ++wuffs_private_impl__high_prec_dec__trim(wuffs_private_impl__high_prec_dec* h) { ++ while ((h->num_digits > 0) && (h->digits[h->num_digits - 1] == 0)) { ++ h->num_digits--; + } +- +- // TODO: have a separate FourCC for CUR? +- return 0x49434F20; // 'ICO 'be + } + +-// TGA doesn't start with a magic identifier. Instead, see if the opening bytes +-// are plausibly TGA. ++// wuffs_private_impl__high_prec_dec__assign sets h to represent the number x. + // +-// Callers should have already verified that (prefix_data.len >= 2) and the +-// second byte (prefix_data.ptr[1], the Color Map Type byte), is either 0x00 or +-// 0x01. +-// +-// See: +-// - https://docs.fileformat.com/image/tga/ +-// - https://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf +-static int32_t // +-wuffs_base__magic_number_guess_fourcc__maybe_tga( +- wuffs_base__slice_u8 prefix_data, +- bool prefix_closed) { +- // Allow-list for the Image Type field. +- if (prefix_data.len < 3) { +- return prefix_closed ? 0 : -1; +- } +- switch (prefix_data.ptr[2]) { +- case 0x01: +- case 0x02: +- case 0x03: +- case 0x09: +- case 0x0A: +- case 0x0B: +- break; +- default: +- // TODO: 0x20 and 0x21 are invalid, according to the spec, but are +- // apparently unofficial extensions. +- return 0; +- } +- +- // Allow-list for the Color Map Entry Size field (if the Color Map Type field +- // is non-zero) or else all the Color Map fields should be zero. +- if (prefix_data.len < 8) { +- return prefix_closed ? 0 : -1; +- } else if (prefix_data.ptr[1] != 0x00) { +- switch (prefix_data.ptr[7]) { +- case 0x0F: +- case 0x10: +- case 0x18: +- case 0x20: +- break; +- default: +- return 0; +- } +- } else if ((prefix_data.ptr[3] | prefix_data.ptr[4] | prefix_data.ptr[5] | +- prefix_data.ptr[6] | prefix_data.ptr[7]) != 0x00) { +- return 0; +- } ++// Preconditions: ++// - h is non-NULL. ++static void // ++wuffs_private_impl__high_prec_dec__assign(wuffs_private_impl__high_prec_dec* h, ++ uint64_t x, ++ bool negative) { ++ uint32_t n = 0; + +- // Allow-list for the Pixel Depth field. +- if (prefix_data.len < 17) { +- return prefix_closed ? 0 : -1; +- } +- switch (prefix_data.ptr[16]) { +- case 0x01: +- case 0x08: +- case 0x0F: +- case 0x10: +- case 0x18: +- case 0x20: +- break; +- default: +- return 0; ++ // Set h->digits. ++ if (x > 0) { ++ // Calculate the digits, working right-to-left. After we determine n (how ++ // many digits there are), copy from buf to h->digits. ++ // ++ // UINT64_MAX, 18446744073709551615, is 20 digits long. It can be faster to ++ // copy a constant number of bytes than a variable number (20 instead of ++ // n). Make buf large enough (and start writing to it from the middle) so ++ // that can we always copy 20 bytes: the slice buf[(20-n) .. (40-n)]. ++ uint8_t buf[40] = {0}; ++ uint8_t* ptr = &buf[20]; ++ do { ++ uint64_t remaining = x / 10; ++ x -= remaining * 10; ++ ptr--; ++ *ptr = (uint8_t)x; ++ n++; ++ x = remaining; ++ } while (x > 0); ++ memcpy(h->digits, ptr, 20); + } + +- return 0x54474120; // 'TGA 'be ++ // Set h's other fields. ++ h->num_digits = n; ++ h->decimal_point = (int32_t)n; ++ h->negative = negative; ++ h->truncated = false; ++ wuffs_private_impl__high_prec_dec__trim(h); + } + +-WUFFS_BASE__MAYBE_STATIC int32_t // +-wuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix_data, +- bool prefix_closed) { +- // This is similar to (but different from): +- // - the magic/Magdir tables under https://github.com/file/file +- // - the MIME Sniffing algorithm at https://mimesniff.spec.whatwg.org/ +- +- // table holds the 'magic numbers' (which are actually variable length +- // strings). The strings may contain NUL bytes, so the "const char* magic" +- // value starts with the length-minus-1 of the 'magic number'. +- // +- // Keep it sorted by magic[1], then magic[0] descending (prioritizing longer +- // matches) and finally by magic[2:]. When multiple entries match, the +- // longest one wins. +- // +- // The fourcc field might be negated, in which case there's further +- // specialization (see § below). +- static struct { +- int32_t fourcc; +- const char* magic; +- } table[] = { +- {-0x30302020, "\x01\x00\x00"}, // '00 'be +- {+0x475A2020, "\x02\x1F\x8B\x08"}, // GZ +- {+0x5A535444, "\x03\x28\xB5\x2F\xFD"}, // ZSTD +- {+0x425A3220, "\x02\x42\x5A\x68"}, // BZ2 +- {+0x424D5020, "\x01\x42\x4D"}, // BMP +- {+0x47494620, "\x03\x47\x49\x46\x38"}, // GIF +- {+0x54494646, "\x03\x49\x49\x2A\x00"}, // TIFF (little-endian) +- {+0x54494646, "\x03\x4D\x4D\x00\x2A"}, // TIFF (big-endian) +- {+0x4E50424D, "\x02\x50\x35\x0A"}, // NPBM (P5; *.pgm) +- {+0x4E50424D, "\x02\x50\x36\x0A"}, // NPBM (P6; *.ppm) +- {-0x52494646, "\x03\x52\x49\x46\x46"}, // RIFF +- {+0x4C5A4D41, "\x04\x5D\x00\x10\x00\x00"}, // LZMA +- {+0x4C5A4D41, "\x02\x5D\x00\x00"}, // LZMA +- {+0x4E494520, "\x02\x6E\xC3\xAF"}, // NIE +- {+0x514F4920, "\x03\x71\x6F\x69\x66"}, // QOI +- {+0x5A4C4942, "\x01\x78\x9C"}, // ZLIB +- {+0x504E4720, "\x03\x89\x50\x4E\x47"}, // PNG +- {+0x585A2020, "\x04\xFD\x37\x7A\x58\x5A"}, // XZ +- {+0x4A504547, "\x01\xFF\xD8"}, // JPEG +- }; +- static const size_t table_len = sizeof(table) / sizeof(table[0]); +- +- if (prefix_data.len == 0) { +- return prefix_closed ? 0 : -1; ++static wuffs_base__status // ++wuffs_private_impl__high_prec_dec__parse(wuffs_private_impl__high_prec_dec* h, ++ wuffs_base__slice_u8 s, ++ uint32_t options) { ++ if (!h) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- uint8_t pre_first_byte = prefix_data.ptr[0]; ++ h->num_digits = 0; ++ h->decimal_point = 0; ++ h->negative = false; ++ h->truncated = false; + +- int32_t fourcc = 0; +- size_t i; +- for (i = 0; i < table_len; i++) { +- uint8_t mag_first_byte = ((uint8_t)(table[i].magic[1])); +- if (pre_first_byte < mag_first_byte) { +- break; +- } else if (pre_first_byte > mag_first_byte) { +- continue; +- } +- fourcc = table[i].fourcc; ++ uint8_t* p = s.ptr; ++ uint8_t* q = s.ptr + s.len; + +- uint8_t mag_remaining_len = ((uint8_t)(table[i].magic[0])); +- if (mag_remaining_len == 0) { +- goto match; ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { ++ for (;; p++) { ++ if (p >= q) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } else if (*p != '_') { ++ break; ++ } + } ++ } + +- const char* mag_remaining_ptr = table[i].magic + 2; +- uint8_t* pre_remaining_ptr = prefix_data.ptr + 1; +- size_t pre_remaining_len = prefix_data.len - 1; +- if (pre_remaining_len < mag_remaining_len) { +- if (!memcmp(pre_remaining_ptr, mag_remaining_ptr, pre_remaining_len)) { +- return prefix_closed ? 0 : -1; +- } ++ // Parse sign. ++ do { ++ if (*p == '+') { ++ p++; ++ } else if (*p == '-') { ++ h->negative = true; ++ p++; + } else { +- if (!memcmp(pre_remaining_ptr, mag_remaining_ptr, mag_remaining_len)) { +- goto match; ++ break; ++ } ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { ++ for (;; p++) { ++ if (p >= q) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } else if (*p != '_') { ++ break; ++ } + } + } +- } +- +- if (prefix_data.len < 2) { +- return prefix_closed ? 0 : -1; +- } else if ((prefix_data.ptr[1] == 0x00) || (prefix_data.ptr[1] == 0x01)) { +- return wuffs_base__magic_number_guess_fourcc__maybe_tga(prefix_data, +- prefix_closed); +- } +- +- return 0; +- +-match: +- // Negative FourCC values (see § above) are further specialized. +- if (fourcc < 0) { +- fourcc = -fourcc; ++ } while (0); + +- if (fourcc == 0x52494646) { // 'RIFF'be +- if (prefix_data.len < 12) { +- return prefix_closed ? 0 : -1; ++ // Parse digits, up to (and including) a '.', 'E' or 'e'. Examples for each ++ // limb in this if-else chain: ++ // - "0.789" ++ // - "1002.789" ++ // - ".789" ++ // - Other (invalid input). ++ uint32_t nd = 0; ++ int32_t dp = 0; ++ bool no_digits_before_separator = false; ++ if (('0' == *p) && ++ !(options & ++ WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES)) { ++ p++; ++ for (;; p++) { ++ if (p >= q) { ++ goto after_all; ++ } else if (*p == ++ ((options & ++ WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) ++ ? ',' ++ : '.')) { ++ p++; ++ goto after_sep; ++ } else if ((*p == 'E') || (*p == 'e')) { ++ p++; ++ goto after_exp; ++ } else if ((*p != '_') || ++ !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); + } +- uint32_t x = wuffs_base__peek_u32be__no_bounds_check(prefix_data.ptr + 8); +- if (x == 0x57454250) { // 'WEBP'be +- return 0x57454250; // 'WEBP'be ++ } ++ ++ } else if (('0' <= *p) && (*p <= '9')) { ++ if (*p == '0') { ++ for (; (p < q) && (*p == '0'); p++) { + } ++ } else { ++ h->digits[nd++] = (uint8_t)(*p - '0'); ++ dp = (int32_t)nd; ++ p++; ++ } + +- } else if (fourcc == 0x30302020) { // '00 'be +- // Binary data starting with multiple 0x00 NUL bytes is quite common. +- // Unfortunately, some file formats also don't start with a magic +- // identifier, so we have to use heuristics (where the order matters, the +- // same as /usr/bin/file's magic/Magdir tables) as best we can. Maybe +- // it's TGA, ICO/CUR, etc. Maybe it's something else. +- int32_t tga = wuffs_base__magic_number_guess_fourcc__maybe_tga( +- prefix_data, prefix_closed); +- if (tga != 0) { +- return tga; ++ for (;; p++) { ++ if (p >= q) { ++ goto after_all; ++ } else if (('0' <= *p) && (*p <= '9')) { ++ if (nd < WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION) { ++ h->digits[nd++] = (uint8_t)(*p - '0'); ++ dp = (int32_t)nd; ++ } else if ('0' != *p) { ++ // Long-tail non-zeroes set the truncated bit. ++ h->truncated = true; ++ } ++ } else if (*p == ++ ((options & ++ WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) ++ ? ',' ++ : '.')) { ++ p++; ++ goto after_sep; ++ } else if ((*p == 'E') || (*p == 'e')) { ++ p++; ++ goto after_exp; ++ } else if ((*p != '_') || ++ !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); + } +- int32_t ico = wuffs_base__magic_number_guess_fourcc__maybe_ico( +- prefix_data, prefix_closed); +- if (ico != 0) { +- return ico; ++ } ++ ++ } else if (*p == ((options & ++ WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) ++ ? ',' ++ : '.')) { ++ p++; ++ no_digits_before_separator = true; ++ ++ } else { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ ++after_sep: ++ for (;; p++) { ++ if (p >= q) { ++ goto after_all; ++ } else if ('0' == *p) { ++ if (nd == 0) { ++ // Track leading zeroes implicitly. ++ dp--; ++ } else if (nd < WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION) { ++ h->digits[nd++] = (uint8_t)(*p - '0'); + } +- if (prefix_data.len < 4) { +- return prefix_closed ? 0 : -1; +- } else if ((prefix_data.ptr[2] != 0x00) && +- ((prefix_data.ptr[2] >= 0x80) || +- (prefix_data.ptr[3] != 0x00))) { +- // Roughly speaking, this could be a non-degenerate (non-0-width and +- // non-0-height) WBMP image. +- return 0x57424D50; // 'WBMP'be ++ } else if (('0' < *p) && (*p <= '9')) { ++ if (nd < WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION) { ++ h->digits[nd++] = (uint8_t)(*p - '0'); ++ } else { ++ // Long-tail non-zeroes set the truncated bit. ++ h->truncated = true; + } +- return 0; ++ } else if ((*p == 'E') || (*p == 'e')) { ++ p++; ++ goto after_exp; ++ } else if ((*p != '_') || ++ !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + } +- return fourcc; +-} +- +-#endif // !defined(WUFFS_CONFIG__MODULES) || +- // defined(WUFFS_CONFIG__MODULE__BASE) || +- // defined(WUFFS_CONFIG__MODULE__BASE__MAGIC) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ +- defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV) + +-// ---------------- Pixel Swizzler ++after_exp: ++ do { ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { ++ for (;; p++) { ++ if (p >= q) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } else if (*p != '_') { ++ break; ++ } ++ } ++ } + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") +-static uint64_t // +-wuffs_base__pixel_swizzler__bgrw__rgb__x86_sse42(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len); ++ int32_t exp_sign = +1; ++ if (*p == '+') { ++ p++; ++ } else if (*p == '-') { ++ exp_sign = -1; ++ p++; ++ } + +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") +-static uint64_t // +-wuffs_base__pixel_swizzler__swap_rgbx_bgrx__x86_sse42(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len); ++ int32_t exp = 0; ++ const int32_t exp_large = WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE + ++ WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION; ++ bool saw_exp_digits = false; ++ for (; p < q; p++) { ++ if ((*p == '_') && ++ (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { ++ // No-op. ++ } else if (('0' <= *p) && (*p <= '9')) { ++ saw_exp_digits = true; ++ if (exp < exp_large) { ++ exp = (10 * exp) + ((int32_t)(*p - '0')); ++ } ++ } else { ++ break; ++ } ++ } ++ if (!saw_exp_digits) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ dp += exp_sign * exp; ++ } while (0); + +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") +-static uint64_t // +-wuffs_base__pixel_swizzler__xxxx__y__x86_sse42(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) ++after_all: ++ if (p != q) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ h->num_digits = nd; ++ if (nd == 0) { ++ if (no_digits_before_separator) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ h->decimal_point = 0; ++ } else if (dp < -WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE) { ++ h->decimal_point = -WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE - 1; ++ } else if (dp > +WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE) { ++ h->decimal_point = +WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE + 1; ++ } else { ++ h->decimal_point = dp; ++ } ++ wuffs_private_impl__high_prec_dec__trim(h); ++ return wuffs_base__make_status(NULL); ++} + + // -------- + +-static inline uint32_t // +-wuffs_base__swap_u32_argb_abgr(uint32_t u) { +- uint32_t o = u & 0xFF00FF00ul; +- uint32_t r = u & 0x00FF0000ul; +- uint32_t b = u & 0x000000FFul; +- return o | (r >> 16) | (b << 16); +-} ++// wuffs_private_impl__high_prec_dec__lshift_num_new_digits returns the number ++// of additional decimal digits when left-shifting by shift. ++// ++// See below for preconditions. ++static uint32_t // ++wuffs_private_impl__high_prec_dec__lshift_num_new_digits( ++ wuffs_private_impl__high_prec_dec* h, ++ uint32_t shift) { ++ // Masking with 0x3F should be unnecessary (assuming the preconditions) but ++ // it's cheap and ensures that we don't overflow the ++ // wuffs_private_impl__hpd_left_shift array. ++ shift &= 63; + +-static inline uint64_t // +-wuffs_base__swap_u64_argb_abgr(uint64_t u) { +- uint64_t o = u & 0xFFFF0000FFFF0000ull; +- uint64_t r = u & 0x0000FFFF00000000ull; +- uint64_t b = u & 0x000000000000FFFFull; +- return o | (r >> 32) | (b << 32); +-} ++ uint32_t x_a = wuffs_private_impl__hpd_left_shift[shift]; ++ uint32_t x_b = wuffs_private_impl__hpd_left_shift[shift + 1]; ++ uint32_t num_new_digits = x_a >> 11; ++ uint32_t pow5_a = 0x7FF & x_a; ++ uint32_t pow5_b = 0x7FF & x_b; + +-static inline uint32_t // +-wuffs_base__color_u64__as__color_u32__swap_u32_argb_abgr(uint64_t c) { +- uint32_t a = ((uint32_t)(0xFF & (c >> 56))); +- uint32_t r = ((uint32_t)(0xFF & (c >> 40))); +- uint32_t g = ((uint32_t)(0xFF & (c >> 24))); +- uint32_t b = ((uint32_t)(0xFF & (c >> 8))); +- return (a << 24) | (b << 16) | (g << 8) | (r << 0); ++ const uint8_t* pow5 = &wuffs_private_impl__powers_of_5[pow5_a]; ++ uint32_t i = 0; ++ uint32_t n = pow5_b - pow5_a; ++ for (; i < n; i++) { ++ if (i >= h->num_digits) { ++ return num_new_digits - 1; ++ } else if (h->digits[i] == pow5[i]) { ++ continue; ++ } else if (h->digits[i] < pow5[i]) { ++ return num_new_digits - 1; ++ } else { ++ return num_new_digits; ++ } ++ } ++ return num_new_digits; + } + + // -------- + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul // +-wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb, +- uint32_t x, +- uint32_t y) { +- if (!pb || (x >= pb->pixcfg.private_impl.width) || +- (y >= pb->pixcfg.private_impl.height)) { ++// wuffs_private_impl__high_prec_dec__rounded_integer returns the integral ++// (non-fractional) part of h, provided that it is 18 or fewer decimal digits. ++// For 19 or more digits, it returns UINT64_MAX. Note that: ++// - (1 << 53) is 9007199254740992, which has 16 decimal digits. ++// - (1 << 56) is 72057594037927936, which has 17 decimal digits. ++// - (1 << 59) is 576460752303423488, which has 18 decimal digits. ++// - (1 << 63) is 9223372036854775808, which has 19 decimal digits. ++// and that IEEE 754 double precision has 52 mantissa bits. ++// ++// That integral part is rounded-to-even: rounding 7.5 or 8.5 both give 8. ++// ++// h's negative bit is ignored: rounding -8.6 returns 9. ++// ++// See below for preconditions. ++static uint64_t // ++wuffs_private_impl__high_prec_dec__rounded_integer( ++ wuffs_private_impl__high_prec_dec* h) { ++ if ((h->num_digits == 0) || (h->decimal_point < 0)) { + return 0; ++ } else if (h->decimal_point > 18) { ++ return UINT64_MAX; + } + +- if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) { +- // TODO: support planar formats. +- return 0; ++ uint32_t dp = (uint32_t)(h->decimal_point); ++ uint64_t n = 0; ++ uint32_t i = 0; ++ for (; i < dp; i++) { ++ n = (10 * n) + ((i < h->num_digits) ? h->digits[i] : 0); + } + +- size_t stride = pb->private_impl.planes[0].stride; +- const uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)); ++ bool round_up = false; ++ if (dp < h->num_digits) { ++ round_up = h->digits[dp] >= 5; ++ if ((h->digits[dp] == 5) && (dp + 1 == h->num_digits)) { ++ // We are exactly halfway. If we're truncated, round up, otherwise round ++ // to even. ++ round_up = h->truncated || // ++ ((dp > 0) && (1 & h->digits[dp - 1])); ++ } ++ } ++ if (round_up) { ++ n++; ++ } + +- switch (pb->pixcfg.private_impl.pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- return wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))); ++ return n; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: { +- uint8_t* palette = pb->private_impl.planes[3].ptr; +- return wuffs_base__peek_u32le__no_bounds_check(palette + +- (4 * ((size_t)row[x]))); +- } ++// wuffs_private_impl__high_prec_dec__small_xshift shifts h's number (where 'x' ++// is 'l' or 'r' for left or right) by a small shift value. ++// ++// Preconditions: ++// - h is non-NULL. ++// - h->decimal_point is "not extreme". ++// - shift is non-zero. ++// - shift is "a small shift". ++// ++// "Not extreme" means within ±WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE. ++// ++// "A small shift" means not more than ++// WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL. ++// ++// wuffs_private_impl__high_prec_dec__rounded_integer and ++// wuffs_private_impl__high_prec_dec__lshift_num_new_digits have the same ++// preconditions. ++// ++// wuffs_private_impl__high_prec_dec__lshift keeps the first two preconditions ++// but not the last two. Its shift argument is signed and does not need to be ++// "small": zero is a no-op, positive means left shift and negative means right ++// shift. + +- // Common formats above. Rarer formats below. ++static void // ++wuffs_private_impl__high_prec_dec__small_lshift( ++ wuffs_private_impl__high_prec_dec* h, ++ uint32_t shift) { ++ if (h->num_digits == 0) { ++ return; ++ } ++ uint32_t num_new_digits = ++ wuffs_private_impl__high_prec_dec__lshift_num_new_digits(h, shift); ++ uint32_t rx = h->num_digits - 1; // Read index. ++ uint32_t wx = h->num_digits - 1 + num_new_digits; // Write index. ++ uint64_t n = 0; + +- case WUFFS_BASE__PIXEL_FORMAT__Y: +- return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x]))); +- case WUFFS_BASE__PIXEL_FORMAT__Y_16LE: +- return 0xFF000000 | (0x00010101 * ((uint32_t)(row[(2 * x) + 1]))); +- case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: +- return 0xFF000000 | (0x00010101 * ((uint32_t)(row[(2 * x) + 0]))); ++ // Repeat: pick up a digit, put down a digit, right to left. ++ while (((int32_t)rx) >= 0) { ++ n += ((uint64_t)(h->digits[rx])) << shift; ++ uint64_t quo = n / 10; ++ uint64_t rem = n - (10 * quo); ++ if (wx < WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION) { ++ h->digits[wx] = (uint8_t)rem; ++ } else if (rem > 0) { ++ h->truncated = true; ++ } ++ n = quo; ++ wx--; ++ rx--; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: { +- uint8_t* palette = pb->private_impl.planes[3].ptr; +- return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u32le__no_bounds_check(palette + +- (4 * ((size_t)row[x])))); ++ // Put down leading digits, right to left. ++ while (n > 0) { ++ uint64_t quo = n / 10; ++ uint64_t rem = n - (10 * quo); ++ if (wx < WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION) { ++ h->digits[wx] = (uint8_t)rem; ++ } else if (rem > 0) { ++ h->truncated = true; + } ++ n = quo; ++ wx--; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( +- wuffs_base__peek_u16le__no_bounds_check(row + (2 * ((size_t)x)))); +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- return 0xFF000000 | +- wuffs_base__peek_u24le__no_bounds_check(row + (3 * ((size_t)x))); +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)))); +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- return wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u64le__no_bounds_check(row + (8 * ((size_t)x)))); +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- return 0xFF000000 | +- wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))); ++ // Finish. ++ h->num_digits += num_new_digits; ++ if (h->num_digits > WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION) { ++ h->num_digits = WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION; ++ } ++ h->decimal_point += (int32_t)num_new_digits; ++ wuffs_private_impl__high_prec_dec__trim(h); ++} + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- return wuffs_base__swap_u32_argb_abgr( +- 0xFF000000 | +- wuffs_base__peek_u24le__no_bounds_check(row + (3 * ((size_t)x)))); +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- return wuffs_base__swap_u32_argb_abgr( +- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u32le__no_bounds_check(row + +- (4 * ((size_t)x))))); +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- return wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)))); +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- return wuffs_base__swap_u32_argb_abgr( +- 0xFF000000 | +- wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)))); ++static void // ++wuffs_private_impl__high_prec_dec__small_rshift( ++ wuffs_private_impl__high_prec_dec* h, ++ uint32_t shift) { ++ uint32_t rx = 0; // Read index. ++ uint32_t wx = 0; // Write index. ++ uint64_t n = 0; + +- default: +- // TODO: support more formats. ++ // Pick up enough leading digits to cover the first shift. ++ while ((n >> shift) == 0) { ++ if (rx < h->num_digits) { ++ // Read a digit. ++ n = (10 * n) + h->digits[rx++]; ++ } else if (n == 0) { ++ // h's number used to be zero and remains zero. ++ return; ++ } else { ++ // Read sufficient implicit trailing zeroes. ++ while ((n >> shift) == 0) { ++ n = 10 * n; ++ rx++; ++ } + break; ++ } ++ } ++ h->decimal_point -= ((int32_t)(rx - 1)); ++ if (h->decimal_point < -WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE) { ++ // After the shift, h's number is effectively zero. ++ h->num_digits = 0; ++ h->decimal_point = 0; ++ h->truncated = false; ++ return; + } + +- return 0; ++ // Repeat: pick up a digit, put down a digit, left to right. ++ uint64_t mask = (((uint64_t)(1)) << shift) - 1; ++ while (rx < h->num_digits) { ++ uint8_t new_digit = ((uint8_t)(n >> shift)); ++ n = (10 * (n & mask)) + h->digits[rx++]; ++ h->digits[wx++] = new_digit; ++ } ++ ++ // Put down trailing digits, left to right. ++ while (n > 0) { ++ uint8_t new_digit = ((uint8_t)(n >> shift)); ++ n = 10 * (n & mask); ++ if (wx < WUFFS_PRIVATE_IMPL__HPD__DIGITS_PRECISION) { ++ h->digits[wx++] = new_digit; ++ } else if (new_digit > 0) { ++ h->truncated = true; ++ } ++ } ++ ++ // Finish. ++ h->num_digits = wx; ++ wuffs_private_impl__high_prec_dec__trim(h); ++} ++ ++static void // ++wuffs_private_impl__high_prec_dec__lshift(wuffs_private_impl__high_prec_dec* h, ++ int32_t shift) { ++ if (shift > 0) { ++ while (shift > +WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL) { ++ wuffs_private_impl__high_prec_dec__small_lshift( ++ h, WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL); ++ shift -= WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL; ++ } ++ wuffs_private_impl__high_prec_dec__small_lshift(h, ((uint32_t)(+shift))); ++ } else if (shift < 0) { ++ while (shift < -WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL) { ++ wuffs_private_impl__high_prec_dec__small_rshift( ++ h, WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL); ++ shift += WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL; ++ } ++ wuffs_private_impl__high_prec_dec__small_rshift(h, ((uint32_t)(-shift))); ++ } + } + + // -------- + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status // +-wuffs_base__pixel_buffer__set_color_u32_at( +- wuffs_base__pixel_buffer* pb, +- uint32_t x, +- uint32_t y, +- wuffs_base__color_u32_argb_premul color) { +- if (!pb) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++// wuffs_private_impl__high_prec_dec__round_etc rounds h's number. For those ++// functions that take an n argument, rounding produces at most n digits (which ++// is not necessarily at most n decimal places). Negative n values are ignored, ++// as well as any n greater than or equal to h's number of digits. The ++// etc__round_just_enough function implicitly chooses an n to implement ++// WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION. ++// ++// Preconditions: ++// - h is non-NULL. ++// - h->decimal_point is "not extreme". ++// ++// "Not extreme" means within ±WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE. ++ ++static void // ++wuffs_private_impl__high_prec_dec__round_down( ++ wuffs_private_impl__high_prec_dec* h, ++ int32_t n) { ++ if ((n < 0) || (h->num_digits <= (uint32_t)n)) { ++ return; + } +- if ((x >= pb->pixcfg.private_impl.width) || +- (y >= pb->pixcfg.private_impl.height)) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ h->num_digits = (uint32_t)(n); ++ wuffs_private_impl__high_prec_dec__trim(h); ++} ++ ++static void // ++wuffs_private_impl__high_prec_dec__round_up( ++ wuffs_private_impl__high_prec_dec* h, ++ int32_t n) { ++ if ((n < 0) || (h->num_digits <= (uint32_t)n)) { ++ return; + } + +- if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) { +- // TODO: support planar formats. +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ for (n--; n >= 0; n--) { ++ if (h->digits[n] < 9) { ++ h->digits[n]++; ++ h->num_digits = (uint32_t)(n + 1); ++ return; ++ } + } + +- size_t stride = pb->private_impl.planes[0].stride; +- uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)); ++ // The number is all 9s. Change to a single 1 and adjust the decimal point. ++ h->digits[0] = 1; ++ h->num_digits = 1; ++ h->decimal_point++; ++} + +- switch (pb->pixcfg.private_impl.pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- wuffs_base__poke_u32le__no_bounds_check(row + (4 * ((size_t)x)), color); +- break; ++static void // ++wuffs_private_impl__high_prec_dec__round_nearest( ++ wuffs_private_impl__high_prec_dec* h, ++ int32_t n) { ++ if ((n < 0) || (h->num_digits <= (uint32_t)n)) { ++ return; ++ } ++ bool up = h->digits[n] >= 5; ++ if ((h->digits[n] == 5) && ((n + 1) == ((int32_t)(h->num_digits)))) { ++ up = h->truncated || // ++ ((n > 0) && ((h->digits[n - 1] & 1) != 0)); ++ } + +- // Common formats above. Rarer formats below. +- +- case WUFFS_BASE__PIXEL_FORMAT__Y: +- wuffs_base__poke_u8__no_bounds_check( +- row + ((size_t)x), +- wuffs_base__color_u32_argb_premul__as__color_u8_gray(color)); +- break; +- case WUFFS_BASE__PIXEL_FORMAT__Y_16LE: +- wuffs_base__poke_u16le__no_bounds_check( +- row + (2 * ((size_t)x)), +- wuffs_base__color_u32_argb_premul__as__color_u16_gray(color)); +- break; +- case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: +- wuffs_base__poke_u16be__no_bounds_check( +- row + (2 * ((size_t)x)), +- wuffs_base__color_u32_argb_premul__as__color_u16_gray(color)); +- break; +- +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: +- wuffs_base__poke_u8__no_bounds_check( +- row + ((size_t)x), wuffs_base__pixel_palette__closest_element( +- wuffs_base__pixel_buffer__palette(pb), +- pb->pixcfg.private_impl.pixfmt, color)); +- break; +- +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- wuffs_base__poke_u16le__no_bounds_check( +- row + (2 * ((size_t)x)), +- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color)); +- break; +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- wuffs_base__poke_u24le__no_bounds_check(row + (3 * ((size_t)x)), color); +- break; +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- wuffs_base__poke_u32le__no_bounds_check( +- row + (4 * ((size_t)x)), +- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( +- color)); +- break; +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- wuffs_base__poke_u64le__no_bounds_check( +- row + (8 * ((size_t)x)), +- wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul( +- color)); +- break; +- +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- wuffs_base__poke_u24le__no_bounds_check( +- row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color)); +- break; +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- wuffs_base__poke_u32le__no_bounds_check( +- row + (4 * ((size_t)x)), +- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( +- wuffs_base__swap_u32_argb_abgr(color))); +- break; +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- wuffs_base__poke_u32le__no_bounds_check( +- row + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color)); +- break; +- +- default: +- // TODO: support more formats. +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ if (up) { ++ wuffs_private_impl__high_prec_dec__round_up(h, n); ++ } else { ++ wuffs_private_impl__high_prec_dec__round_down(h, n); + } +- +- return wuffs_base__make_status(NULL); + } + +-// -------- +- +-static inline void // +-wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx( +- wuffs_base__pixel_buffer* pb, +- wuffs_base__rect_ie_u32 rect, +- uint16_t color) { +- size_t stride = pb->private_impl.planes[0].stride; +- uint32_t width = wuffs_base__rect_ie_u32__width(&rect); +- if ((stride == (2 * ((uint64_t)width))) && (rect.min_incl_x == 0)) { +- uint8_t* ptr = +- pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y)); +- uint32_t height = wuffs_base__rect_ie_u32__height(&rect); +- size_t n; +- for (n = ((size_t)width) * ((size_t)height); n > 0; n--) { +- wuffs_base__poke_u16le__no_bounds_check(ptr, color); +- ptr += 2; +- } ++static void // ++wuffs_private_impl__high_prec_dec__round_just_enough( ++ wuffs_private_impl__high_prec_dec* h, ++ int32_t exp2, ++ uint64_t mantissa) { ++ // The magic numbers 52 and 53 in this function are because IEEE 754 double ++ // precision has 52 mantissa bits. ++ // ++ // Let f be the floating point number represented by exp2 and mantissa (and ++ // also the number in h): the number (mantissa * (2 ** (exp2 - 52))). ++ // ++ // If f is zero or a small integer, we can return early. ++ if ((mantissa == 0) || ++ ((exp2 < 53) && (h->decimal_point >= ((int32_t)(h->num_digits))))) { + return; + } + +- uint32_t y; +- for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { +- uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) + +- (2 * ((size_t)rect.min_incl_x)); +- uint32_t n; +- for (n = width; n > 0; n--) { +- wuffs_base__poke_u16le__no_bounds_check(ptr, color); +- ptr += 2; +- } +- } +-} ++ // The smallest normal f has an exp2 of -1022 and a mantissa of (1 << 52). ++ // Subnormal numbers have the same exp2 but a smaller mantissa. ++ static const int32_t min_incl_normal_exp2 = -1022; ++ static const uint64_t min_incl_normal_mantissa = 0x0010000000000000ul; + +-static inline void // +-wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx( +- wuffs_base__pixel_buffer* pb, +- wuffs_base__rect_ie_u32 rect, +- uint32_t color) { +- size_t stride = pb->private_impl.planes[0].stride; +- uint32_t width = wuffs_base__rect_ie_u32__width(&rect); +- if ((stride == (3 * ((uint64_t)width))) && (rect.min_incl_x == 0)) { +- uint8_t* ptr = +- pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y)); +- uint32_t height = wuffs_base__rect_ie_u32__height(&rect); +- size_t n; +- for (n = ((size_t)width) * ((size_t)height); n > 0; n--) { +- wuffs_base__poke_u24le__no_bounds_check(ptr, color); +- ptr += 3; +- } +- return; ++ // Compute lower and upper bounds such that any number between them (possibly ++ // inclusive) will round to f. First, the lower bound. Our number f is: ++ // ((mantissa + 0) * (2 ** ( exp2 - 52))) ++ // ++ // The next lowest floating point number is: ++ // ((mantissa - 1) * (2 ** ( exp2 - 52))) ++ // unless (mantissa - 1) drops the (1 << 52) bit and exp2 is not the ++ // min_incl_normal_exp2. Either way, call it: ++ // ((l_mantissa) * (2 ** (l_exp2 - 52))) ++ // ++ // The lower bound is halfway between them (noting that 52 became 53): ++ // (((2 * l_mantissa) + 1) * (2 ** (l_exp2 - 53))) ++ int32_t l_exp2 = exp2; ++ uint64_t l_mantissa = mantissa - 1; ++ if ((exp2 > min_incl_normal_exp2) && (mantissa <= min_incl_normal_mantissa)) { ++ l_exp2 = exp2 - 1; ++ l_mantissa = (2 * mantissa) - 1; + } ++ wuffs_private_impl__high_prec_dec lower; ++ wuffs_private_impl__high_prec_dec__assign(&lower, (2 * l_mantissa) + 1, ++ false); ++ wuffs_private_impl__high_prec_dec__lshift(&lower, l_exp2 - 53); + +- uint32_t y; +- for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { +- uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) + +- (3 * ((size_t)rect.min_incl_x)); +- uint32_t n; +- for (n = width; n > 0; n--) { +- wuffs_base__poke_u24le__no_bounds_check(ptr, color); +- ptr += 3; +- } +- } +-} ++ // Next, the upper bound. Our number f is: ++ // ((mantissa + 0) * (2 ** (exp2 - 52))) ++ // ++ // The next highest floating point number is: ++ // ((mantissa + 1) * (2 ** (exp2 - 52))) ++ // ++ // The upper bound is halfway between them (noting that 52 became 53): ++ // (((2 * mantissa) + 1) * (2 ** (exp2 - 53))) ++ wuffs_private_impl__high_prec_dec upper; ++ wuffs_private_impl__high_prec_dec__assign(&upper, (2 * mantissa) + 1, false); ++ wuffs_private_impl__high_prec_dec__lshift(&upper, exp2 - 53); + +-static inline void // +-wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx( +- wuffs_base__pixel_buffer* pb, +- wuffs_base__rect_ie_u32 rect, +- uint32_t color) { +- size_t stride = pb->private_impl.planes[0].stride; +- uint32_t width = wuffs_base__rect_ie_u32__width(&rect); +- if ((stride == (4 * ((uint64_t)width))) && (rect.min_incl_x == 0)) { +- uint8_t* ptr = +- pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y)); +- uint32_t height = wuffs_base__rect_ie_u32__height(&rect); +- size_t n; +- for (n = ((size_t)width) * ((size_t)height); n > 0; n--) { +- wuffs_base__poke_u32le__no_bounds_check(ptr, color); +- ptr += 4; +- } +- return; +- } ++ // The lower and upper bounds are possible outputs only if the original ++ // mantissa is even, so that IEEE round-to-even would round to the original ++ // mantissa and not its neighbors. ++ bool inclusive = (mantissa & 1) == 0; + +- uint32_t y; +- for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { +- uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) + +- (4 * ((size_t)rect.min_incl_x)); +- uint32_t n; +- for (n = width; n > 0; n--) { +- wuffs_base__poke_u32le__no_bounds_check(ptr, color); +- ptr += 4; +- } +- } +-} ++ // As we walk the digits, we want to know whether rounding up would fall ++ // within the upper bound. This is tracked by upper_delta: ++ // - When -1, the digits of h and upper are the same so far. ++ // - When +0, we saw a difference of 1 between h and upper on a previous ++ // digit and subsequently only 9s for h and 0s for upper. Thus, rounding ++ // up may fall outside of the bound if !inclusive. ++ // - When +1, the difference is greater than 1 and we know that rounding up ++ // falls within the bound. ++ // ++ // This is a state machine with three states. The numerical value for each ++ // state (-1, +0 or +1) isn't important, other than their order. ++ int upper_delta = -1; + +-static inline void // +-wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx( +- wuffs_base__pixel_buffer* pb, +- wuffs_base__rect_ie_u32 rect, +- uint64_t color) { +- size_t stride = pb->private_impl.planes[0].stride; +- uint32_t width = wuffs_base__rect_ie_u32__width(&rect); +- if ((stride == (8 * ((uint64_t)width))) && (rect.min_incl_x == 0)) { +- uint8_t* ptr = +- pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y)); +- uint32_t height = wuffs_base__rect_ie_u32__height(&rect); +- size_t n; +- for (n = ((size_t)width) * ((size_t)height); n > 0; n--) { +- wuffs_base__poke_u64le__no_bounds_check(ptr, color); +- ptr += 8; ++ // We can now figure out the shortest number of digits required. Walk the ++ // digits until h has distinguished itself from lower or upper. ++ // ++ // The zi and zd variables are indexes and digits, for z in l (lower), h (the ++ // number) and u (upper). ++ // ++ // The lower, h and upper numbers may have their decimal points at different ++ // places. In this case, upper is the longest, so we iterate ui starting from ++ // 0 and iterate li and hi starting from either 0 or -1. ++ int32_t ui = 0; ++ for (;; ui++) { ++ // Calculate hd, the middle number's digit. ++ int32_t hi = ui - upper.decimal_point + h->decimal_point; ++ if (hi >= ((int32_t)(h->num_digits))) { ++ break; + } +- return; +- } ++ uint8_t hd = (((uint32_t)hi) < h->num_digits) ? h->digits[hi] : 0; + +- uint32_t y; +- for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { +- uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) + +- (8 * ((size_t)rect.min_incl_x)); +- uint32_t n; +- for (n = width; n > 0; n--) { +- wuffs_base__poke_u64le__no_bounds_check(ptr, color); +- ptr += 8; ++ // Calculate ld, the lower bound's digit. ++ int32_t li = ui - upper.decimal_point + lower.decimal_point; ++ uint8_t ld = (((uint32_t)li) < lower.num_digits) ? lower.digits[li] : 0; ++ ++ // We can round down (truncate) if lower has a different digit than h or if ++ // lower is inclusive and is exactly the result of rounding down (i.e. we ++ // have reached the final digit of lower). ++ bool can_round_down = ++ (ld != hd) || // ++ (inclusive && ((li + 1) == ((int32_t)(lower.num_digits)))); ++ ++ // Calculate ud, the upper bound's digit, and update upper_delta. ++ uint8_t ud = (((uint32_t)ui) < upper.num_digits) ? upper.digits[ui] : 0; ++ if (upper_delta < 0) { ++ if ((hd + 1) < ud) { ++ // For example: ++ // h = 12345??? ++ // upper = 12347??? ++ upper_delta = +1; ++ } else if (hd != ud) { ++ // For example: ++ // h = 12345??? ++ // upper = 12346??? ++ upper_delta = +0; ++ } ++ } else if (upper_delta == 0) { ++ if ((hd != 9) || (ud != 0)) { ++ // For example: ++ // h = 1234598? ++ // upper = 1234600? ++ upper_delta = +1; ++ } + } +- } +-} + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status // +-wuffs_base__pixel_buffer__set_color_u32_fill_rect( +- wuffs_base__pixel_buffer* pb, +- wuffs_base__rect_ie_u32 rect, +- wuffs_base__color_u32_argb_premul color) { +- if (!pb) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } else if (wuffs_base__rect_ie_u32__is_empty(&rect)) { +- return wuffs_base__make_status(NULL); +- } +- wuffs_base__rect_ie_u32 bounds = +- wuffs_base__pixel_config__bounds(&pb->pixcfg); +- if (!wuffs_base__rect_ie_u32__contains_rect(&bounds, rect)) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } ++ // We can round up if upper has a different digit than h and either upper ++ // is inclusive or upper is bigger than the result of rounding up. ++ bool can_round_up = ++ (upper_delta > 0) || // ++ ((upper_delta == 0) && // ++ (inclusive || ((ui + 1) < ((int32_t)(upper.num_digits))))); + +- if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) { +- // TODO: support planar formats. +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ // If we can round either way, round to nearest. If we can round only one ++ // way, do it. If we can't round, continue the loop. ++ if (can_round_down) { ++ if (can_round_up) { ++ wuffs_private_impl__high_prec_dec__round_nearest(h, hi + 1); ++ return; ++ } else { ++ wuffs_private_impl__high_prec_dec__round_down(h, hi + 1); ++ return; ++ } ++ } else { ++ if (can_round_up) { ++ wuffs_private_impl__high_prec_dec__round_up(h, hi + 1); ++ return; ++ } ++ } + } ++} + +- switch (pb->pixcfg.private_impl.pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, color); +- return wuffs_base__make_status(NULL); +- +- // Common formats above. Rarer formats below. ++// -------- + +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx( +- pb, rect, +- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color)); +- return wuffs_base__make_status(NULL); ++// wuffs_private_impl__parse_number_f64_eisel_lemire produces the IEEE 754 ++// double-precision value for an exact mantissa and base-10 exponent. For ++// example: ++// - when parsing "12345.678e+02", man is 12345678 and exp10 is -1. ++// - when parsing "-12", man is 12 and exp10 is 0. Processing the leading ++// minus sign is the responsibility of the caller, not this function. ++// ++// On success, it returns a non-negative int64_t such that the low 63 bits hold ++// the 11-bit exponent and 52-bit mantissa. ++// ++// On failure, it returns a negative value. ++// ++// The algorithm is based on an original idea by Michael Eisel that was refined ++// by Daniel Lemire. See ++// https://lemire.me/blog/2020/03/10/fast-float-parsing-in-practice/ ++// and ++// https://nigeltao.github.io/blog/2020/eisel-lemire.html ++// ++// Preconditions: ++// - man is non-zero. ++// - exp10 is in the range [-307 ..= 288], the same range of the ++// wuffs_private_impl__powers_of_10 array. ++// ++// The exp10 range (and the fact that man is in the range [1 ..= UINT64_MAX], ++// approximately [1 ..= 1.85e+19]) means that (man * (10 ** exp10)) is in the ++// range [1e-307 ..= 1.85e+307]. This is entirely within the range of normal ++// (neither subnormal nor non-finite) f64 values: DBL_MIN and DBL_MAX are ++// approximately 2.23e–308 and 1.80e+308. ++static int64_t // ++wuffs_private_impl__parse_number_f64_eisel_lemire(uint64_t man, int32_t exp10) { ++ // Look up the (possibly truncated) base-2 representation of (10 ** exp10). ++ // The look-up table was constructed so that it is already normalized: the ++ // table entry's mantissa's MSB (most significant bit) is on. ++ const uint64_t* po10 = &wuffs_private_impl__powers_of_10[exp10 + 307][0]; + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(pb, rect, color); +- return wuffs_base__make_status(NULL); ++ // Normalize the man argument. The (man != 0) precondition means that a ++ // non-zero bit exists. ++ uint32_t clz = wuffs_base__count_leading_zeroes_u64(man); ++ man <<= clz; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx( +- pb, rect, +- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( +- color)); +- return wuffs_base__make_status(NULL); ++ // Calculate the return value's base-2 exponent. We might tweak it by ±1 ++ // later, but its initial value comes from a linear scaling of exp10, ++ // converting from power-of-10 to power-of-2, and adjusting by clz. ++ // ++ // The magic constants are: ++ // - 1087 = 1023 + 64. The 1023 is the f64 exponent bias. The 64 is because ++ // the look-up table uses 64-bit mantissas. ++ // - 217706 is such that the ratio 217706 / 65536 ≈ 3.321930 is close enough ++ // (over the practical range of exp10) to log(10) / log(2) ≈ 3.321928. ++ // - 65536 = 1<<16 is arbitrary but a power of 2, so division is a shift. ++ // ++ // Equality of the linearly-scaled value and the actual power-of-2, over the ++ // range of exp10 arguments that this function accepts, is confirmed by ++ // script/print-mpb-powers-of-10.go ++ uint64_t ret_exp2 = ++ ((uint64_t)(((217706 * exp10) >> 16) + 1087)) - ((uint64_t)clz); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx( +- pb, rect, +- wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul( +- color)); +- return wuffs_base__make_status(NULL); ++ // Multiply the two mantissas. Normalization means that both mantissas are at ++ // least (1<<63), so the 128-bit product must be at least (1<<126). The high ++ // 64 bits of the product, x_hi, must therefore be at least (1<<62). ++ // ++ // As a consequence, x_hi has either 0 or 1 leading zeroes. Shifting x_hi ++ // right by either 9 or 10 bits (depending on x_hi's MSB) will therefore ++ // leave the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on. ++ wuffs_base__multiply_u64__output x = wuffs_base__multiply_u64(man, po10[1]); ++ uint64_t x_hi = x.hi; ++ uint64_t x_lo = x.lo; + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx( +- pb, rect, +- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( +- wuffs_base__swap_u32_argb_abgr(color))); +- return wuffs_base__make_status(NULL); ++ // Before we shift right by at least 9 bits, recall that the look-up table ++ // entry was possibly truncated. We have so far only calculated a lower bound ++ // for the product (man * e), where e is (10 ** exp10). The upper bound would ++ // add a further (man * 1) to the 128-bit product, which overflows the lower ++ // 64-bit limb if ((x_lo + man) < man). ++ // ++ // If overflow occurs, that adds 1 to x_hi. Since we're about to shift right ++ // by at least 9 bits, that carried 1 can be ignored unless the higher 64-bit ++ // limb's low 9 bits are all on. ++ // ++ // For example, parsing "9999999999999999999" will take the if-true branch ++ // here, since: ++ // - x_hi = 0x4563918244F3FFFF ++ // - x_lo = 0x8000000000000000 ++ // - man = 0x8AC7230489E7FFFF ++ if (((x_hi & 0x1FF) == 0x1FF) && ((x_lo + man) < man)) { ++ // Refine our calculation of (man * e). Before, our approximation of e used ++ // a "low resolution" 64-bit mantissa. Now use a "high resolution" 128-bit ++ // mantissa. We've already calculated x = (man * bits_0_to_63_incl_of_e). ++ // Now calculate y = (man * bits_64_to_127_incl_of_e). ++ wuffs_base__multiply_u64__output y = wuffs_base__multiply_u64(man, po10[0]); ++ uint64_t y_hi = y.hi; ++ uint64_t y_lo = y.lo; + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx( +- pb, rect, wuffs_base__swap_u32_argb_abgr(color)); +- return wuffs_base__make_status(NULL); +- } ++ // Merge the 128-bit x and 128-bit y, which overlap by 64 bits, to ++ // calculate the 192-bit product of the 64-bit man by the 128-bit e. ++ // As we exit this if-block, we only care about the high 128 bits ++ // (merged_hi and merged_lo) of that 192-bit product. ++ // ++ // For example, parsing "1.234e-45" will take the if-true branch here, ++ // since: ++ // - x_hi = 0x70B7E3696DB29FFF ++ // - x_lo = 0xE040000000000000 ++ // - y_hi = 0x33718BBEAB0E0D7A ++ // - y_lo = 0xA880000000000000 ++ uint64_t merged_hi = x_hi; ++ uint64_t merged_lo = x_lo + y_hi; ++ if (merged_lo < x_lo) { ++ merged_hi++; // Carry the overflow bit. ++ } + +- uint32_t y; +- for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { +- uint32_t x; +- for (x = rect.min_incl_x; x < rect.max_excl_x; x++) { +- wuffs_base__pixel_buffer__set_color_u32_at(pb, x, y, color); ++ // The "high resolution" approximation of e is still a lower bound. Once ++ // again, see if the upper bound is large enough to produce a different ++ // result. This time, if it does, give up instead of reaching for an even ++ // more precise approximation to e. ++ // ++ // This three-part check is similar to the two-part check that guarded the ++ // if block that we're now in, but it has an extra term for the middle 64 ++ // bits (checking that adding 1 to merged_lo would overflow). ++ // ++ // For example, parsing "5.9604644775390625e-8" will take the if-true ++ // branch here, since: ++ // - merged_hi = 0x7FFFFFFFFFFFFFFF ++ // - merged_lo = 0xFFFFFFFFFFFFFFFF ++ // - y_lo = 0x4DB3FFC120988200 ++ // - man = 0xD3C21BCECCEDA100 ++ if (((merged_hi & 0x1FF) == 0x1FF) && ((merged_lo + 1) == 0) && ++ (y_lo + man < man)) { ++ return -1; + } ++ ++ // Replace the 128-bit x with merged. ++ x_hi = merged_hi; ++ x_lo = merged_lo; + } +- return wuffs_base__make_status(NULL); +-} + +-// -------- ++ // As mentioned above, shifting x_hi right by either 9 or 10 bits will leave ++ // the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on. If the ++ // MSB (before shifting) was on, adjust ret_exp2 for the larger shift. ++ // ++ // Having bit 53 on (and higher bits off) means that ret_mantissa is a 54-bit ++ // number. ++ uint64_t msb = x_hi >> 63; ++ uint64_t ret_mantissa = x_hi >> (msb + 9); ++ ret_exp2 -= 1 ^ msb; + +-WUFFS_BASE__MAYBE_STATIC uint8_t // +-wuffs_base__pixel_palette__closest_element( +- wuffs_base__slice_u8 palette_slice, +- wuffs_base__pixel_format palette_format, +- wuffs_base__color_u32_argb_premul c) { +- size_t n = palette_slice.len / 4; +- if (n > (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- n = (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4); ++ // IEEE 754 rounds to-nearest with ties rounded to-even. Rounding to-even can ++ // be tricky. If we're half-way between two exactly representable numbers ++ // (x's low 73 bits are zero and the next 2 bits that matter are "01"), give ++ // up instead of trying to pick the winner. ++ // ++ // Technically, we could tighten the condition by changing "73" to "73 or 74, ++ // depending on msb", but a flat "73" is simpler. ++ // ++ // For example, parsing "1e+23" will take the if-true branch here, since: ++ // - x_hi = 0x54B40B1F852BDA00 ++ // - ret_mantissa = 0x002A5A058FC295ED ++ if ((x_lo == 0) && ((x_hi & 0x1FF) == 0) && ((ret_mantissa & 3) == 1)) { ++ return -1; + } +- size_t best_index = 0; +- uint64_t best_score = 0xFFFFFFFFFFFFFFFF; + +- // Work in 16-bit color. +- uint32_t ca = 0x101 * (0xFF & (c >> 24)); +- uint32_t cr = 0x101 * (0xFF & (c >> 16)); +- uint32_t cg = 0x101 * (0xFF & (c >> 8)); +- uint32_t cb = 0x101 * (0xFF & (c >> 0)); +- +- switch (palette_format.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: { +- bool nonpremul = palette_format.repr == +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL; +- +- size_t i; +- for (i = 0; i < n; i++) { +- // Work in 16-bit color. +- uint32_t pb = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 0])); +- uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1])); +- uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2])); +- uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3])); +- +- // Convert to premultiplied alpha. +- if (nonpremul && (pa != 0xFFFF)) { +- pb = (pb * pa) / 0xFFFF; +- pg = (pg * pa) / 0xFFFF; +- pr = (pr * pa) / 0xFFFF; +- } +- +- // These deltas are conceptually int32_t (signed) but after squaring, +- // it's equivalent to work in uint32_t (unsigned). +- pb -= cb; +- pg -= cg; +- pr -= cr; +- pa -= ca; +- uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) + +- ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa)); +- if (best_score > score) { +- best_score = score; +- best_index = i; +- } +- } +- break; +- } ++ // If we're not halfway then it's rounding to-nearest. Starting with a 54-bit ++ // number, carry the lowest bit (bit 0) up if it's on. Regardless of whether ++ // it was on or off, shifting right by one then produces a 53-bit number. If ++ // carrying up overflowed, shift again. ++ ret_mantissa += ret_mantissa & 1; ++ ret_mantissa >>= 1; ++ // This if block is equivalent to (but benchmarks slightly faster than) the ++ // following branchless form: ++ // uint64_t overflow_adjustment = ret_mantissa >> 53; ++ // ret_mantissa >>= overflow_adjustment; ++ // ret_exp2 += overflow_adjustment; ++ // ++ // For example, parsing "7.2057594037927933e+16" will take the if-true ++ // branch here, since: ++ // - x_hi = 0x7FFFFFFFFFFFFE80 ++ // - ret_mantissa = 0x0020000000000000 ++ if ((ret_mantissa >> 53) > 0) { ++ ret_mantissa >>= 1; ++ ret_exp2++; + } + +- return (uint8_t)best_index; ++ // Starting with a 53-bit number, IEEE 754 double-precision normal numbers ++ // have an implicit mantissa bit. Mask that away and keep the low 52 bits. ++ ret_mantissa &= 0x000FFFFFFFFFFFFF; ++ ++ // Pack the bits and return. ++ return ((int64_t)(ret_mantissa | (ret_exp2 << 52))); + } + + // -------- + +-static inline uint32_t // +-wuffs_base__composite_nonpremul_nonpremul_u32_axxx(uint32_t dst_nonpremul, +- uint32_t src_nonpremul) { +- // Extract 16-bit color components. +- // +- // If the destination is transparent then SRC_OVER is equivalent to SRC: just +- // return src_nonpremul. This isn't just an optimization (skipping the rest +- // of the function's computation). It also preserves the nonpremul +- // distinction between e.g. transparent red and transparent blue that would +- // otherwise be lost by converting from nonpremul to premul and back. +- uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24)); +- if (da == 0) { +- return src_nonpremul; +- } +- uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16)); +- uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8)); +- uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0)); +- uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24)); +- uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16)); +- uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8)); +- uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0)); +- +- // Convert dst from nonpremul to premul. +- dr = (dr * da) / 0xFFFF; +- dg = (dg * da) / 0xFFFF; +- db = (db * da) / 0xFFFF; ++static wuffs_base__result_f64 // ++wuffs_private_impl__parse_number_f64_special(wuffs_base__slice_u8 s, ++ uint32_t options) { ++ do { ++ if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) { ++ goto fail; ++ } + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ uint8_t* p = s.ptr; ++ uint8_t* q = s.ptr + s.len; + +- // Composite src (nonpremul) over dst (premul). +- da = sa + ((da * ia) / 0xFFFF); +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ for (; (p < q) && (*p == '_'); p++) { ++ } ++ if (p >= q) { ++ goto fail; ++ } + +- // Convert dst from premul to nonpremul. +- if (da != 0) { +- dr = (dr * 0xFFFF) / da; +- dg = (dg * 0xFFFF) / da; +- db = (db * 0xFFFF) / da; +- } ++ // Parse sign. ++ bool negative = false; ++ do { ++ if (*p == '+') { ++ p++; ++ } else if (*p == '-') { ++ negative = true; ++ p++; ++ } else { ++ break; ++ } ++ for (; (p < q) && (*p == '_'); p++) { ++ } ++ } while (0); ++ if (p >= q) { ++ goto fail; ++ } + +- // Convert from 16-bit color to 8-bit color. +- da >>= 8; +- dr >>= 8; +- dg >>= 8; +- db >>= 8; ++ bool nan = false; ++ switch (p[0]) { ++ case 'I': ++ case 'i': ++ if (((q - p) < 3) || // ++ ((p[1] != 'N') && (p[1] != 'n')) || // ++ ((p[2] != 'F') && (p[2] != 'f'))) { ++ goto fail; ++ } ++ p += 3; + +- // Combine components. +- return (db << 0) | (dg << 8) | (dr << 16) | (da << 24); +-} ++ if ((p >= q) || (*p == '_')) { ++ break; ++ } else if (((q - p) < 5) || // ++ ((p[0] != 'I') && (p[0] != 'i')) || // ++ ((p[1] != 'N') && (p[1] != 'n')) || // ++ ((p[2] != 'I') && (p[2] != 'i')) || // ++ ((p[3] != 'T') && (p[3] != 't')) || // ++ ((p[4] != 'Y') && (p[4] != 'y'))) { ++ goto fail; ++ } ++ p += 5; + +-static inline uint64_t // +-wuffs_base__composite_nonpremul_nonpremul_u64_axxx(uint64_t dst_nonpremul, +- uint64_t src_nonpremul) { +- // Extract components. +- // +- // If the destination is transparent then SRC_OVER is equivalent to SRC: just +- // return src_nonpremul. This isn't just an optimization (skipping the rest +- // of the function's computation). It also preserves the nonpremul +- // distinction between e.g. transparent red and transparent blue that would +- // otherwise be lost by converting from nonpremul to premul and back. +- uint64_t da = 0xFFFF & (dst_nonpremul >> 48); +- if (da == 0) { +- return src_nonpremul; +- } +- uint64_t dr = 0xFFFF & (dst_nonpremul >> 32); +- uint64_t dg = 0xFFFF & (dst_nonpremul >> 16); +- uint64_t db = 0xFFFF & (dst_nonpremul >> 0); +- uint64_t sa = 0xFFFF & (src_nonpremul >> 48); +- uint64_t sr = 0xFFFF & (src_nonpremul >> 32); +- uint64_t sg = 0xFFFF & (src_nonpremul >> 16); +- uint64_t sb = 0xFFFF & (src_nonpremul >> 0); ++ if ((p >= q) || (*p == '_')) { ++ break; ++ } ++ goto fail; + +- // Convert dst from nonpremul to premul. +- dr = (dr * da) / 0xFFFF; +- dg = (dg * da) / 0xFFFF; +- db = (db * da) / 0xFFFF; ++ case 'N': ++ case 'n': ++ if (((q - p) < 3) || // ++ ((p[1] != 'A') && (p[1] != 'a')) || // ++ ((p[2] != 'N') && (p[2] != 'n'))) { ++ goto fail; ++ } ++ p += 3; + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint64_t ia = 0xFFFF - sa; ++ if ((p >= q) || (*p == '_')) { ++ nan = true; ++ break; ++ } ++ goto fail; + +- // Composite src (nonpremul) over dst (premul). +- da = sa + ((da * ia) / 0xFFFF); +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ default: ++ goto fail; ++ } + +- // Convert dst from premul to nonpremul. +- if (da != 0) { +- dr = (dr * 0xFFFF) / da; +- dg = (dg * 0xFFFF) / da; +- db = (db * 0xFFFF) / da; +- } ++ // Finish. ++ for (; (p < q) && (*p == '_'); p++) { ++ } ++ if (p != q) { ++ goto fail; ++ } ++ wuffs_base__result_f64 ret; ++ ret.status.repr = NULL; ++ ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64( ++ (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) | ++ (negative ? 0x8000000000000000 : 0)); ++ return ret; ++ } while (0); + +- // Combine components. +- return (db << 0) | (dg << 16) | (dr << 32) | (da << 48); ++fail: ++ do { ++ wuffs_base__result_f64 ret; ++ ret.status.repr = wuffs_base__error__bad_argument; ++ ret.value = 0; ++ return ret; ++ } while (0); + } + +-static inline uint32_t // +-wuffs_base__composite_nonpremul_premul_u32_axxx(uint32_t dst_nonpremul, +- uint32_t src_premul) { +- // Extract 16-bit color components. +- uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24)); +- uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16)); +- uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8)); +- uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0)); +- uint32_t sa = 0x101 * (0xFF & (src_premul >> 24)); +- uint32_t sr = 0x101 * (0xFF & (src_premul >> 16)); +- uint32_t sg = 0x101 * (0xFF & (src_premul >> 8)); +- uint32_t sb = 0x101 * (0xFF & (src_premul >> 0)); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 // ++wuffs_private_impl__high_prec_dec__to_f64(wuffs_private_impl__high_prec_dec* h, ++ uint32_t options) { ++ do { ++ // powers converts decimal powers of 10 to binary powers of 2. For example, ++ // (10000 >> 13) is 1. It stops before the elements exceed 60, also known ++ // as WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL. ++ // ++ // This rounds down (1<<13 is a lower bound for 1e4). Adding 1 to the array ++ // element value rounds up (1<<14 is an upper bound for 1e4) while staying ++ // at or below WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL. ++ // ++ // When starting in the range [1e+1 .. 1e+2] (i.e. h->decimal_point == +2), ++ // powers[2] == 6 and so: ++ // - Right shifting by 6+0 produces the range [10/64 .. 100/64] = ++ // [0.156250 .. 1.56250]. The resultant h->decimal_point is +0 or +1. ++ // - Right shifting by 6+1 produces the range [10/128 .. 100/128] = ++ // [0.078125 .. 0.78125]. The resultant h->decimal_point is -1 or -0. ++ // ++ // When starting in the range [1e-3 .. 1e-2] (i.e. h->decimal_point == -2), ++ // powers[2] == 6 and so: ++ // - Left shifting by 6+0 produces the range [0.001*64 .. 0.01*64] = ++ // [0.064 .. 0.64]. The resultant h->decimal_point is -1 or -0. ++ // - Left shifting by 6+1 produces the range [0.001*128 .. 0.01*128] = ++ // [0.128 .. 1.28]. The resultant h->decimal_point is +0 or +1. ++ // ++ // Thus, when targeting h->decimal_point being +0 or +1, use (powers[n]+0) ++ // when right shifting but (powers[n]+1) when left shifting. ++ static const uint32_t num_powers = 19; ++ static const uint8_t powers[19] = { ++ 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, // ++ 33, 36, 39, 43, 46, 49, 53, 56, 59, // ++ }; + +- // Convert dst from nonpremul to premul. +- dr = (dr * da) / 0xFFFF; +- dg = (dg * da) / 0xFFFF; +- db = (db * da) / 0xFFFF; ++ // Handle zero and obvious extremes. The largest and smallest positive ++ // finite f64 values are approximately 1.8e+308 and 4.9e-324. ++ if ((h->num_digits == 0) || (h->decimal_point < -326)) { ++ goto zero; ++ } else if (h->decimal_point > 310) { ++ goto infinity; ++ } + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ // Try the fast Eisel-Lemire algorithm again. Calculating the (man, exp10) ++ // pair from the high_prec_dec h is more correct but slower than the ++ // approach taken in wuffs_base__parse_number_f64. The latter is optimized ++ // for the common cases (e.g. assuming no underscores or a leading '+' ++ // sign) rather than the full set of cases allowed by the Wuffs API. ++ // ++ // When we have 19 or fewer mantissa digits, run Eisel-Lemire once (trying ++ // for an exact result). When we have more than 19 mantissa digits, run it ++ // twice to get a lower and upper bound. We still have an exact result ++ // (within f64's rounding margin) if both bounds are equal (and valid). ++ uint32_t i_max = h->num_digits; ++ if (i_max > 19) { ++ i_max = 19; ++ } ++ int32_t exp10 = h->decimal_point - ((int32_t)i_max); ++ if ((-307 <= exp10) && (exp10 <= 288)) { ++ uint64_t man = 0; ++ uint32_t i; ++ for (i = 0; i < i_max; i++) { ++ man = (10 * man) + h->digits[i]; ++ } ++ while (man != 0) { // The 'while' is just an 'if' that we can 'break'. ++ int64_t r0 = ++ wuffs_private_impl__parse_number_f64_eisel_lemire(man + 0, exp10); ++ if (r0 < 0) { ++ break; ++ } else if (h->num_digits > 19) { ++ int64_t r1 = ++ wuffs_private_impl__parse_number_f64_eisel_lemire(man + 1, exp10); ++ if (r1 != r0) { ++ break; ++ } ++ } ++ wuffs_base__result_f64 ret; ++ ret.status.repr = NULL; ++ ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64( ++ ((uint64_t)r0) | (((uint64_t)(h->negative)) << 63)); ++ return ret; ++ } ++ } + +- // Composite src (premul) over dst (premul). +- da = sa + ((da * ia) / 0xFFFF); +- dr = sr + ((dr * ia) / 0xFFFF); +- dg = sg + ((dg * ia) / 0xFFFF); +- db = sb + ((db * ia) / 0xFFFF); ++ // When Eisel-Lemire fails, fall back to Simple Decimal Conversion. See ++ // https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html ++ // ++ // Scale by powers of 2 until we're in the range [0.1 .. 10]. Equivalently, ++ // that h->decimal_point is +0 or +1. ++ // ++ // First we shift right while at or above 10... ++ const int32_t f64_bias = -1023; ++ int32_t exp2 = 0; ++ while (h->decimal_point > 1) { ++ uint32_t n = (uint32_t)(+h->decimal_point); ++ uint32_t shift = (n < num_powers) ++ ? powers[n] ++ : WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL; + +- // Convert dst from premul to nonpremul. +- if (da != 0) { +- dr = (dr * 0xFFFF) / da; +- dg = (dg * 0xFFFF) / da; +- db = (db * 0xFFFF) / da; +- } ++ wuffs_private_impl__high_prec_dec__small_rshift(h, shift); ++ if (h->decimal_point < -WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE) { ++ goto zero; ++ } ++ exp2 += (int32_t)shift; ++ } ++ // ...then we shift left while below 0.1. ++ while (h->decimal_point < 0) { ++ uint32_t shift; ++ uint32_t n = (uint32_t)(-h->decimal_point); ++ shift = (n < num_powers) ++ // The +1 is per "when targeting h->decimal_point being +0 or ++ // +1... when left shifting" in the powers comment above. ++ ? (powers[n] + 1u) ++ : WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL; + +- // Convert from 16-bit color to 8-bit color. +- da >>= 8; +- dr >>= 8; +- dg >>= 8; +- db >>= 8; ++ wuffs_private_impl__high_prec_dec__small_lshift(h, shift); ++ if (h->decimal_point > +WUFFS_PRIVATE_IMPL__HPD__DECIMAL_POINT__RANGE) { ++ goto infinity; ++ } ++ exp2 -= (int32_t)shift; ++ } + +- // Combine components. +- return (db << 0) | (dg << 8) | (dr << 16) | (da << 24); +-} ++ // To get from "in the range [0.1 .. 10]" to "in the range [1 .. 2]" (which ++ // will give us our exponent in base-2), the mantissa's first 3 digits will ++ // determine the final left shift, equal to 52 (the number of explicit f64 ++ // bits) plus an additional adjustment. ++ int man3 = (100 * h->digits[0]) + ++ ((h->num_digits > 1) ? (10 * h->digits[1]) : 0) + ++ ((h->num_digits > 2) ? h->digits[2] : 0); ++ int32_t additional_lshift = 0; ++ if (h->decimal_point == 0) { // The value is in [0.1 .. 1]. ++ if (man3 < 125) { ++ additional_lshift = +4; ++ } else if (man3 < 250) { ++ additional_lshift = +3; ++ } else if (man3 < 500) { ++ additional_lshift = +2; ++ } else { ++ additional_lshift = +1; ++ } ++ } else { // The value is in [1 .. 10]. ++ if (man3 < 200) { ++ additional_lshift = -0; ++ } else if (man3 < 400) { ++ additional_lshift = -1; ++ } else if (man3 < 800) { ++ additional_lshift = -2; ++ } else { ++ additional_lshift = -3; ++ } ++ } ++ exp2 -= additional_lshift; ++ uint32_t final_lshift = (uint32_t)(52 + additional_lshift); + +-static inline uint64_t // +-wuffs_base__composite_nonpremul_premul_u64_axxx(uint64_t dst_nonpremul, +- uint64_t src_premul) { +- // Extract components. +- uint64_t da = 0xFFFF & (dst_nonpremul >> 48); +- uint64_t dr = 0xFFFF & (dst_nonpremul >> 32); +- uint64_t dg = 0xFFFF & (dst_nonpremul >> 16); +- uint64_t db = 0xFFFF & (dst_nonpremul >> 0); +- uint64_t sa = 0xFFFF & (src_premul >> 48); +- uint64_t sr = 0xFFFF & (src_premul >> 32); +- uint64_t sg = 0xFFFF & (src_premul >> 16); +- uint64_t sb = 0xFFFF & (src_premul >> 0); ++ // The minimum normal exponent is (f64_bias + 1). ++ while ((f64_bias + 1) > exp2) { ++ uint32_t n = (uint32_t)((f64_bias + 1) - exp2); ++ if (n > WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL) { ++ n = WUFFS_PRIVATE_IMPL__HPD__SHIFT__MAX_INCL; ++ } ++ wuffs_private_impl__high_prec_dec__small_rshift(h, n); ++ exp2 += (int32_t)n; ++ } + +- // Convert dst from nonpremul to premul. +- dr = (dr * da) / 0xFFFF; +- dg = (dg * da) / 0xFFFF; +- db = (db * da) / 0xFFFF; ++ // Check for overflow. ++ if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1. ++ goto infinity; ++ } + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint64_t ia = 0xFFFF - sa; ++ // Extract 53 bits for the mantissa (in base-2). ++ wuffs_private_impl__high_prec_dec__small_lshift(h, final_lshift); ++ uint64_t man2 = wuffs_private_impl__high_prec_dec__rounded_integer(h); + +- // Composite src (premul) over dst (premul). +- da = sa + ((da * ia) / 0xFFFF); +- dr = sr + ((dr * ia) / 0xFFFF); +- dg = sg + ((dg * ia) / 0xFFFF); +- db = sb + ((db * ia) / 0xFFFF); ++ // Rounding might have added one bit. If so, shift and re-check overflow. ++ if ((man2 >> 53) != 0) { ++ man2 >>= 1; ++ exp2++; ++ if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1. ++ goto infinity; ++ } ++ } + +- // Convert dst from premul to nonpremul. +- if (da != 0) { +- dr = (dr * 0xFFFF) / da; +- dg = (dg * 0xFFFF) / da; +- db = (db * 0xFFFF) / da; +- } ++ // Handle subnormal numbers. ++ if ((man2 >> 52) == 0) { ++ exp2 = f64_bias; ++ } + +- // Combine components. +- return (db << 0) | (dg << 16) | (dr << 32) | (da << 48); +-} ++ // Pack the bits and return. ++ uint64_t exp2_bits = ++ (uint64_t)((exp2 - f64_bias) & 0x07FF); // (1 << 11) - 1. ++ uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) | // (1 << 52) - 1. ++ (exp2_bits << 52) | // ++ (h->negative ? 0x8000000000000000 : 0); // (1 << 63). + +-static inline uint32_t // +-wuffs_base__composite_premul_nonpremul_u32_axxx(uint32_t dst_premul, +- uint32_t src_nonpremul) { +- // Extract 16-bit color components. +- uint32_t da = 0x101 * (0xFF & (dst_premul >> 24)); +- uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16)); +- uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8)); +- uint32_t db = 0x101 * (0xFF & (dst_premul >> 0)); +- uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24)); +- uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16)); +- uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8)); +- uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0)); ++ wuffs_base__result_f64 ret; ++ ret.status.repr = NULL; ++ ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits); ++ return ret; ++ } while (0); + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++zero: ++ do { ++ uint64_t bits = h->negative ? 0x8000000000000000 : 0; + +- // Composite src (nonpremul) over dst (premul). +- da = sa + ((da * ia) / 0xFFFF); +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ wuffs_base__result_f64 ret; ++ ret.status.repr = NULL; ++ ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits); ++ return ret; ++ } while (0); + +- // Convert from 16-bit color to 8-bit color. +- da >>= 8; +- dr >>= 8; +- dg >>= 8; +- db >>= 8; ++infinity: ++ do { ++ if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) { ++ wuffs_base__result_f64 ret; ++ ret.status.repr = wuffs_base__error__bad_argument; ++ ret.value = 0; ++ return ret; ++ } + +- // Combine components. +- return (db << 0) | (dg << 8) | (dr << 16) | (da << 24); +-} ++ uint64_t bits = h->negative ? 0xFFF0000000000000 : 0x7FF0000000000000; + +-static inline uint64_t // +-wuffs_base__composite_premul_nonpremul_u64_axxx(uint64_t dst_premul, +- uint64_t src_nonpremul) { +- // Extract components. +- uint64_t da = 0xFFFF & (dst_premul >> 48); +- uint64_t dr = 0xFFFF & (dst_premul >> 32); +- uint64_t dg = 0xFFFF & (dst_premul >> 16); +- uint64_t db = 0xFFFF & (dst_premul >> 0); +- uint64_t sa = 0xFFFF & (src_nonpremul >> 48); +- uint64_t sr = 0xFFFF & (src_nonpremul >> 32); +- uint64_t sg = 0xFFFF & (src_nonpremul >> 16); +- uint64_t sb = 0xFFFF & (src_nonpremul >> 0); +- +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint64_t ia = 0xFFFF - sa; +- +- // Composite src (nonpremul) over dst (premul). +- da = sa + ((da * ia) / 0xFFFF); +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; +- +- // Combine components. +- return (db << 0) | (dg << 16) | (dr << 32) | (da << 48); ++ wuffs_base__result_f64 ret; ++ ret.status.repr = NULL; ++ ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits); ++ return ret; ++ } while (0); + } + +-static inline uint32_t // +-wuffs_base__composite_premul_premul_u32_axxx(uint32_t dst_premul, +- uint32_t src_premul) { +- // Extract 16-bit color components. +- uint32_t da = 0x101 * (0xFF & (dst_premul >> 24)); +- uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16)); +- uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8)); +- uint32_t db = 0x101 * (0xFF & (dst_premul >> 0)); +- uint32_t sa = 0x101 * (0xFF & (src_premul >> 24)); +- uint32_t sr = 0x101 * (0xFF & (src_premul >> 16)); +- uint32_t sg = 0x101 * (0xFF & (src_premul >> 8)); +- uint32_t sb = 0x101 * (0xFF & (src_premul >> 0)); +- +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; +- +- // Composite src (premul) over dst (premul). +- da = sa + ((da * ia) / 0xFFFF); +- dr = sr + ((dr * ia) / 0xFFFF); +- dg = sg + ((dg * ia) / 0xFFFF); +- db = sb + ((db * ia) / 0xFFFF); +- +- // Convert from 16-bit color to 8-bit color. +- da >>= 8; +- dr >>= 8; +- dg >>= 8; +- db >>= 8; +- +- // Combine components. +- return (db << 0) | (dg << 8) | (dr << 16) | (da << 24); ++static inline bool // ++wuffs_private_impl__is_decimal_digit(uint8_t c) { ++ return ('0' <= c) && (c <= '9'); + } + +-// -------- ++WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 // ++wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options) { ++ // In practice, almost all "dd.ddddE±xxx" numbers can be represented ++ // losslessly by a uint64_t mantissa "dddddd" and an int32_t base-10 ++ // exponent, adjusting "xxx" for the position (if present) of the decimal ++ // separator '.' or ','. ++ // ++ // This (u64 man, i32 exp10) data structure is superficially similar to the ++ // "Do It Yourself Floating Point" type from Loitsch (†), but the exponent ++ // here is base-10, not base-2. ++ // ++ // If s's number fits in a (man, exp10), parse that pair with the ++ // Eisel-Lemire algorithm. If not, or if Eisel-Lemire fails, parsing s with ++ // the fallback algorithm is slower but comprehensive. ++ // ++ // † "Printing Floating-Point Numbers Quickly and Accurately with Integers" ++ // (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf). ++ // Florian Loitsch is also the primary contributor to ++ // https://github.com/google/double-conversion ++ do { ++ // Calculating that (man, exp10) pair needs to stay within s's bounds. ++ // Provided that s isn't extremely long, work on a NUL-terminated copy of ++ // s's contents. The NUL byte isn't a valid part of "±dd.ddddE±xxx". ++ // ++ // As the pointer p walks the contents, it's faster to repeatedly check "is ++ // *p a valid digit" than "is p within bounds and *p a valid digit". ++ if (s.len >= 256) { ++ goto fallback; ++ } ++ uint8_t z[256]; ++ memcpy(&z[0], s.ptr, s.len); ++ z[s.len] = 0; ++ const uint8_t* p = &z[0]; + +-static uint64_t // +-wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888(uint8_t* dst_ptr, +- size_t dst_len, +- const uint8_t* src_ptr, +- size_t src_len, +- bool nonpremul) { +- size_t len = (dst_len < src_len ? dst_len : src_len) / 4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; ++ // Look for a leading minus sign. Technically, we could also look for an ++ // optional plus sign, but the "script/process-json-numbers.c with -p" ++ // benchmark is noticably slower if we do. It's optional and, in practice, ++ // usually absent. Let the fallback catch it. ++ bool negative = (*p == '-'); ++ if (negative) { ++ p++; ++ } + +- size_t n = len; +- while (n--) { +- uint32_t argb = wuffs_base__peek_u32le__no_bounds_check(s); +- if (nonpremul) { +- argb = +- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(argb); ++ // After walking "dd.dddd", comparing p later with p now will produce the ++ // number of "d"s and "."s. ++ const uint8_t* const start_of_digits_ptr = p; ++ ++ // Walk the "d"s before a '.', 'E', NUL byte, etc. If it starts with '0', ++ // it must be a single '0'. If it starts with a non-zero decimal digit, it ++ // can be a sequence of decimal digits. ++ // ++ // Update the man variable during the walk. It's OK if man overflows now. ++ // We'll detect that later. ++ uint64_t man; ++ if (*p == '0') { ++ man = 0; ++ p++; ++ if (wuffs_private_impl__is_decimal_digit(*p)) { ++ goto fallback; ++ } ++ } else if (wuffs_private_impl__is_decimal_digit(*p)) { ++ man = ((uint8_t)(*p - '0')); ++ p++; ++ for (; wuffs_private_impl__is_decimal_digit(*p); p++) { ++ man = (10 * man) + ((uint8_t)(*p - '0')); ++ } ++ } else { ++ goto fallback; + } +- uint32_t b5 = 0x1F & (argb >> (8 - 5)); +- uint32_t g6 = 0x3F & (argb >> (16 - 6)); +- uint32_t r5 = 0x1F & (argb >> (24 - 5)); +- uint32_t alpha = argb & 0xFF000000; +- wuffs_base__poke_u32le__no_bounds_check( +- d, alpha | (r5 << 11) | (g6 << 5) | (b5 << 0)); +- s += 4; +- d += 4; +- } +- return len; +-} + +-// -------- ++ // Walk the "d"s after the optional decimal separator ('.' or ','), ++ // updating the man and exp10 variables. ++ int32_t exp10 = 0; ++ if (*p == ++ ((options & WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) ++ ? ',' ++ : '.')) { ++ p++; ++ const uint8_t* first_after_separator_ptr = p; ++ if (!wuffs_private_impl__is_decimal_digit(*p)) { ++ goto fallback; ++ } ++ man = (10 * man) + ((uint8_t)(*p - '0')); ++ p++; ++ for (; wuffs_private_impl__is_decimal_digit(*p); p++) { ++ man = (10 * man) + ((uint8_t)(*p - '0')); ++ } ++ exp10 = ((int32_t)(first_after_separator_ptr - p)); ++ } + +-static uint64_t // +-wuffs_base__pixel_swizzler__swap_rgb_bgr(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t len = (dst_len < src_len ? dst_len : src_len) / 3; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; ++ // Count the number of digits: ++ // - for an input of "314159", digit_count is 6. ++ // - for an input of "3.14159", digit_count is 7. ++ // ++ // This is off-by-one if there is a decimal separator. That's OK for now. ++ // We'll correct for that later. The "script/process-json-numbers.c with ++ // -p" benchmark is noticably slower if we try to correct for that now. ++ uint32_t digit_count = (uint32_t)(p - start_of_digits_ptr); + +- size_t n = len; +- while (n--) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- d[0] = s2; +- d[1] = s1; +- d[2] = s0; +- s += 3; +- d += 3; +- } +- return len; +-} ++ // Update exp10 for the optional exponent, starting with 'E' or 'e'. ++ if ((*p | 0x20) == 'e') { ++ p++; ++ int32_t exp_sign = +1; ++ if (*p == '-') { ++ p++; ++ exp_sign = -1; ++ } else if (*p == '+') { ++ p++; ++ } ++ if (!wuffs_private_impl__is_decimal_digit(*p)) { ++ goto fallback; ++ } ++ int32_t exp_num = ((uint8_t)(*p - '0')); ++ p++; ++ // The rest of the exp_num walking has a peculiar control flow but, once ++ // again, the "script/process-json-numbers.c with -p" benchmark is ++ // sensitive to alternative formulations. ++ if (wuffs_private_impl__is_decimal_digit(*p)) { ++ exp_num = (10 * exp_num) + ((uint8_t)(*p - '0')); ++ p++; ++ } ++ if (wuffs_private_impl__is_decimal_digit(*p)) { ++ exp_num = (10 * exp_num) + ((uint8_t)(*p - '0')); ++ p++; ++ } ++ while (wuffs_private_impl__is_decimal_digit(*p)) { ++ if (exp_num > 0x1000000) { ++ goto fallback; ++ } ++ exp_num = (10 * exp_num) + ((uint8_t)(*p - '0')); ++ p++; ++ } ++ exp10 += exp_sign * exp_num; ++ } + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") +-static uint64_t // +-wuffs_base__pixel_swizzler__swap_rgbx_bgrx__x86_sse42(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t len = (dst_len < src_len ? dst_len : src_len) / 4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ // The Wuffs API is that the original slice has no trailing data. It also ++ // allows underscores, which we don't catch here but the fallback should. ++ if (p != &z[s.len]) { ++ goto fallback; ++ } + +- __m128i shuffle = _mm_set_epi8(+0x0F, +0x0C, +0x0D, +0x0E, // +- +0x0B, +0x08, +0x09, +0x0A, // +- +0x07, +0x04, +0x05, +0x06, // +- +0x03, +0x00, +0x01, +0x02); ++ // Check that the uint64_t typed man variable has not overflowed, based on ++ // digit_count. ++ // ++ // For reference: ++ // - (1 << 63) is 9223372036854775808, which has 19 decimal digits. ++ // - (1 << 64) is 18446744073709551616, which has 20 decimal digits. ++ // - 19 nines, 9999999999999999999, is 0x8AC7230489E7FFFF, which has 64 ++ // bits and 16 hexadecimal digits. ++ // - 20 nines, 99999999999999999999, is 0x56BC75E2D630FFFFF, which has 67 ++ // bits and 17 hexadecimal digits. ++ if (digit_count > 19) { ++ // Even if we have more than 19 pseudo-digits, it's not yet definitely an ++ // overflow. Recall that digit_count might be off-by-one (too large) if ++ // there's a decimal separator. It will also over-report the number of ++ // meaningful digits if the input looks something like "0.000dddExxx". ++ // ++ // We adjust by the number of leading '0's and '.'s and re-compare to 19. ++ // Once again, technically, we could skip ','s too, but that perturbs the ++ // "script/process-json-numbers.c with -p" benchmark. ++ const uint8_t* q = start_of_digits_ptr; ++ for (; (*q == '0') || (*q == '.'); q++) { ++ } ++ digit_count -= (uint32_t)(q - start_of_digits_ptr); ++ if (digit_count > 19) { ++ goto fallback; ++ } ++ } + +- while (n >= 4) { +- __m128i x; +- x = _mm_lddqu_si128((const __m128i*)(const void*)s); +- x = _mm_shuffle_epi8(x, shuffle); +- _mm_storeu_si128((__m128i*)(void*)d, x); ++ // The wuffs_private_impl__parse_number_f64_eisel_lemire preconditions ++ // include that exp10 is in the range [-307 ..= 288]. ++ if ((exp10 < -307) || (288 < exp10)) { ++ goto fallback; ++ } + +- s += 4 * 4; +- d += 4 * 4; +- n -= 4; +- } ++ // If both man and (10 ** exp10) are exactly representable by a double, we ++ // don't need to run the Eisel-Lemire algorithm. ++ if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) { ++ double d = (double)man; ++ if (exp10 >= 0) { ++ d *= wuffs_private_impl__f64_powers_of_10[+exp10]; ++ } else { ++ d /= wuffs_private_impl__f64_powers_of_10[-exp10]; ++ } ++ wuffs_base__result_f64 ret; ++ ret.status.repr = NULL; ++ ret.value = negative ? -d : +d; ++ return ret; ++ } + +- while (n--) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- uint8_t s3 = s[3]; +- d[0] = s2; +- d[1] = s1; +- d[2] = s0; +- d[3] = s3; +- s += 4; +- d += 4; +- } +- return len; +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 ++ // The wuffs_private_impl__parse_number_f64_eisel_lemire preconditions ++ // include that man is non-zero. Parsing "0" should be caught by the "If ++ // both man and (10 ** exp10)" above, but "0e99" might not. ++ if (man == 0) { ++ goto fallback; ++ } + +-static uint64_t // +-wuffs_base__pixel_swizzler__swap_rgbx_bgrx(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t len = (dst_len < src_len ? dst_len : src_len) / 4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; ++ // Our man and exp10 are in range. Run the Eisel-Lemire algorithm. ++ int64_t r = wuffs_private_impl__parse_number_f64_eisel_lemire(man, exp10); ++ if (r < 0) { ++ goto fallback; ++ } ++ wuffs_base__result_f64 ret; ++ ret.status.repr = NULL; ++ ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64( ++ ((uint64_t)r) | (((uint64_t)negative) << 63)); ++ return ret; ++ } while (0); + +- size_t n = len; +- while (n--) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- uint8_t s3 = s[3]; +- d[0] = s2; +- d[1] = s1; +- d[2] = s0; +- d[3] = s3; +- s += 4; +- d += 4; +- } +- return len; ++fallback: ++ do { ++ wuffs_private_impl__high_prec_dec h; ++ wuffs_base__status status = ++ wuffs_private_impl__high_prec_dec__parse(&h, s, options); ++ if (status.repr) { ++ return wuffs_private_impl__parse_number_f64_special(s, options); ++ } ++ return wuffs_private_impl__high_prec_dec__to_f64(&h, options); ++ } while (0); + } + + // -------- + +-static uint64_t // +-wuffs_base__pixel_swizzler__copy_1_1(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t len = (dst_len < src_len) ? dst_len : src_len; +- if (len > 0) { +- memmove(dst_ptr, src_ptr, len); ++static inline size_t // ++wuffs_private_impl__render_inf(wuffs_base__slice_u8 dst, ++ bool neg, ++ uint32_t options) { ++ if (neg) { ++ if (dst.len < 4) { ++ return 0; ++ } ++ wuffs_base__poke_u32le__no_bounds_check(dst.ptr, 0x666E492D); // '-Inf'le. ++ return 4; + } +- return len; +-} + +-static uint64_t // +-wuffs_base__pixel_swizzler__copy_2_2(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len2 = src_len / 2; +- size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; +- if (len > 0) { +- memmove(dst_ptr, src_ptr, len * 2); ++ if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) { ++ if (dst.len < 4) { ++ return 0; ++ } ++ wuffs_base__poke_u32le__no_bounds_check(dst.ptr, 0x666E492B); // '+Inf'le. ++ return 4; + } +- return len; +-} + +-static uint64_t // +-wuffs_base__pixel_swizzler__copy_3_3(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len3 = src_len / 3; +- size_t len = (dst_len3 < src_len3) ? dst_len3 : src_len3; +- if (len > 0) { +- memmove(dst_ptr, src_ptr, len * 3); ++ if (dst.len < 3) { ++ return 0; + } +- return len; ++ wuffs_base__poke_u24le__no_bounds_check(dst.ptr, 0x666E49); // 'Inf'le. ++ return 3; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__copy_4_4(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; +- if (len > 0) { +- memmove(dst_ptr, src_ptr, len * 4); ++static inline size_t // ++wuffs_private_impl__render_nan(wuffs_base__slice_u8 dst) { ++ if (dst.len < 3) { ++ return 0; + } +- return len; ++ wuffs_base__poke_u24le__no_bounds_check(dst.ptr, 0x4E614E); // 'NaN'le. ++ return 3; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__copy_8_8(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len8 < src_len8) ? dst_len8 : src_len8; +- if (len > 0) { +- memmove(dst_ptr, src_ptr, len * 8); ++static size_t // ++wuffs_private_impl__high_prec_dec__render_exponent_absent( ++ wuffs_base__slice_u8 dst, ++ wuffs_private_impl__high_prec_dec* h, ++ uint32_t precision, ++ uint32_t options) { ++ size_t n = (h->negative || ++ (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN)) ++ ? 1 ++ : 0; ++ if (h->decimal_point <= 0) { ++ n += 1; ++ } else { ++ n += (size_t)(h->decimal_point); ++ } ++ if (precision > 0) { ++ n += precision + 1; // +1 for the '.'. + } +- return len; +-} + +-// -------- ++ // Don't modify dst if the formatted number won't fit. ++ if (n > dst.len) { ++ return 0; ++ } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__bgr(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len3 = src_len / 3; +- size_t len = (dst_len2 < src_len3) ? dst_len2 : src_len3; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ // Align-left or align-right. ++ uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT) ++ ? &dst.ptr[dst.len - n] ++ : &dst.ptr[0]; + +- // TODO: unroll. ++ // Leading "±". ++ if (h->negative) { ++ *ptr++ = '-'; ++ } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) { ++ *ptr++ = '+'; ++ } + +- while (n >= 1) { +- uint32_t b5 = s[0] >> 3; +- uint32_t g6 = s[1] >> 2; +- uint32_t r5 = s[2] >> 3; +- uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); ++ // Integral digits. ++ if (h->decimal_point <= 0) { ++ *ptr++ = '0'; ++ } else { ++ uint32_t m = ++ wuffs_base__u32__min(h->num_digits, (uint32_t)(h->decimal_point)); ++ uint32_t i = 0; ++ for (; i < m; i++) { ++ *ptr++ = (uint8_t)('0' | h->digits[i]); ++ } ++ for (; i < (uint32_t)(h->decimal_point); i++) { ++ *ptr++ = '0'; ++ } ++ } + +- s += 1 * 3; +- d += 1 * 2; +- n -= 1; ++ // Separator and then fractional digits. ++ if (precision > 0) { ++ *ptr++ = ++ (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) ++ ? ',' ++ : '.'; ++ uint32_t i = 0; ++ for (; i < precision; i++) { ++ uint32_t j = ((uint32_t)(h->decimal_point)) + i; ++ *ptr++ = (uint8_t)('0' | ((j < h->num_digits) ? h->digits[j] : 0)); ++ } + } + +- return len; ++ return n; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__bgrx(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; +- +- // TODO: unroll. ++static size_t // ++wuffs_private_impl__high_prec_dec__render_exponent_present( ++ wuffs_base__slice_u8 dst, ++ wuffs_private_impl__high_prec_dec* h, ++ uint32_t precision, ++ uint32_t options) { ++ int32_t exp = 0; ++ if (h->num_digits > 0) { ++ exp = h->decimal_point - 1; ++ } ++ bool negative_exp = exp < 0; ++ if (negative_exp) { ++ exp = -exp; ++ } + +- while (n >= 1) { +- uint32_t b5 = s[0] >> 3; +- uint32_t g6 = s[1] >> 2; +- uint32_t r5 = s[2] >> 3; +- uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); ++ size_t n = (h->negative || ++ (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN)) ++ ? 4 ++ : 3; // Mininum 3 bytes: first digit and then "e±". ++ if (precision > 0) { ++ n += precision + 1; // +1 for the '.'. ++ } ++ n += (exp < 100) ? 2 : 3; + +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; ++ // Don't modify dst if the formatted number won't fit. ++ if (n > dst.len) { ++ return 0; + } + +- return len; +-} ++ // Align-left or align-right. ++ uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT) ++ ? &dst.ptr[dst.len - n] ++ : &dst.ptr[0]; + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ // Leading "±". ++ if (h->negative) { ++ *ptr++ = '-'; ++ } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) { ++ *ptr++ = '+'; ++ } + +- // TODO: unroll. ++ // Integral digit. ++ if (h->num_digits > 0) { ++ *ptr++ = (uint8_t)('0' | h->digits[0]); ++ } else { ++ *ptr++ = '0'; ++ } + +- while (n >= 1) { +- wuffs_base__poke_u16le__no_bounds_check( +- d + (0 * 2), +- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( +- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))))); ++ // Separator and then fractional digits. ++ if (precision > 0) { ++ *ptr++ = ++ (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA) ++ ? ',' ++ : '.'; ++ uint32_t i = 1; ++ uint32_t j = wuffs_base__u32__min(h->num_digits, precision + 1); ++ for (; i < j; i++) { ++ *ptr++ = (uint8_t)('0' | h->digits[i]); ++ } ++ for (; i <= precision; i++) { ++ *ptr++ = '0'; ++ } ++ } + +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; ++ // Exponent: "e±" and then 2 or 3 digits. ++ *ptr++ = 'e'; ++ *ptr++ = negative_exp ? '-' : '+'; ++ if (exp < 10) { ++ *ptr++ = '0'; ++ *ptr++ = (uint8_t)('0' | exp); ++ } else if (exp < 100) { ++ *ptr++ = (uint8_t)('0' | (exp / 10)); ++ *ptr++ = (uint8_t)('0' | (exp % 10)); ++ } else { ++ int32_t e = exp / 100; ++ exp -= e * 100; ++ *ptr++ = (uint8_t)('0' | e); ++ *ptr++ = (uint8_t)('0' | (exp / 10)); ++ *ptr++ = (uint8_t)('0' | (exp % 10)); + } + +- return len; ++ return n; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len2 < src_len8) ? dst_len2 : src_len8; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; +- +- // TODO: unroll. ++WUFFS_BASE__MAYBE_STATIC size_t // ++wuffs_base__render_number_f64(wuffs_base__slice_u8 dst, ++ double x, ++ uint32_t precision, ++ uint32_t options) { ++ // Decompose x (64 bits) into negativity (1 bit), base-2 exponent (11 bits ++ // with a -1023 bias) and mantissa (52 bits). ++ uint64_t bits = wuffs_base__ieee_754_bit_representation__from_f64_to_u64(x); ++ bool neg = (bits >> 63) != 0; ++ int32_t exp2 = ((int32_t)(bits >> 52)) & 0x7FF; ++ uint64_t man = bits & 0x000FFFFFFFFFFFFFul; + +- while (n >= 1) { +- wuffs_base__poke_u16le__no_bounds_check( +- d + (0 * 2), +- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( +- wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))))); ++ // Apply the exponent bias and set the implicit top bit of the mantissa, ++ // unless x is subnormal. Also take care of Inf and NaN. ++ if (exp2 == 0x7FF) { ++ if (man != 0) { ++ return wuffs_private_impl__render_nan(dst); ++ } ++ return wuffs_private_impl__render_inf(dst, neg, options); ++ } else if (exp2 == 0) { ++ exp2 = -1022; ++ } else { ++ exp2 -= 1023; ++ man |= 0x0010000000000000ul; ++ } + +- s += 1 * 8; +- d += 1 * 2; +- n -= 1; ++ // Ensure that precision isn't too large. ++ if (precision > 4095) { ++ precision = 4095; + } + +- return len; +-} ++ // Convert from the (neg, exp2, man) tuple to an HPD. ++ wuffs_private_impl__high_prec_dec h; ++ wuffs_private_impl__high_prec_dec__assign(&h, man, neg); ++ if (h.num_digits > 0) { ++ wuffs_private_impl__high_prec_dec__lshift(&h, ++ exp2 - 52); // 52 mantissa bits. ++ } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ // Handle the "%e" and "%f" formats. ++ switch (options & (WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT | ++ WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT)) { ++ case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT: // The "%"f" format. ++ if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) { ++ wuffs_private_impl__high_prec_dec__round_just_enough(&h, exp2, man); ++ int32_t p = ((int32_t)(h.num_digits)) - h.decimal_point; ++ precision = ((uint32_t)(wuffs_base__i32__max(0, p))); ++ } else { ++ wuffs_private_impl__high_prec_dec__round_nearest( ++ &h, ((int32_t)precision) + h.decimal_point); ++ } ++ return wuffs_private_impl__high_prec_dec__render_exponent_absent( ++ dst, &h, precision, options); + +- // TODO: unroll. ++ case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT: // The "%e" format. ++ if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) { ++ wuffs_private_impl__high_prec_dec__round_just_enough(&h, exp2, man); ++ precision = (h.num_digits > 0) ? (h.num_digits - 1) : 0; ++ } else { ++ wuffs_private_impl__high_prec_dec__round_nearest( ++ &h, ((int32_t)precision) + 1); ++ } ++ return wuffs_private_impl__high_prec_dec__render_exponent_present( ++ dst, &h, precision, options); ++ } + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t sa = 0x101 * ((uint32_t)s[3]); +- uint32_t sr = 0x101 * ((uint32_t)s[2]); +- uint32_t sg = 0x101 * ((uint32_t)s[1]); +- uint32_t sb = 0x101 * ((uint32_t)s[0]); ++ // We have the "%g" format and so precision means the number of significant ++ // digits, not the number of digits after the decimal separator. Perform ++ // rounding and determine whether to use "%e" or "%f". ++ int32_t e_threshold = 0; ++ if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) { ++ wuffs_private_impl__high_prec_dec__round_just_enough(&h, exp2, man); ++ precision = h.num_digits; ++ e_threshold = 6; ++ } else { ++ if (precision == 0) { ++ precision = 1; ++ } ++ wuffs_private_impl__high_prec_dec__round_nearest(&h, ((int32_t)precision)); ++ e_threshold = ((int32_t)precision); ++ int32_t nd = ((int32_t)(h.num_digits)); ++ if ((e_threshold > nd) && (nd >= h.decimal_point)) { ++ e_threshold = nd; ++ } ++ } + +- // Convert from 565 color to 16-bit color. +- uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); +- uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); +- uint32_t dr = (0x8421 * old_r5) >> 4; +- uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); +- uint32_t dg = (0x1041 * old_g6) >> 2; +- uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); +- uint32_t db = (0x8421 * old_b5) >> 4; ++ // Use the "%e" format if the exponent is large. ++ int32_t e = h.decimal_point - 1; ++ if ((e < -4) || (e_threshold <= e)) { ++ uint32_t p = wuffs_base__u32__min(precision, h.num_digits); ++ return wuffs_private_impl__high_prec_dec__render_exponent_present( ++ dst, &h, (p > 0) ? (p - 1) : 0, options); ++ } + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ // Use the "%f" format otherwise. ++ int32_t p = ((int32_t)precision); ++ if (p > h.decimal_point) { ++ p = ((int32_t)(h.num_digits)); ++ } ++ precision = ((uint32_t)(wuffs_base__i32__max(0, p - h.decimal_point))); ++ return wuffs_private_impl__high_prec_dec__render_exponent_absent( ++ dst, &h, precision, options); ++} + +- // Composite src (nonpremul) over dst (premul). +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++#endif // !defined(WUFFS_CONFIG__MODULES) || ++ // defined(WUFFS_CONFIG__MODULE__BASE) || ++ // defined(WUFFS_CONFIG__MODULE__BASE__FLOATCONV) + +- // Convert from 16-bit color to 565 color and combine the components. +- uint32_t new_r5 = 0x1F & (dr >> 11); +- uint32_t new_g6 = 0x3F & (dg >> 10); +- uint32_t new_b5 = 0x1F & (db >> 11); +- uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ ++ defined(WUFFS_CONFIG__MODULE__BASE__INTCONV) + +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; +- } ++// ---------------- Integer + +- return len; +-} ++// wuffs_base__parse_number__foo_digits entries are 0x00 for invalid digits, ++// and (0x80 | v) for valid digits, where v is the 4 bit value. + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len2 < src_len8) ? dst_len2 : src_len8; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++static const uint8_t wuffs_base__parse_number__decimal_digits[256] = { ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F. ++ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // 0x30 ..= 0x37. '0'-'7'. ++ 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. '8'-'9'. + +- // TODO: unroll. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 ..= 0x47. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 ..= 0x67. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F. + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6)); +- uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4)); +- uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2)); +- uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0)); ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 ..= 0x87. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 ..= 0x8F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 ..= 0x97. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 ..= 0x9F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 ..= 0xA7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 ..= 0xAF. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 ..= 0xB7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 ..= 0xBF. + +- // Convert from 565 color to 16-bit color. +- uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); +- uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); +- uint32_t dr = (0x8421 * old_r5) >> 4; +- uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); +- uint32_t dg = (0x1041 * old_g6) >> 2; +- uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); +- uint32_t db = (0x8421 * old_b5) >> 4; ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 ..= 0xC7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 ..= 0xCF. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 ..= 0xD7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 ..= 0xDF. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 ..= 0xE7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 ..= 0xEF. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 ..= 0xF7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF8 ..= 0xFF. ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++}; + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++static const uint8_t wuffs_base__parse_number__hexadecimal_digits[256] = { ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F. ++ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // 0x30 ..= 0x37. '0'-'7'. ++ 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. '8'-'9'. + +- // Composite src (nonpremul) over dst (premul). +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00, // 0x40 ..= 0x47. 'A'-'F'. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F. ++ 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00, // 0x60 ..= 0x67. 'a'-'f'. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F. + +- // Convert from 16-bit color to 565 color and combine the components. +- uint32_t new_r5 = 0x1F & (dr >> 11); +- uint32_t new_g6 = 0x3F & (dg >> 10); +- uint32_t new_b5 = 0x1F & (db >> 11); +- uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 ..= 0x87. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 ..= 0x8F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 ..= 0x97. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 ..= 0x9F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 ..= 0xA7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 ..= 0xAF. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 ..= 0xB7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 ..= 0xBF. + +- s += 1 * 8; +- d += 1 * 2; +- n -= 1; +- } ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 ..= 0xC7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 ..= 0xCF. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 ..= 0xD7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 ..= 0xDF. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 ..= 0xE7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 ..= 0xEF. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 ..= 0xF7. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF8 ..= 0xFF. ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++}; + +- return len; +-} ++static const uint8_t wuffs_private_impl__encode_base16[16] = { ++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 0x00 ..= 0x07. ++ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, // 0x08 ..= 0x0F. ++}; + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++// -------- + +- // TODO: unroll. ++WUFFS_BASE__MAYBE_STATIC wuffs_base__result_i64 // ++wuffs_base__parse_number_i64(wuffs_base__slice_u8 s, uint32_t options) { ++ uint8_t* p = s.ptr; ++ uint8_t* q = s.ptr + s.len; + +- while (n >= 1) { +- wuffs_base__poke_u16le__no_bounds_check( +- d + (0 * 2), wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { ++ for (; (p < q) && (*p == '_'); p++) { ++ } ++ } + +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; ++ bool negative = false; ++ if (p >= q) { ++ goto fail_bad_argument; ++ } else if (*p == '-') { ++ p++; ++ negative = true; ++ } else if (*p == '+') { ++ p++; + } + +- return len; +-} ++ do { ++ wuffs_base__result_u64 r = wuffs_base__parse_number_u64( ++ wuffs_base__make_slice_u8(p, (size_t)(q - p)), options); ++ if (r.status.repr != NULL) { ++ wuffs_base__result_i64 ret; ++ ret.status.repr = r.status.repr; ++ ret.value = 0; ++ return ret; ++ } else if (negative) { ++ if (r.value < 0x8000000000000000) { ++ wuffs_base__result_i64 ret; ++ ret.status.repr = NULL; ++ ret.value = -(int64_t)(r.value); ++ return ret; ++ } else if (r.value == 0x8000000000000000) { ++ wuffs_base__result_i64 ret; ++ ret.status.repr = NULL; ++ ret.value = INT64_MIN; ++ return ret; ++ } ++ goto fail_out_of_bounds; ++ } else if (r.value > 0x7FFFFFFFFFFFFFFF) { ++ goto fail_out_of_bounds; ++ } else { ++ wuffs_base__result_i64 ret; ++ ret.status.repr = NULL; ++ ret.value = +(int64_t)(r.value); ++ return ret; ++ } ++ } while (0); + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++fail_bad_argument: ++ do { ++ wuffs_base__result_i64 ret; ++ ret.status.repr = wuffs_base__error__bad_argument; ++ ret.value = 0; ++ return ret; ++ } while (0); + +- // TODO: unroll. ++fail_out_of_bounds: ++ do { ++ wuffs_base__result_i64 ret; ++ ret.status.repr = wuffs_base__error__out_of_bounds; ++ ret.value = 0; ++ return ret; ++ } while (0); ++} + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t sa = 0x101 * ((uint32_t)s[3]); +- uint32_t sr = 0x101 * ((uint32_t)s[2]); +- uint32_t sg = 0x101 * ((uint32_t)s[1]); +- uint32_t sb = 0x101 * ((uint32_t)s[0]); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__result_u64 // ++wuffs_base__parse_number_u64(wuffs_base__slice_u8 s, uint32_t options) { ++ uint8_t* p = s.ptr; ++ uint8_t* q = s.ptr + s.len; + +- // Convert from 565 color to 16-bit color. +- uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); +- uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); +- uint32_t dr = (0x8421 * old_r5) >> 4; +- uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); +- uint32_t dg = (0x1041 * old_g6) >> 2; +- uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); +- uint32_t db = (0x8421 * old_b5) >> 4; +- +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; +- +- // Composite src (premul) over dst (premul). +- dr = sr + ((dr * ia) / 0xFFFF); +- dg = sg + ((dg * ia) / 0xFFFF); +- db = sb + ((db * ia) / 0xFFFF); +- +- // Convert from 16-bit color to 565 color and combine the components. +- uint32_t new_r5 = 0x1F & (dr >> 11); +- uint32_t new_g6 = 0x3F & (dg >> 10); +- uint32_t new_b5 = 0x1F & (db >> 11); +- uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); +- +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { ++ for (; (p < q) && (*p == '_'); p++) { ++ } + } + +- return len; +-} ++ if (p >= q) { ++ goto fail_bad_argument; + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__rgb(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len3 = src_len / 3; +- size_t len = (dst_len2 < src_len3) ? dst_len2 : src_len3; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ } else if (*p == '0') { ++ p++; ++ if (p >= q) { ++ goto ok_zero; ++ } ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { ++ if (*p == '_') { ++ p++; ++ for (; p < q; p++) { ++ if (*p != '_') { ++ if (options & ++ WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES) { ++ goto decimal; ++ } ++ goto fail_bad_argument; ++ } ++ } ++ goto ok_zero; ++ } ++ } + +- // TODO: unroll. ++ if ((*p == 'x') || (*p == 'X')) { ++ p++; ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { ++ for (; (p < q) && (*p == '_'); p++) { ++ } ++ } ++ if (p < q) { ++ goto hexadecimal; ++ } + +- while (n >= 1) { +- uint32_t r5 = s[0] >> 3; +- uint32_t g6 = s[1] >> 2; +- uint32_t b5 = s[2] >> 3; +- uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); ++ } else if ((*p == 'd') || (*p == 'D')) { ++ p++; ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) { ++ for (; (p < q) && (*p == '_'); p++) { ++ } ++ } ++ if (p < q) { ++ goto decimal; ++ } ++ } + +- s += 1 * 3; +- d += 1 * 2; +- n -= 1; ++ if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES) { ++ goto decimal; ++ } ++ goto fail_bad_argument; + } + +- return len; +-} ++decimal: ++ do { ++ uint64_t v = wuffs_base__parse_number__decimal_digits[*p++]; ++ if (v == 0) { ++ goto fail_bad_argument; ++ } ++ v &= 0x0F; + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ // UINT64_MAX is 18446744073709551615, which is ((10 * max10) + max1). ++ const uint64_t max10 = 1844674407370955161u; ++ const uint8_t max1 = 5; + +- // TODO: unroll. ++ for (; p < q; p++) { ++ if ((*p == '_') && ++ (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { ++ continue; ++ } ++ uint8_t digit = wuffs_base__parse_number__decimal_digits[*p]; ++ if (digit == 0) { ++ goto fail_bad_argument; ++ } ++ digit &= 0x0F; ++ if ((v > max10) || ((v == max10) && (digit > max1))) { ++ goto fail_out_of_bounds; ++ } ++ v = (10 * v) + ((uint64_t)(digit)); ++ } + +- while (n >= 1) { +- wuffs_base__poke_u16le__no_bounds_check( +- d + (0 * 2), +- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( +- wuffs_base__swap_u32_argb_abgr( +- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))))); ++ wuffs_base__result_u64 ret; ++ ret.status.repr = NULL; ++ ret.value = v; ++ return ret; ++ } while (0); + +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; +- } ++hexadecimal: ++ do { ++ uint64_t v = wuffs_base__parse_number__hexadecimal_digits[*p++]; ++ if (v == 0) { ++ goto fail_bad_argument; ++ } ++ v &= 0x0F; + +- return len; +-} ++ for (; p < q; p++) { ++ if ((*p == '_') && ++ (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) { ++ continue; ++ } ++ uint8_t digit = wuffs_base__parse_number__hexadecimal_digits[*p]; ++ if (digit == 0) { ++ goto fail_bad_argument; ++ } ++ digit &= 0x0F; ++ if ((v >> 60) != 0) { ++ goto fail_out_of_bounds; ++ } ++ v = (v << 4) | ((uint64_t)(digit)); ++ } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ wuffs_base__result_u64 ret; ++ ret.status.repr = NULL; ++ ret.value = v; ++ return ret; ++ } while (0); + +- // TODO: unroll. ++ok_zero: ++ do { ++ wuffs_base__result_u64 ret; ++ ret.status.repr = NULL; ++ ret.value = 0; ++ return ret; ++ } while (0); + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t sa = 0x101 * ((uint32_t)s[3]); +- uint32_t sb = 0x101 * ((uint32_t)s[2]); +- uint32_t sg = 0x101 * ((uint32_t)s[1]); +- uint32_t sr = 0x101 * ((uint32_t)s[0]); ++fail_bad_argument: ++ do { ++ wuffs_base__result_u64 ret; ++ ret.status.repr = wuffs_base__error__bad_argument; ++ ret.value = 0; ++ return ret; ++ } while (0); + +- // Convert from 565 color to 16-bit color. +- uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); +- uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); +- uint32_t dr = (0x8421 * old_r5) >> 4; +- uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); +- uint32_t dg = (0x1041 * old_g6) >> 2; +- uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); +- uint32_t db = (0x8421 * old_b5) >> 4; ++fail_out_of_bounds: ++ do { ++ wuffs_base__result_u64 ret; ++ ret.status.repr = wuffs_base__error__out_of_bounds; ++ ret.value = 0; ++ return ret; ++ } while (0); ++} + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++// -------- + +- // Composite src (nonpremul) over dst (premul). +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++// wuffs_base__render_number__first_hundred contains the decimal encodings of ++// the first one hundred numbers [0 ..= 99]. ++static const uint8_t wuffs_base__render_number__first_hundred[200] = { ++ '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', // ++ '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', // ++ '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', // ++ '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', // ++ '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', // ++ '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', // ++ '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', // ++ '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', // ++ '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', // ++ '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', // ++ '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', // ++ '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', // ++ '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', // ++ '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', // ++ '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', // ++ '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', // ++ '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', // ++ '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', // ++ '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', // ++ '9', '5', '9', '6', '9', '7', '9', '8', '9', '9', // ++}; + +- // Convert from 16-bit color to 565 color and combine the components. +- uint32_t new_r5 = 0x1F & (dr >> 11); +- uint32_t new_g6 = 0x3F & (dg >> 10); +- uint32_t new_b5 = 0x1F & (db >> 11); +- uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); ++static size_t // ++wuffs_private_impl__render_number_u64(wuffs_base__slice_u8 dst, ++ uint64_t x, ++ uint32_t options, ++ bool neg) { ++ uint8_t buf[WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL]; ++ uint8_t* ptr = &buf[0] + sizeof(buf); + +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; ++ while (x >= 100) { ++ size_t index = ((size_t)((x % 100) * 2)); ++ x /= 100; ++ uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0]; ++ uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1]; ++ ptr -= 2; ++ ptr[0] = s0; ++ ptr[1] = s1; + } + +- return len; +-} +- +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ if (x < 10) { ++ ptr -= 1; ++ ptr[0] = (uint8_t)('0' + x); ++ } else { ++ size_t index = ((size_t)(x * 2)); ++ uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0]; ++ uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1]; ++ ptr -= 2; ++ ptr[0] = s0; ++ ptr[1] = s1; ++ } + +- // TODO: unroll. ++ if (neg) { ++ ptr -= 1; ++ ptr[0] = '-'; ++ } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) { ++ ptr -= 1; ++ ptr[0] = '+'; ++ } + +- while (n >= 1) { +- wuffs_base__poke_u16le__no_bounds_check( +- d + (0 * 2), +- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( +- wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))))); ++ size_t n = sizeof(buf) - ((size_t)(ptr - &buf[0])); ++ if (n > dst.len) { ++ return 0; ++ } ++ memcpy(dst.ptr + ((options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT) ++ ? (dst.len - n) ++ : 0), ++ ptr, n); ++ return n; ++} + +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; ++WUFFS_BASE__MAYBE_STATIC size_t // ++wuffs_base__render_number_i64(wuffs_base__slice_u8 dst, ++ int64_t x, ++ uint32_t options) { ++ uint64_t u = (uint64_t)x; ++ bool neg = x < 0; ++ if (neg) { ++ u = 1 + ~u; + } ++ return wuffs_private_impl__render_number_u64(dst, u, options, neg); ++} + +- return len; ++WUFFS_BASE__MAYBE_STATIC size_t // ++wuffs_base__render_number_u64(wuffs_base__slice_u8 dst, ++ uint64_t x, ++ uint32_t options) { ++ return wuffs_private_impl__render_number_u64(dst, x, options, false); + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++// ---------------- Base-16 + +- // TODO: unroll. ++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; ++ 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; ++ } ++ } + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t sa = 0x101 * ((uint32_t)s[3]); +- uint32_t sb = 0x101 * ((uint32_t)s[2]); +- uint32_t sg = 0x101 * ((uint32_t)s[1]); +- uint32_t sr = 0x101 * ((uint32_t)s[0]); ++ uint8_t* d = dst.ptr; ++ uint8_t* s = src.ptr; ++ size_t n = len; + +- // Convert from 565 color to 16-bit color. +- uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); +- uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); +- uint32_t dr = (0x8421 * old_r5) >> 4; +- uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); +- uint32_t dg = (0x1041 * old_g6) >> 2; +- uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); +- uint32_t db = (0x8421 * old_b5) >> 4; ++ while (n--) { ++ *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) | ++ (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F)); ++ d += 1; ++ s += 2; ++ } + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ o.num_dst = len; ++ o.num_src = len * 2; ++ return o; ++} + +- // Composite src (premul) over dst (premul). +- dr = sr + ((dr * ia) / 0xFFFF); +- dg = sg + ((dg * ia) / 0xFFFF); +- db = sb + ((db * ia) / 0xFFFF); ++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; ++ } ++ } + +- // Convert from 16-bit color to 565 color and combine the components. +- uint32_t new_r5 = 0x1F & (dr >> 11); +- uint32_t new_g6 = 0x3F & (dg >> 10); +- uint32_t new_b5 = 0x1F & (db >> 11); +- uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); ++ uint8_t* d = dst.ptr; ++ uint8_t* s = src.ptr; ++ size_t n = len; + +- s += 1 * 4; +- d += 1 * 2; +- n -= 1; ++ while (n--) { ++ *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) | ++ (wuffs_base__parse_number__hexadecimal_digits[s[3]] & 0x0F)); ++ d += 1; ++ s += 4; + } + +- return len; ++ o.num_dst = len; ++ o.num_src = len * 4; ++ return o; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__y(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t len = (dst_len2 < src_len) ? dst_len2 : src_len; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; +- +- // TODO: unroll. ++WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output // ++wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 src, ++ bool src_closed, ++ uint32_t options) { ++ wuffs_base__transform__output o; ++ size_t dst_len2 = dst.len / 2; ++ size_t len; ++ if (dst_len2 < src.len) { ++ len = dst_len2; ++ o.status.repr = wuffs_base__suspension__short_write; ++ } else { ++ len = src.len; ++ if (!src_closed) { ++ o.status.repr = wuffs_base__suspension__short_read; ++ } else { ++ o.status.repr = NULL; ++ } ++ } + +- while (n >= 1) { +- uint32_t y5 = s[0] >> 3; +- uint32_t y6 = s[0] >> 2; +- uint32_t rgb_565 = (y5 << 11) | (y6 << 5) | (y5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); ++ uint8_t* d = dst.ptr; ++ uint8_t* s = src.ptr; ++ size_t n = len; + +- s += 1 * 1; +- d += 1 * 2; +- n -= 1; ++ while (n--) { ++ uint8_t c = *s; ++ d[0] = wuffs_private_impl__encode_base16[c >> 4]; ++ d[1] = wuffs_private_impl__encode_base16[c & 0x0F]; ++ d += 2; ++ s += 1; + } + +- return len; ++ o.num_dst = len * 2; ++ o.num_src = len; ++ return o; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__y_16be(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; +- size_t src_len2 = src_len / 2; +- size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; +- +- // TODO: unroll. ++WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output // ++wuffs_base__base_16__encode4(wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 src, ++ bool src_closed, ++ uint32_t options) { ++ wuffs_base__transform__output o; ++ size_t dst_len4 = dst.len / 4; ++ size_t len; ++ if (dst_len4 < src.len) { ++ len = dst_len4; ++ o.status.repr = wuffs_base__suspension__short_write; ++ } else { ++ len = src.len; ++ if (!src_closed) { ++ o.status.repr = wuffs_base__suspension__short_read; ++ } else { ++ o.status.repr = NULL; ++ } ++ } + +- while (n >= 1) { +- uint32_t y5 = s[0] >> 3; +- uint32_t y6 = s[0] >> 2; +- uint32_t rgb_565 = (y5 << 11) | (y6 << 5) | (y5 << 0); +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); ++ uint8_t* d = dst.ptr; ++ uint8_t* s = src.ptr; ++ size_t n = len; + +- s += 1 * 2; +- d += 1 * 2; +- n -= 1; ++ while (n--) { ++ uint8_t c = *s; ++ d[0] = '\\'; ++ d[1] = 'x'; ++ d[2] = wuffs_private_impl__encode_base16[c >> 4]; ++ d[3] = wuffs_private_impl__encode_base16[c & 0x0F]; ++ d += 4; ++ s += 1; + } + +- return len; ++ o.num_dst = len * 4; ++ o.num_src = len; ++ return o; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__index__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } +- size_t dst_len2 = dst_len / 2; +- size_t len = (dst_len2 < src_len) ? dst_len2 : src_len; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++// ---------------- Base-64 + +- const size_t loop_unroll_count = 4; ++// The two base-64 alphabets, std and url, differ only in the last two codes. ++// - std: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ++// - url: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" + +- while (n >= loop_unroll_count) { +- wuffs_base__poke_u16le__no_bounds_check( +- d + (0 * 2), wuffs_base__peek_u16le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[0] * 4))); +- wuffs_base__poke_u16le__no_bounds_check( +- d + (1 * 2), wuffs_base__peek_u16le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[1] * 4))); +- wuffs_base__poke_u16le__no_bounds_check( +- d + (2 * 2), wuffs_base__peek_u16le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[2] * 4))); +- wuffs_base__poke_u16le__no_bounds_check( +- d + (3 * 2), wuffs_base__peek_u16le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[3] * 4))); ++static const uint8_t wuffs_base__base_64__decode_std[256] = { ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27. ++ 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, // 0x28 ..= 0x2F. ++ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37. ++ 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F. + +- s += loop_unroll_count * 1; +- d += loop_unroll_count * 2; +- n -= loop_unroll_count; +- } ++ 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47. ++ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F. ++ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57. ++ 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x58 ..= 0x5F. ++ 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67. ++ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F. ++ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77. ++ 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F. + +- while (n >= 1) { +- wuffs_base__poke_u16le__no_bounds_check( +- d + (0 * 2), wuffs_base__peek_u16le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[0] * 4))); ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB0 ..= 0xB7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB8 ..= 0xBF. + +- s += 1 * 1; +- d += 1 * 2; +- n -= 1; +- } ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC0 ..= 0xC7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC8 ..= 0xCF. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD0 ..= 0xD7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD8 ..= 0xDF. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE0 ..= 0xE7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE8 ..= 0xEF. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF. ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++}; + +- return len; +-} ++static const uint8_t wuffs_base__base_64__decode_url[256] = { ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, // 0x28 ..= 0x2F. ++ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37. ++ 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F. + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__index_bgra_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } +- size_t dst_len2 = dst_len / 2; +- size_t len = (dst_len2 < src_len) ? dst_len2 : src_len; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47. ++ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F. ++ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57. ++ 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x3F, // 0x58 ..= 0x5F. ++ 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67. ++ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F. ++ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77. ++ 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F. + +- // TODO: unroll. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB0 ..= 0xB7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB8 ..= 0xBF. + +- while (n >= 1) { +- uint32_t d0 = wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( +- wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2))); +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- wuffs_base__poke_u16le__no_bounds_check( +- d + (0 * 2), +- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( +- wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0))); ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC0 ..= 0xC7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC8 ..= 0xCF. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD0 ..= 0xD7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD8 ..= 0xDF. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE0 ..= 0xE7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE8 ..= 0xEF. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF. ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++}; + +- s += 1 * 1; +- d += 1 * 2; +- n -= 1; +- } ++static const uint8_t wuffs_base__base_64__encode_std[64] = { ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // 0x00 ..= 0x07. ++ 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, // 0x08 ..= 0x0F. ++ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, // 0x10 ..= 0x17. ++ 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 0x18 ..= 0x1F. ++ 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, // 0x20 ..= 0x27. ++ 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, // 0x28 ..= 0x2F. ++ 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, // 0x30 ..= 0x37. ++ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F, // 0x38 ..= 0x3F. ++}; + +- return len; +-} ++static const uint8_t wuffs_base__base_64__encode_url[64] = { ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // 0x00 ..= 0x07. ++ 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, // 0x08 ..= 0x0F. ++ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, // 0x10 ..= 0x17. ++ 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 0x18 ..= 0x1F. ++ 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, // 0x20 ..= 0x27. ++ 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, // 0x28 ..= 0x2F. ++ 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, // 0x30 ..= 0x37. ++ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2D, 0x5F, // 0x38 ..= 0x3F. ++}; + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr_565__index_binary_alpha__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } +- size_t dst_len2 = dst_len / 2; +- size_t len = (dst_len2 < src_len) ? dst_len2 : src_len; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++// -------- + +- // TODO: unroll. ++WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output // ++wuffs_base__base_64__decode(wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 src, ++ bool src_closed, ++ uint32_t options) { ++ const uint8_t* alphabet = (options & WUFFS_BASE__BASE_64__URL_ALPHABET) ++ ? wuffs_base__base_64__decode_url ++ : wuffs_base__base_64__decode_std; ++ wuffs_base__transform__output o; ++ uint8_t* d_ptr = dst.ptr; ++ size_t d_len = dst.len; ++ const uint8_t* s_ptr = src.ptr; ++ size_t s_len = src.len; ++ bool pad = false; + +- while (n >= 1) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- if (s0) { +- wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)s0); +- } ++ while (s_len >= 4) { ++ uint32_t s = wuffs_base__peek_u32le__no_bounds_check(s_ptr); ++ uint32_t s0 = alphabet[0xFF & (s >> 0)]; ++ uint32_t s1 = alphabet[0xFF & (s >> 8)]; ++ uint32_t s2 = alphabet[0xFF & (s >> 16)]; ++ uint32_t s3 = alphabet[0xFF & (s >> 24)]; + +- s += 1 * 1; +- d += 1 * 2; +- n -= 1; +- } ++ if (((s0 | s1 | s2 | s3) & 0xC0) != 0) { ++ if (s_len > 4) { ++ o.status.repr = wuffs_base__error__bad_data; ++ goto done; ++ } else if (!src_closed) { ++ o.status.repr = wuffs_base__suspension__short_read; ++ goto done; ++ } else if ((options & WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING) && ++ (s_ptr[3] == '=')) { ++ pad = true; ++ if (s_ptr[2] == '=') { ++ goto src2; ++ } ++ goto src3; ++ } ++ o.status.repr = wuffs_base__error__bad_data; ++ goto done; ++ } + +- return len; +-} ++ if (d_len < 3) { ++ o.status.repr = wuffs_base__suspension__short_write; ++ goto done; ++ } + +-// -------- ++ s_ptr += 4; ++ s_len -= 4; ++ s = (s0 << 18) | (s1 << 12) | (s2 << 6) | (s3 << 0); ++ *d_ptr++ = (uint8_t)(s >> 16); ++ *d_ptr++ = (uint8_t)(s >> 8); ++ *d_ptr++ = (uint8_t)(s >> 0); ++ d_len -= 3; ++ } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__bgr_565(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len2 = src_len / 2; +- size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ if (!src_closed) { ++ o.status.repr = wuffs_base__suspension__short_read; ++ goto done; ++ } + +- // TODO: unroll. ++ if (s_len == 0) { ++ o.status.repr = NULL; ++ goto done; ++ } else if (s_len == 1) { ++ o.status.repr = wuffs_base__error__bad_data; ++ goto done; ++ } else if (s_len == 2) { ++ goto src2; ++ } + +- while (n >= 1) { +- uint32_t s0 = wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( +- wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))); +- wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); ++src3: ++ do { ++ uint32_t s = wuffs_base__peek_u24le__no_bounds_check(s_ptr); ++ uint32_t s0 = alphabet[0xFF & (s >> 0)]; ++ uint32_t s1 = alphabet[0xFF & (s >> 8)]; ++ uint32_t s2 = alphabet[0xFF & (s >> 16)]; ++ if ((s0 & 0xC0) || (s1 & 0xC0) || (s2 & 0xC3)) { ++ o.status.repr = wuffs_base__error__bad_data; ++ goto done; ++ } ++ if (d_len < 2) { ++ o.status.repr = wuffs_base__suspension__short_write; ++ goto done; ++ } ++ s_ptr += pad ? 4 : 3; ++ s = (s0 << 18) | (s1 << 12) | (s2 << 6); ++ *d_ptr++ = (uint8_t)(s >> 16); ++ *d_ptr++ = (uint8_t)(s >> 8); ++ o.status.repr = NULL; ++ goto done; ++ } while (0); + +- s += 1 * 2; +- d += 1 * 3; +- n -= 1; +- } ++src2: ++ do { ++ uint32_t s = wuffs_base__peek_u16le__no_bounds_check(s_ptr); ++ uint32_t s0 = alphabet[0xFF & (s >> 0)]; ++ uint32_t s1 = alphabet[0xFF & (s >> 8)]; ++ if ((s0 & 0xC0) || (s1 & 0xCF)) { ++ o.status.repr = wuffs_base__error__bad_data; ++ goto done; ++ } ++ if (d_len < 1) { ++ o.status.repr = wuffs_base__suspension__short_write; ++ goto done; ++ } ++ s_ptr += pad ? 4 : 2; ++ s = (s0 << 18) | (s1 << 12); ++ *d_ptr++ = (uint8_t)(s >> 16); ++ o.status.repr = NULL; ++ goto done; ++ } while (0); + +- return len; ++done: ++ o.num_dst = (size_t)(d_ptr - dst.ptr); ++ o.num_src = (size_t)(s_ptr - src.ptr); ++ return o; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output // ++wuffs_base__base_64__encode(wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 src, ++ bool src_closed, ++ uint32_t options) { ++ const uint8_t* alphabet = (options & WUFFS_BASE__BASE_64__URL_ALPHABET) ++ ? wuffs_base__base_64__encode_url ++ : wuffs_base__base_64__encode_std; ++ wuffs_base__transform__output o; ++ uint8_t* d_ptr = dst.ptr; ++ size_t d_len = dst.len; ++ const uint8_t* s_ptr = src.ptr; ++ size_t s_len = src.len; + +- // TODO: unroll. ++ do { ++ while (s_len >= 3) { ++ if (d_len < 4) { ++ o.status.repr = wuffs_base__suspension__short_write; ++ goto done; ++ } ++ uint32_t s = wuffs_base__peek_u24be__no_bounds_check(s_ptr); ++ s_ptr += 3; ++ s_len -= 3; ++ *d_ptr++ = alphabet[0x3F & (s >> 18)]; ++ *d_ptr++ = alphabet[0x3F & (s >> 12)]; ++ *d_ptr++ = alphabet[0x3F & (s >> 6)]; ++ *d_ptr++ = alphabet[0x3F & (s >> 0)]; ++ d_len -= 4; ++ } + +- while (n >= 1) { +- uint32_t s0 = +- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); ++ if (!src_closed) { ++ o.status.repr = wuffs_base__suspension__short_read; ++ goto done; ++ } + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; +- } ++ if (s_len == 2) { ++ if (d_len < ++ ((options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) ? 4 : 3)) { ++ o.status.repr = wuffs_base__suspension__short_write; ++ goto done; ++ } ++ uint32_t s = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(s_ptr))) ++ << 8; ++ s_ptr += 2; ++ *d_ptr++ = alphabet[0x3F & (s >> 18)]; ++ *d_ptr++ = alphabet[0x3F & (s >> 12)]; ++ *d_ptr++ = alphabet[0x3F & (s >> 6)]; ++ if (options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) { ++ *d_ptr++ = '='; ++ } ++ o.status.repr = NULL; ++ goto done; + +- return len; +-} ++ } else if (s_len == 1) { ++ if (d_len < ++ ((options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) ? 4 : 2)) { ++ o.status.repr = wuffs_base__suspension__short_write; ++ goto done; ++ } ++ uint32_t s = ((uint32_t)(wuffs_base__peek_u8__no_bounds_check(s_ptr))) ++ << 16; ++ s_ptr += 1; ++ *d_ptr++ = alphabet[0x3F & (s >> 18)]; ++ *d_ptr++ = alphabet[0x3F & (s >> 12)]; ++ if (options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) { ++ *d_ptr++ = '='; ++ *d_ptr++ = '='; ++ } ++ o.status.repr = NULL; ++ goto done; + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ } else { ++ o.status.repr = NULL; ++ goto done; ++ } ++ } while (0); + +- // TODO: unroll. ++done: ++ o.num_dst = (size_t)(d_ptr - dst.ptr); ++ o.num_src = (size_t)(s_ptr - src.ptr); ++ return o; ++} + +- while (n >= 1) { +- uint32_t s0 = +- wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))); +- wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); ++#endif // !defined(WUFFS_CONFIG__MODULES) || ++ // defined(WUFFS_CONFIG__MODULE__BASE) || ++ // defined(WUFFS_CONFIG__MODULE__BASE__INTCONV) + +- s += 1 * 8; +- d += 1 * 3; +- n -= 1; +- } ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ ++ defined(WUFFS_CONFIG__MODULE__BASE__MAGIC) + +- return len; +-} ++// ---------------- Magic Numbers + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++// ICO doesn't start with a magic identifier. Instead, see if the opening bytes ++// are plausibly ICO. ++// ++// Callers should have already verified that (prefix_data.len >= 2) and the ++// first two bytes are 0x00. ++// ++// See: ++// - https://docs.fileformat.com/image/ico/ ++static int32_t // ++wuffs_base__magic_number_guess_fourcc__maybe_ico( ++ wuffs_base__slice_u8 prefix_data, ++ bool prefix_closed) { ++ // Allow-list for the Image Type field. ++ if (prefix_data.len < 4) { ++ return prefix_closed ? 0 : -1; ++ } else if (prefix_data.ptr[3] != 0) { ++ return 0; ++ } ++ switch (prefix_data.ptr[2]) { ++ case 0x01: // ICO ++ case 0x02: // CUR ++ break; ++ default: ++ return 0; ++ } + +- // TODO: unroll. ++ // The Number Of Images should be positive. ++ if (prefix_data.len < 6) { ++ return prefix_closed ? 0 : -1; ++ } else if ((prefix_data.ptr[4] == 0) && (prefix_data.ptr[5] == 0)) { ++ return 0; ++ } + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t dr = 0x101 * ((uint32_t)d[2]); +- uint32_t dg = 0x101 * ((uint32_t)d[1]); +- uint32_t db = 0x101 * ((uint32_t)d[0]); +- uint32_t sa = 0x101 * ((uint32_t)s[3]); +- uint32_t sr = 0x101 * ((uint32_t)s[2]); +- uint32_t sg = 0x101 * ((uint32_t)s[1]); +- uint32_t sb = 0x101 * ((uint32_t)s[0]); ++ // The first ICONDIRENTRY's fourth byte should be zero. ++ if (prefix_data.len < 10) { ++ return prefix_closed ? 0 : -1; ++ } else if (prefix_data.ptr[9] != 0) { ++ return 0; ++ } + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ // TODO: have a separate FourCC for CUR? ++ return 0x49434F20; // 'ICO 'be ++} + +- // Composite src (nonpremul) over dst (premul). +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++// TGA doesn't start with a magic identifier. Instead, see if the opening bytes ++// are plausibly TGA. ++// ++// Callers should have already verified that (prefix_data.len >= 2) and the ++// second byte (prefix_data.ptr[1], the Color Map Type byte), is either 0x00 or ++// 0x01. ++// ++// See: ++// - https://docs.fileformat.com/image/tga/ ++// - https://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf ++static int32_t // ++wuffs_base__magic_number_guess_fourcc__maybe_tga( ++ wuffs_base__slice_u8 prefix_data, ++ bool prefix_closed) { ++ // Allow-list for the Image Type field. ++ if (prefix_data.len < 3) { ++ return prefix_closed ? 0 : -1; ++ } ++ switch (prefix_data.ptr[2]) { ++ case 0x01: ++ case 0x02: ++ case 0x03: ++ case 0x09: ++ case 0x0A: ++ case 0x0B: ++ break; ++ default: ++ // TODO: 0x20 and 0x21 are invalid, according to the spec, but are ++ // apparently unofficial extensions. ++ return 0; ++ } + +- // Convert from 16-bit color to 8-bit color. +- d[0] = (uint8_t)(db >> 8); +- d[1] = (uint8_t)(dg >> 8); +- d[2] = (uint8_t)(dr >> 8); ++ // Allow-list for the Color Map Entry Size field (if the Color Map Type field ++ // is non-zero) or else all the Color Map fields should be zero. ++ if (prefix_data.len < 8) { ++ return prefix_closed ? 0 : -1; ++ } else if (prefix_data.ptr[1] != 0x00) { ++ switch (prefix_data.ptr[7]) { ++ case 0x0F: ++ case 0x10: ++ case 0x18: ++ case 0x20: ++ break; ++ default: ++ return 0; ++ } ++ } else if ((prefix_data.ptr[3] | prefix_data.ptr[4] | prefix_data.ptr[5] | ++ prefix_data.ptr[6] | prefix_data.ptr[7]) != 0x00) { ++ return 0; ++ } + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; ++ // Allow-list for the Pixel Depth field. ++ if (prefix_data.len < 17) { ++ return prefix_closed ? 0 : -1; ++ } ++ switch (prefix_data.ptr[16]) { ++ case 0x01: ++ case 0x08: ++ case 0x0F: ++ case 0x10: ++ case 0x18: ++ case 0x20: ++ break; ++ default: ++ return 0; + } + +- return len; ++ return 0x54474120; // 'TGA 'be + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++WUFFS_BASE__MAYBE_STATIC int32_t // ++wuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix_data, ++ bool prefix_closed) { ++ // This is similar to (but different from): ++ // - the magic/Magdir tables under https://github.com/file/file ++ // - the MIME Sniffing algorithm at https://mimesniff.spec.whatwg.org/ + +- // TODO: unroll. ++ // table holds the 'magic numbers' (which are actually variable length ++ // strings). The strings may contain NUL bytes, so the "const char* magic" ++ // value starts with the length-minus-1 of the 'magic number'. ++ // ++ // Keep it sorted by magic[1], then magic[0] descending (prioritizing longer ++ // matches) and finally by magic[2:]. When multiple entries match, the ++ // longest one wins. ++ // ++ // The fourcc field might be negated, in which case there's further ++ // specialization (see § below). ++ static struct { ++ int32_t fourcc; ++ const char* magic; ++ } table[] = { ++ {-0x30302020, "\x01\x00\x00"}, // '00 'be ++ {+0x475A2020, "\x02\x1F\x8B\x08"}, // GZ ++ {+0x5A535444, "\x03\x28\xB5\x2F\xFD"}, // ZSTD ++ {+0x425A3220, "\x02\x42\x5A\x68"}, // BZ2 ++ {+0x424D5020, "\x01\x42\x4D"}, // BMP ++ {+0x47494620, "\x03\x47\x49\x46\x38"}, // GIF ++ {+0x54494646, "\x03\x49\x49\x2A\x00"}, // TIFF (little-endian) ++ {+0x4C5A4950, "\x04\x4C\x5A\x49\x50\x01"}, // LZIP ++ {+0x54494646, "\x03\x4D\x4D\x00\x2A"}, // TIFF (big-endian) ++ {+0x4E50424D, "\x02\x50\x35\x0A"}, // NPBM (P5; *.pgm) ++ {+0x4E50424D, "\x02\x50\x36\x0A"}, // NPBM (P6; *.ppm) ++ {-0x52494646, "\x03\x52\x49\x46\x46"}, // RIFF ++ {+0x4C5A4D41, "\x04\x5D\x00\x10\x00\x00"}, // LZMA ++ {+0x4C5A4D41, "\x02\x5D\x00\x00"}, // LZMA ++ {+0x4E494520, "\x02\x6E\xC3\xAF"}, // NIE ++ {+0x514F4920, "\x03\x71\x6F\x69\x66"}, // QOI ++ {+0x5A4C4942, "\x01\x78\x9C"}, // ZLIB ++ {+0x504E4720, "\x03\x89\x50\x4E\x47"}, // PNG ++ {+0x585A2020, "\x04\xFD\x37\x7A\x58\x5A"}, // XZ ++ {+0x4A504547, "\x01\xFF\xD8"}, // JPEG ++ }; ++ static const size_t table_len = sizeof(table) / sizeof(table[0]); + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t dr = 0x101 * ((uint32_t)d[2]); +- uint32_t dg = 0x101 * ((uint32_t)d[1]); +- uint32_t db = 0x101 * ((uint32_t)d[0]); +- uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6)); +- uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4)); +- uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2)); +- uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0)); ++ if (prefix_data.len == 0) { ++ return prefix_closed ? 0 : -1; ++ } ++ uint8_t pre_first_byte = prefix_data.ptr[0]; + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ int32_t fourcc = 0; ++ size_t i; ++ for (i = 0; i < table_len; i++) { ++ uint8_t mag_first_byte = ((uint8_t)(table[i].magic[1])); ++ if (pre_first_byte < mag_first_byte) { ++ break; ++ } else if (pre_first_byte > mag_first_byte) { ++ continue; ++ } ++ fourcc = table[i].fourcc; + +- // Composite src (nonpremul) over dst (premul). +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ uint8_t mag_remaining_len = ((uint8_t)(table[i].magic[0])); ++ if (mag_remaining_len == 0) { ++ goto match; ++ } + +- // Convert from 16-bit color to 8-bit color. +- d[0] = (uint8_t)(db >> 8); +- d[1] = (uint8_t)(dg >> 8); +- d[2] = (uint8_t)(dr >> 8); ++ const char* mag_remaining_ptr = table[i].magic + 2; ++ uint8_t* pre_remaining_ptr = prefix_data.ptr + 1; ++ size_t pre_remaining_len = prefix_data.len - 1; ++ if (pre_remaining_len < mag_remaining_len) { ++ if (!memcmp(pre_remaining_ptr, mag_remaining_ptr, pre_remaining_len)) { ++ return prefix_closed ? 0 : -1; ++ } ++ } else { ++ if (!memcmp(pre_remaining_ptr, mag_remaining_ptr, mag_remaining_len)) { ++ goto match; ++ } ++ } ++ } + +- s += 1 * 8; +- d += 1 * 3; +- n -= 1; ++ if (prefix_data.len < 2) { ++ return prefix_closed ? 0 : -1; ++ } else if ((prefix_data.ptr[1] == 0x00) || (prefix_data.ptr[1] == 0x01)) { ++ return wuffs_base__magic_number_guess_fourcc__maybe_tga(prefix_data, ++ prefix_closed); + } + +- return len; +-} ++ return 0; + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__bgra_premul__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++match: ++ // Negative FourCC values (see § above) are further specialized. ++ if (fourcc < 0) { ++ fourcc = -fourcc; + +- while (n >= 1) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- d[0] = s0; +- d[1] = s1; +- d[2] = s2; ++ if (fourcc == 0x52494646) { // 'RIFF'be ++ if (prefix_data.len < 12) { ++ return prefix_closed ? 0 : -1; ++ } ++ uint32_t x = wuffs_base__peek_u32be__no_bounds_check(prefix_data.ptr + 8); ++ if (x == 0x57454250) { // 'WEBP'be ++ return 0x57454250; // 'WEBP'be ++ } + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; ++ } else if (fourcc == 0x30302020) { // '00 'be ++ // Binary data starting with multiple 0x00 NUL bytes is quite common. ++ // Unfortunately, some file formats also don't start with a magic ++ // identifier, so we have to use heuristics (where the order matters, the ++ // same as /usr/bin/file's magic/Magdir tables) as best we can. Maybe ++ // it's TGA, ICO/CUR, etc. Maybe it's something else. ++ int32_t tga = wuffs_base__magic_number_guess_fourcc__maybe_tga( ++ prefix_data, prefix_closed); ++ if (tga != 0) { ++ return tga; ++ } ++ int32_t ico = wuffs_base__magic_number_guess_fourcc__maybe_ico( ++ prefix_data, prefix_closed); ++ if (ico != 0) { ++ return ico; ++ } ++ if (prefix_data.len < 4) { ++ return prefix_closed ? 0 : -1; ++ } else if ((prefix_data.ptr[2] != 0x00) && ++ ((prefix_data.ptr[2] >= 0x80) || ++ (prefix_data.ptr[3] != 0x00))) { ++ // Roughly speaking, this could be a non-degenerate (non-0-width and ++ // non-0-height) WBMP image. ++ return 0x57424D50; // 'WBMP'be ++ } ++ return 0; ++ } + } +- +- return len; ++ return fourcc; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__bgra_premul__src_over(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; +- +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t dr = 0x101 * ((uint32_t)d[2]); +- uint32_t dg = 0x101 * ((uint32_t)d[1]); +- uint32_t db = 0x101 * ((uint32_t)d[0]); +- uint32_t sa = 0x101 * ((uint32_t)s[3]); +- uint32_t sr = 0x101 * ((uint32_t)s[2]); +- uint32_t sg = 0x101 * ((uint32_t)s[1]); +- uint32_t sb = 0x101 * ((uint32_t)s[0]); +- +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++#endif // !defined(WUFFS_CONFIG__MODULES) || ++ // defined(WUFFS_CONFIG__MODULE__BASE) || ++ // defined(WUFFS_CONFIG__MODULE__BASE__MAGIC) + +- // Composite src (premul) over dst (premul). +- dr = sr + ((dr * ia) / 0xFFFF); +- dg = sg + ((dg * ia) / 0xFFFF); +- db = sb + ((db * ia) / 0xFFFF); ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ ++ defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV) + +- // Convert from 16-bit color to 8-bit color. +- d[0] = (uint8_t)(db >> 8); +- d[1] = (uint8_t)(dg >> 8); +- d[2] = (uint8_t)(dr >> 8); ++// ---------------- Pixel Swizzler + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; +- } ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__bgr__x86_sse42(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len); + +- return len; +-} ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__rgb__x86_sse42(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len); + ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + static uint64_t // +-wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++wuffs_private_impl__swizzle_swap_rgbx_bgrx__x86_sse42(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len); + +- // TODO: unroll. ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") ++static uint64_t // ++wuffs_private_impl__swizzle_xxxx__y__x86_sse42(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) + +- while (n >= 1) { +- uint32_t s0 = wuffs_base__swap_u32_argb_abgr( +- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); +- wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); ++// -------- + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; +- } ++static inline uint32_t // ++wuffs_private_impl__swap_u32_argb_abgr(uint32_t u) { ++ uint32_t o = u & 0xFF00FF00ul; ++ uint32_t r = u & 0x00FF0000ul; ++ uint32_t b = u & 0x000000FFul; ++ return o | (r >> 16) | (b << 16); ++} + +- return len; ++static inline uint64_t // ++wuffs_private_impl__swap_u64_argb_abgr(uint64_t u) { ++ uint64_t o = u & 0xFFFF0000FFFF0000ull; ++ uint64_t r = u & 0x0000FFFF00000000ull; ++ uint64_t b = u & 0x000000000000FFFFull; ++ return o | (r >> 32) | (b << 32); + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__rgba_nonpremul_4x16le__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++static inline uint32_t // ++wuffs_private_impl__color_u64__as__color_u32__swap_u32_argb_abgr(uint64_t c) { ++ uint32_t a = ((uint32_t)(0xFF & (c >> 56))); ++ uint32_t r = ((uint32_t)(0xFF & (c >> 40))); ++ uint32_t g = ((uint32_t)(0xFF & (c >> 24))); ++ uint32_t b = ((uint32_t)(0xFF & (c >> 8))); ++ return (a << 24) | (b << 16) | (g << 8) | (r << 0); ++} + +- // TODO: unroll. ++// -------- + +- while (n >= 1) { +- uint32_t s0 = wuffs_base__swap_u32_argb_abgr( +- wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( +- wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)))); +- wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul // ++wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb, ++ uint32_t x, ++ uint32_t y) { ++ if (!pb || (x >= pb->pixcfg.private_impl.width) || ++ (y >= pb->pixcfg.private_impl.height)) { ++ return 0; ++ } + +- s += 1 * 8; +- d += 1 * 3; +- n -= 1; ++ if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) { ++ // TODO: support planar formats. ++ return 0; + } + +- return len; +-} ++ size_t stride = pb->private_impl.planes[0].stride; ++ const uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)); + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ switch (pb->pixcfg.private_impl.pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ return wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))); + +- // TODO: unroll. ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: { ++ uint8_t* palette = pb->private_impl.planes[3].ptr; ++ return wuffs_base__peek_u32le__no_bounds_check(palette + ++ (4 * ((size_t)row[x]))); ++ } + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t dr = 0x101 * ((uint32_t)d[2]); +- uint32_t dg = 0x101 * ((uint32_t)d[1]); +- uint32_t db = 0x101 * ((uint32_t)d[0]); +- uint32_t sa = 0x101 * ((uint32_t)s[3]); +- uint32_t sb = 0x101 * ((uint32_t)s[2]); +- uint32_t sg = 0x101 * ((uint32_t)s[1]); +- uint32_t sr = 0x101 * ((uint32_t)s[0]); ++ // Common formats above. Rarer formats below. + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ case WUFFS_BASE__PIXEL_FORMAT__Y: ++ return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x]))); ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16LE: ++ return 0xFF000000 | (0x00010101 * ((uint32_t)(row[(2 * x) + 1]))); ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: ++ return 0xFF000000 | (0x00010101 * ((uint32_t)(row[(2 * x) + 0]))); ++ case WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL: ++ return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ (((uint32_t)(row[(2 * x) + 1])) << 24) | ++ (((uint32_t)(row[(2 * x) + 0])) * 0x00010101)); + +- // Composite src (nonpremul) over dst (premul). +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: { ++ uint8_t* palette = pb->private_impl.planes[3].ptr; ++ return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u32le__no_bounds_check(palette + ++ (4 * ((size_t)row[x])))); ++ } + +- // Convert from 16-bit color to 8-bit color. +- d[0] = (uint8_t)(db >> 8); +- d[1] = (uint8_t)(dg >> 8); +- d[2] = (uint8_t)(dr >> 8); ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( ++ wuffs_base__peek_u16le__no_bounds_check(row + (2 * ((size_t)x)))); ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ return 0xFF000000 | ++ wuffs_base__peek_u24le__no_bounds_check(row + (3 * ((size_t)x))); ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)))); ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ return wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u64le__no_bounds_check(row + (8 * ((size_t)x)))); ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ return 0xFF000000 | ++ wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))); + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ return wuffs_private_impl__swap_u32_argb_abgr( ++ 0xFF000000 | ++ wuffs_base__peek_u24le__no_bounds_check(row + (3 * ((size_t)x)))); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ return wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u32le__no_bounds_check(row + ++ (4 * ((size_t)x))))); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ return wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)))); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ return wuffs_private_impl__swap_u32_argb_abgr( ++ 0xFF000000 | ++ wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)))); ++ ++ default: ++ // TODO: support more formats. ++ break; + } + +- return len; ++ return 0; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__rgba_nonpremul_4x16le__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++// -------- + +- // TODO: unroll. ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status // ++wuffs_base__pixel_buffer__set_color_u32_at( ++ wuffs_base__pixel_buffer* pb, ++ uint32_t x, ++ uint32_t y, ++ wuffs_base__color_u32_argb_premul color) { ++ if (!pb) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if ((x >= pb->pixcfg.private_impl.width) || ++ (y >= pb->pixcfg.private_impl.height)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t dr = 0x101 * ((uint32_t)d[2]); +- uint32_t dg = 0x101 * ((uint32_t)d[1]); +- uint32_t db = 0x101 * ((uint32_t)d[0]); +- uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6)); +- uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4)); +- uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2)); +- uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0)); ++ if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) { ++ // TODO: support planar formats. ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ } + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ size_t stride = pb->private_impl.planes[0].stride; ++ uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)); + +- // Composite src (nonpremul) over dst (premul). +- dr = ((sr * sa) + (dr * ia)) / 0xFFFF; +- dg = ((sg * sa) + (dg * ia)) / 0xFFFF; +- db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ switch (pb->pixcfg.private_impl.pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ wuffs_base__poke_u32le__no_bounds_check(row + (4 * ((size_t)x)), color); ++ break; + +- // Convert from 16-bit color to 8-bit color. +- d[0] = (uint8_t)(db >> 8); +- d[1] = (uint8_t)(dg >> 8); +- d[2] = (uint8_t)(dr >> 8); ++ // Common formats above. Rarer formats below. + +- s += 1 * 8; +- d += 1 * 3; +- n -= 1; +- } ++ case WUFFS_BASE__PIXEL_FORMAT__Y: ++ wuffs_base__poke_u8__no_bounds_check( ++ row + ((size_t)x), ++ wuffs_base__color_u32_argb_premul__as__color_u8_gray(color)); ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16LE: ++ wuffs_base__poke_u16le__no_bounds_check( ++ row + (2 * ((size_t)x)), ++ wuffs_base__color_u32_argb_premul__as__color_u16_gray(color)); ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: ++ wuffs_base__poke_u16be__no_bounds_check( ++ row + (2 * ((size_t)x)), ++ wuffs_base__color_u32_argb_premul__as__color_u16_gray(color)); ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL: ++ wuffs_base__poke_u16le__no_bounds_check( ++ row + (2 * ((size_t)x)), ++ wuffs_base__color_u32_argb_premul__as__color_u16_alpha_gray_nonpremul( ++ color)); ++ break; + +- return len; +-} ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: ++ wuffs_base__poke_u8__no_bounds_check( ++ row + ((size_t)x), wuffs_base__pixel_palette__closest_element( ++ wuffs_base__pixel_buffer__palette(pb), ++ pb->pixcfg.private_impl.pixfmt, color)); ++ break; + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__rgba_premul__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ wuffs_base__poke_u16le__no_bounds_check( ++ row + (2 * ((size_t)x)), ++ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color)); ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ wuffs_base__poke_u24le__no_bounds_check(row + (3 * ((size_t)x)), color); ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ wuffs_base__poke_u32le__no_bounds_check( ++ row + (4 * ((size_t)x)), ++ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( ++ color)); ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ wuffs_base__poke_u64le__no_bounds_check( ++ row + (8 * ((size_t)x)), ++ wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul( ++ color)); ++ break; + +- while (n >= 1) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- d[0] = s2; +- d[1] = s1; +- d[2] = s0; ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ wuffs_base__poke_u24le__no_bounds_check( ++ row + (3 * ((size_t)x)), ++ wuffs_private_impl__swap_u32_argb_abgr(color)); ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ wuffs_base__poke_u32le__no_bounds_check( ++ row + (4 * ((size_t)x)), ++ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( ++ wuffs_private_impl__swap_u32_argb_abgr(color))); ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ wuffs_base__poke_u32le__no_bounds_check( ++ row + (4 * ((size_t)x)), ++ wuffs_private_impl__swap_u32_argb_abgr(color)); ++ break; + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; ++ default: ++ // TODO: support more formats. ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +- return len; ++ return wuffs_base__make_status(NULL); + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__rgba_premul__src_over(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++// -------- + +- while (n >= 1) { +- // Extract 16-bit color components. +- uint32_t dr = 0x101 * ((uint32_t)d[2]); +- uint32_t dg = 0x101 * ((uint32_t)d[1]); +- uint32_t db = 0x101 * ((uint32_t)d[0]); +- uint32_t sa = 0x101 * ((uint32_t)s[3]); +- uint32_t sb = 0x101 * ((uint32_t)s[2]); +- uint32_t sg = 0x101 * ((uint32_t)s[1]); +- uint32_t sr = 0x101 * ((uint32_t)s[0]); ++static inline void // ++wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xx( ++ wuffs_base__pixel_buffer* pb, ++ wuffs_base__rect_ie_u32 rect, ++ uint16_t color) { ++ size_t stride = pb->private_impl.planes[0].stride; ++ uint32_t width = wuffs_base__rect_ie_u32__width(&rect); ++ if ((stride == (2 * ((uint64_t)width))) && (rect.min_incl_x == 0)) { ++ uint8_t* ptr = ++ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y)); ++ uint32_t height = wuffs_base__rect_ie_u32__height(&rect); ++ size_t n; ++ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) { ++ wuffs_base__poke_u16le__no_bounds_check(ptr, color); ++ ptr += 2; ++ } ++ return; ++ } + +- // Calculate the inverse of the src-alpha: how much of the dst to keep. +- uint32_t ia = 0xFFFF - sa; ++ uint32_t y; ++ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { ++ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) + ++ (2 * ((size_t)rect.min_incl_x)); ++ uint32_t n; ++ for (n = width; n > 0; n--) { ++ wuffs_base__poke_u16le__no_bounds_check(ptr, color); ++ ptr += 2; ++ } ++ } ++} + +- // Composite src (premul) over dst (premul). +- dr = sr + ((dr * ia) / 0xFFFF); +- dg = sg + ((dg * ia) / 0xFFFF); +- db = sb + ((db * ia) / 0xFFFF); ++static inline void // ++wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxx( ++ wuffs_base__pixel_buffer* pb, ++ wuffs_base__rect_ie_u32 rect, ++ uint32_t color) { ++ size_t stride = pb->private_impl.planes[0].stride; ++ uint32_t width = wuffs_base__rect_ie_u32__width(&rect); ++ if ((stride == (3 * ((uint64_t)width))) && (rect.min_incl_x == 0)) { ++ uint8_t* ptr = ++ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y)); ++ uint32_t height = wuffs_base__rect_ie_u32__height(&rect); ++ size_t n; ++ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) { ++ wuffs_base__poke_u24le__no_bounds_check(ptr, color); ++ ptr += 3; ++ } ++ return; ++ } + +- // Convert from 16-bit color to 8-bit color. +- d[0] = (uint8_t)(db >> 8); +- d[1] = (uint8_t)(dg >> 8); +- d[2] = (uint8_t)(dr >> 8); ++ uint32_t y; ++ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { ++ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) + ++ (3 * ((size_t)rect.min_incl_x)); ++ uint32_t n; ++ for (n = width; n > 0; n--) { ++ wuffs_base__poke_u24le__no_bounds_check(ptr, color); ++ ptr += 3; ++ } ++ } ++} + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; ++static inline void // ++wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxxx( ++ wuffs_base__pixel_buffer* pb, ++ wuffs_base__rect_ie_u32 rect, ++ uint32_t color) { ++ size_t stride = pb->private_impl.planes[0].stride; ++ uint32_t width = wuffs_base__rect_ie_u32__width(&rect); ++ if ((stride == (4 * ((uint64_t)width))) && (rect.min_incl_x == 0)) { ++ uint8_t* ptr = ++ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y)); ++ uint32_t height = wuffs_base__rect_ie_u32__height(&rect); ++ size_t n; ++ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) { ++ wuffs_base__poke_u32le__no_bounds_check(ptr, color); ++ ptr += 4; ++ } ++ return; + } + +- return len; ++ uint32_t y; ++ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { ++ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) + ++ (4 * ((size_t)rect.min_incl_x)); ++ uint32_t n; ++ for (n = width; n > 0; n--) { ++ wuffs_base__poke_u32le__no_bounds_check(ptr, color); ++ ptr += 4; ++ } ++ } + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgr__rgbx(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++static inline void // ++wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx( ++ wuffs_base__pixel_buffer* pb, ++ wuffs_base__rect_ie_u32 rect, ++ uint64_t color) { ++ size_t stride = pb->private_impl.planes[0].stride; ++ uint32_t width = wuffs_base__rect_ie_u32__width(&rect); ++ if ((stride == (8 * ((uint64_t)width))) && (rect.min_incl_x == 0)) { ++ uint8_t* ptr = ++ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y)); ++ uint32_t height = wuffs_base__rect_ie_u32__height(&rect); ++ size_t n; ++ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) { ++ wuffs_base__poke_u64le__no_bounds_check(ptr, color); ++ ptr += 8; ++ } ++ return; ++ } + +- // TODO: unroll. ++ uint32_t y; ++ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { ++ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) + ++ (8 * ((size_t)rect.min_incl_x)); ++ uint32_t n; ++ for (n = width; n > 0; n--) { ++ wuffs_base__poke_u64le__no_bounds_check(ptr, color); ++ ptr += 8; ++ } ++ } ++} + +- while (n >= 1) { +- uint8_t b0 = s[0]; +- uint8_t b1 = s[1]; +- uint8_t b2 = s[2]; +- d[0] = b2; +- d[1] = b1; +- d[2] = b0; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status // ++wuffs_base__pixel_buffer__set_color_u32_fill_rect( ++ wuffs_base__pixel_buffer* pb, ++ wuffs_base__rect_ie_u32 rect, ++ wuffs_base__color_u32_argb_premul color) { ++ if (!pb) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } else if (wuffs_base__rect_ie_u32__is_empty(&rect)) { ++ return wuffs_base__make_status(NULL); ++ } ++ wuffs_base__rect_ie_u32 bounds = ++ wuffs_base__pixel_config__bounds(&pb->pixcfg); ++ if (!wuffs_base__rect_ie_u32__contains_rect(&bounds, rect)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } + +- s += 1 * 4; +- d += 1 * 3; +- n -= 1; ++ if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) { ++ // TODO: support planar formats. ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +- return len; +-} ++ switch (pb->pixcfg.private_impl.pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, ++ color); ++ return wuffs_base__make_status(NULL); + +-// -------- ++ // Common formats above. Rarer formats below. + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xx( ++ pb, rect, ++ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color)); ++ return wuffs_base__make_status(NULL); + +- while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0)); ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxx(pb, rect, ++ color); ++ return wuffs_base__make_status(NULL); + +- s += 1 * 4; +- d += 1 * 4; +- n -= 1; +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxxx( ++ pb, rect, ++ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( ++ color)); ++ return wuffs_base__make_status(NULL); + +- return len; +-} ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx( ++ pb, rect, ++ wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul( ++ color)); ++ return wuffs_base__make_status(NULL); + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxxx( ++ pb, rect, ++ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( ++ wuffs_private_impl__swap_u32_argb_abgr(color))); ++ return wuffs_base__make_status(NULL); + +- size_t n = len; +- while (n >= 1) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__color_u64__as__color_u32( +- wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)))); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ wuffs_private_impl__pixel_buffer__set_color_u32_fill_rect__xxxx( ++ pb, rect, wuffs_private_impl__swap_u32_argb_abgr(color)); ++ return wuffs_base__make_status(NULL); ++ } + +- s += 1 * 8; +- d += 1 * 4; +- n -= 1; ++ uint32_t y; ++ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) { ++ uint32_t x; ++ for (x = rect.min_incl_x; x < rect.max_excl_x; x++) { ++ wuffs_base__pixel_buffer__set_color_u32_at(pb, x, y, color); ++ } + } +- return len; ++ return wuffs_base__make_status(NULL); + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; +- +- while (n >= 1) { +- uint64_t d0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4))); +- uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u64__as__color_u32( +- wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0))); ++// -------- + +- s += 1 * 8; +- d += 1 * 4; +- n -= 1; ++WUFFS_BASE__MAYBE_STATIC uint8_t // ++wuffs_base__pixel_palette__closest_element( ++ wuffs_base__slice_u8 palette_slice, ++ wuffs_base__pixel_format palette_format, ++ wuffs_base__color_u32_argb_premul c) { ++ size_t n = palette_slice.len / 4; ++ if (n > (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ n = (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4); + } ++ size_t best_index = 0; ++ uint64_t best_score = 0xFFFFFFFFFFFFFFFF; + +- return len; +-} +- +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ // Work in 16-bit color. ++ uint32_t ca = 0x101 * (0xFF & (c >> 24)); ++ uint32_t cr = 0x101 * (0xFF & (c >> 16)); ++ uint32_t cg = 0x101 * (0xFF & (c >> 8)); ++ uint32_t cb = 0x101 * (0xFF & (c >> 0)); + +- while (n >= 1) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(s0)); ++ switch (palette_format.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: { ++ bool nonpremul = palette_format.repr == ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL; + +- s += 1 * 4; +- d += 1 * 4; +- n -= 1; ++ size_t i; ++ for (i = 0; i < n; i++) { ++ // Work in 16-bit color. ++ uint32_t pb = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 0])); ++ uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1])); ++ uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2])); ++ uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3])); ++ ++ // Convert to premultiplied alpha. ++ if (nonpremul && (pa != 0xFFFF)) { ++ pb = (pb * pa) / 0xFFFF; ++ pg = (pg * pa) / 0xFFFF; ++ pr = (pr * pa) / 0xFFFF; ++ } ++ ++ // These deltas are conceptually int32_t (signed) but after squaring, ++ // it's equivalent to work in uint32_t (unsigned). ++ pb -= cb; ++ pg -= cg; ++ pr -= cr; ++ pa -= ca; ++ uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) + ++ ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa)); ++ if (best_score > score) { ++ best_score = score; ++ best_index = i; ++ } ++ } ++ break; ++ } + } + +- return len; ++ return (uint8_t)best_index; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++// -------- + +- while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__composite_nonpremul_premul_u32_axxx(d0, s0)); ++static inline uint32_t // ++wuffs_private_impl__composite_nonpremul_nonpremul_u32_axxx( ++ uint32_t dst_nonpremul, ++ uint32_t src_nonpremul) { ++ // Extract 16-bit color components. ++ // ++ // If the destination is transparent then SRC_OVER is equivalent to SRC: just ++ // return src_nonpremul. This isn't just an optimization (skipping the rest ++ // of the function's computation). It also preserves the nonpremul ++ // distinction between e.g. transparent red and transparent blue that would ++ // otherwise be lost by converting from nonpremul to premul and back. ++ uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24)); ++ if (da == 0) { ++ return src_nonpremul; ++ } ++ uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16)); ++ uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8)); ++ uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0)); ++ uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24)); ++ uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16)); ++ uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8)); ++ uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0)); + +- s += 1 * 4; +- d += 1 * 4; +- n -= 1; ++ // Convert dst from nonpremul to premul. ++ dr = (dr * da) / 0xFFFF; ++ dg = (dg * da) / 0xFFFF; ++ db = (db * da) / 0xFFFF; ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (nonpremul) over dst (premul). ++ da = sa + ((da * ia) / 0xFFFF); ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert dst from premul to nonpremul. ++ if (da != 0) { ++ dr = (dr * 0xFFFF) / da; ++ dg = (dg * 0xFFFF) / da; ++ db = (db * 0xFFFF) / da; + } + +- return len; ++ // Convert from 16-bit color to 8-bit color. ++ da >>= 8; ++ dr >>= 8; ++ dg >>= 8; ++ db >>= 8; ++ ++ // Combine components. ++ return (db << 0) | (dg << 8) | (dr << 16) | (da << 24); + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; ++static inline uint64_t // ++wuffs_private_impl__composite_nonpremul_nonpremul_u64_axxx( ++ uint64_t dst_nonpremul, ++ uint64_t src_nonpremul) { ++ // Extract components. ++ // ++ // If the destination is transparent then SRC_OVER is equivalent to SRC: just ++ // return src_nonpremul. This isn't just an optimization (skipping the rest ++ // of the function's computation). It also preserves the nonpremul ++ // distinction between e.g. transparent red and transparent blue that would ++ // otherwise be lost by converting from nonpremul to premul and back. ++ uint64_t da = 0xFFFF & (dst_nonpremul >> 48); ++ if (da == 0) { ++ return src_nonpremul; + } +- size_t dst_len4 = dst_len / 4; +- size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ uint64_t dr = 0xFFFF & (dst_nonpremul >> 32); ++ uint64_t dg = 0xFFFF & (dst_nonpremul >> 16); ++ uint64_t db = 0xFFFF & (dst_nonpremul >> 0); ++ uint64_t sa = 0xFFFF & (src_nonpremul >> 48); ++ uint64_t sr = 0xFFFF & (src_nonpremul >> 32); ++ uint64_t sg = 0xFFFF & (src_nonpremul >> 16); ++ uint64_t sb = 0xFFFF & (src_nonpremul >> 0); + +- // TODO: unroll. ++ // Convert dst from nonpremul to premul. ++ dr = (dr * da) / 0xFFFF; ++ dg = (dg * da) / 0xFFFF; ++ db = (db * da) / 0xFFFF; + +- while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0)); ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint64_t ia = 0xFFFF - sa; + +- s += 1 * 1; +- d += 1 * 4; +- n -= 1; ++ // Composite src (nonpremul) over dst (premul). ++ da = sa + ((da * ia) / 0xFFFF); ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert dst from premul to nonpremul. ++ if (da != 0) { ++ dr = (dr * 0xFFFF) / da; ++ dg = (dg * 0xFFFF) / da; ++ db = (db * 0xFFFF) / da; + } + +- return len; ++ // Combine components. ++ return (db << 0) | (dg << 16) | (dr << 32) | (da << 48); + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++static inline uint32_t // ++wuffs_private_impl__composite_nonpremul_premul_u32_axxx(uint32_t dst_nonpremul, ++ uint32_t src_premul) { ++ // Extract 16-bit color components. ++ uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24)); ++ uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16)); ++ uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8)); ++ uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0)); ++ uint32_t sa = 0x101 * (0xFF & (src_premul >> 24)); ++ uint32_t sr = 0x101 * (0xFF & (src_premul >> 16)); ++ uint32_t sg = 0x101 * (0xFF & (src_premul >> 8)); ++ uint32_t sb = 0x101 * (0xFF & (src_premul >> 0)); + +- while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0)); ++ // Convert dst from nonpremul to premul. ++ dr = (dr * da) / 0xFFFF; ++ dg = (dg * da) / 0xFFFF; ++ db = (db * da) / 0xFFFF; + +- s += 1 * 4; +- d += 1 * 4; +- n -= 1; ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (premul) over dst (premul). ++ da = sa + ((da * ia) / 0xFFFF); ++ dr = sr + ((dr * ia) / 0xFFFF); ++ dg = sg + ((dg * ia) / 0xFFFF); ++ db = sb + ((db * ia) / 0xFFFF); ++ ++ // Convert dst from premul to nonpremul. ++ if (da != 0) { ++ dr = (dr * 0xFFFF) / da; ++ dg = (dg * 0xFFFF) / da; ++ db = (db * 0xFFFF) / da; + } + +- return len; ++ // Convert from 16-bit color to 8-bit color. ++ da >>= 8; ++ dr >>= 8; ++ dg >>= 8; ++ db >>= 8; ++ ++ // Combine components. ++ return (db << 0) | (dg << 8) | (dr << 16) | (da << 24); + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++static inline uint64_t // ++wuffs_private_impl__composite_nonpremul_premul_u64_axxx(uint64_t dst_nonpremul, ++ uint64_t src_premul) { ++ // Extract components. ++ uint64_t da = 0xFFFF & (dst_nonpremul >> 48); ++ uint64_t dr = 0xFFFF & (dst_nonpremul >> 32); ++ uint64_t dg = 0xFFFF & (dst_nonpremul >> 16); ++ uint64_t db = 0xFFFF & (dst_nonpremul >> 0); ++ uint64_t sa = 0xFFFF & (src_premul >> 48); ++ uint64_t sr = 0xFFFF & (src_premul >> 32); ++ uint64_t sg = 0xFFFF & (src_premul >> 16); ++ uint64_t sb = 0xFFFF & (src_premul >> 0); + +- while (n >= 1) { +- uint32_t s0 = wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(s0)); ++ // Convert dst from nonpremul to premul. ++ dr = (dr * da) / 0xFFFF; ++ dg = (dg * da) / 0xFFFF; ++ db = (db * da) / 0xFFFF; + +- s += 1 * 4; +- d += 1 * 4; +- n -= 1; ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint64_t ia = 0xFFFF - sa; ++ ++ // Composite src (premul) over dst (premul). ++ da = sa + ((da * ia) / 0xFFFF); ++ dr = sr + ((dr * ia) / 0xFFFF); ++ dg = sg + ((dg * ia) / 0xFFFF); ++ db = sb + ((db * ia) / 0xFFFF); ++ ++ // Convert dst from premul to nonpremul. ++ if (da != 0) { ++ dr = (dr * 0xFFFF) / da; ++ dg = (dg * 0xFFFF) / da; ++ db = (db * 0xFFFF) / da; + } + +- return len; ++ // Combine components. ++ return (db << 0) | (dg << 16) | (dr << 32) | (da << 48); + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++static inline uint32_t // ++wuffs_private_impl__composite_premul_nonpremul_u32_axxx( ++ uint32_t dst_premul, ++ uint32_t src_nonpremul) { ++ // Extract 16-bit color components. ++ uint32_t da = 0x101 * (0xFF & (dst_premul >> 24)); ++ uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16)); ++ uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8)); ++ uint32_t db = 0x101 * (0xFF & (dst_premul >> 0)); ++ uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24)); ++ uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16)); ++ uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8)); ++ uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0)); + +- while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__composite_nonpremul_premul_u32_axxx(d0, s0)); ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; + +- s += 1 * 4; +- d += 1 * 4; +- n -= 1; +- } ++ // Composite src (nonpremul) over dst (premul). ++ da = sa + ((da * ia) / 0xFFFF); ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; + +- return len; ++ // Convert from 16-bit color to 8-bit color. ++ da >>= 8; ++ dr >>= 8; ++ dg >>= 8; ++ db >>= 8; ++ ++ // Combine components. ++ return (db << 0) | (dg << 8) | (dr << 16) | (da << 24); ++} ++ ++static inline uint64_t // ++wuffs_private_impl__composite_premul_nonpremul_u64_axxx( ++ uint64_t dst_premul, ++ uint64_t src_nonpremul) { ++ // Extract components. ++ uint64_t da = 0xFFFF & (dst_premul >> 48); ++ uint64_t dr = 0xFFFF & (dst_premul >> 32); ++ uint64_t dg = 0xFFFF & (dst_premul >> 16); ++ uint64_t db = 0xFFFF & (dst_premul >> 0); ++ uint64_t sa = 0xFFFF & (src_nonpremul >> 48); ++ uint64_t sr = 0xFFFF & (src_nonpremul >> 32); ++ uint64_t sg = 0xFFFF & (src_nonpremul >> 16); ++ uint64_t sb = 0xFFFF & (src_nonpremul >> 0); ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint64_t ia = 0xFFFF - sa; ++ ++ // Composite src (nonpremul) over dst (premul). ++ da = sa + ((da * ia) / 0xFFFF); ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Combine components. ++ return (db << 0) | (dg << 16) | (dr << 32) | (da << 48); ++} ++ ++static inline uint32_t // ++wuffs_private_impl__composite_premul_premul_u32_axxx(uint32_t dst_premul, ++ uint32_t src_premul) { ++ // Extract 16-bit color components. ++ uint32_t da = 0x101 * (0xFF & (dst_premul >> 24)); ++ uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16)); ++ uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8)); ++ uint32_t db = 0x101 * (0xFF & (dst_premul >> 0)); ++ uint32_t sa = 0x101 * (0xFF & (src_premul >> 24)); ++ uint32_t sr = 0x101 * (0xFF & (src_premul >> 16)); ++ uint32_t sg = 0x101 * (0xFF & (src_premul >> 8)); ++ uint32_t sb = 0x101 * (0xFF & (src_premul >> 0)); ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (premul) over dst (premul). ++ da = sa + ((da * ia) / 0xFFFF); ++ dr = sr + ((dr * ia) / 0xFFFF); ++ dg = sg + ((dg * ia) / 0xFFFF); ++ db = sb + ((db * ia) / 0xFFFF); ++ ++ // Convert from 16-bit color to 8-bit color. ++ da >>= 8; ++ dr >>= 8; ++ dg >>= 8; ++ db >>= 8; ++ ++ // Combine components. ++ return (db << 0) | (dg << 8) | (dr << 16) | (da << 24); + } + + // -------- + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++wuffs_private_impl__swizzle_squash_align4_bgr_565_8888(uint8_t* dst_ptr, ++ size_t dst_len, ++ const uint8_t* src_ptr, ++ size_t src_len, ++ bool nonpremul) { ++ size_t len = (dst_len < src_len ? dst_len : src_len) / 4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + + size_t n = len; +- while (n >= 1) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- uint8_t s3 = s[3]; +- d[0] = s0; +- d[1] = s0; +- d[2] = s1; +- d[3] = s1; +- d[4] = s2; +- d[5] = s2; +- d[6] = s3; +- d[7] = s3; +- +- s += 1 * 4; +- d += 1 * 8; +- n -= 1; ++ while (n--) { ++ uint32_t argb = wuffs_base__peek_u32le__no_bounds_check(s); ++ if (nonpremul) { ++ argb = ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(argb); ++ } ++ uint32_t b5 = 0x1F & (argb >> (8 - 5)); ++ uint32_t g6 = 0x3F & (argb >> (16 - 6)); ++ uint32_t r5 = 0x1F & (argb >> (24 - 5)); ++ uint32_t alpha = argb & 0xFF000000; ++ wuffs_base__poke_u32le__no_bounds_check( ++ d, alpha | (r5 << 11) | (g6 << 5) | (b5 << 0)); ++ s += 4; ++ d += 4; + } + return len; + } + ++// -------- ++ + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++wuffs_private_impl__swizzle_swap_rgb_bgr(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t len = (dst_len < src_len ? dst_len : src_len) / 3; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + + size_t n = len; +- while (n >= 1) { +- uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); +- uint64_t s0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), +- wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); +- +- s += 1 * 4; +- d += 1 * 8; +- n -= 1; ++ while (n--) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ d[0] = s2; ++ d[1] = s1; ++ d[2] = s0; ++ s += 3; ++ d += 3; + } + return len; + } + ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul_4x16le__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len8 < src_len8) ? dst_len8 : src_len8; ++wuffs_private_impl__swizzle_swap_rgbx_bgrx__x86_sse42(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t len = (dst_len < src_len ? dst_len : src_len) / 4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; +- + size_t n = len; +- while (n >= 1) { +- uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); +- uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), +- wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); + +- s += 1 * 8; +- d += 1 * 8; +- n -= 1; ++ __m128i shuffle = _mm_set_epi8(+0x0F, +0x0C, +0x0D, +0x0E, // ++ +0x0B, +0x08, +0x09, +0x0A, // ++ +0x07, +0x04, +0x05, +0x06, // ++ +0x03, +0x00, +0x01, +0x02); ++ ++ while (n >= 4) { ++ __m128i x; ++ x = _mm_lddqu_si128((const __m128i*)(const void*)s); ++ x = _mm_shuffle_epi8(x, shuffle); ++ _mm_storeu_si128((__m128i*)(void*)d, x); ++ ++ s += 4 * 4; ++ d += 4 * 4; ++ n -= 4; ++ } ++ ++ while (n--) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ uint8_t s3 = s[3]; ++ d[0] = s2; ++ d[1] = s1; ++ d[2] = s0; ++ d[3] = s3; ++ s += 4; ++ d += 4; + } + return len; + } ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++wuffs_private_impl__swizzle_swap_rgbx_bgrx(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t len = (dst_len < src_len ? dst_len : src_len) / 4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + + size_t n = len; +- while (n >= 1) { +- uint64_t s0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); +- wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0); +- +- s += 1 * 4; +- d += 1 * 8; +- n -= 1; ++ while (n--) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ uint8_t s3 = s[3]; ++ d[0] = s2; ++ d[1] = s1; ++ d[2] = s0; ++ d[3] = s3; ++ s += 4; ++ d += 4; + } + return len; + } + +-static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- +- size_t n = len; +- while (n >= 1) { +- uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); +- uint64_t s0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), wuffs_base__composite_nonpremul_premul_u64_axxx(d0, s0)); ++// -------- + +- s += 1 * 4; +- d += 1 * 8; +- n -= 1; ++static uint64_t // ++wuffs_private_impl__swizzle_copy_1_1(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t len = (dst_len < src_len) ? dst_len : src_len; ++ if (len > 0) { ++ memmove(dst_ptr, src_ptr, len); + } + return len; + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__index_bgra_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; ++wuffs_private_impl__swizzle_copy_2_2(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; ++ if (len > 0) { ++ memmove(dst_ptr, src_ptr, len * 2); + } +- size_t dst_len8 = dst_len / 8; +- size_t len = (dst_len8 < src_len) ? dst_len8 : src_len; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; +- +- while (n >= 1) { +- uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); +- uint64_t s0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4))); +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), +- wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); ++ return len; ++} + +- s += 1 * 1; +- d += 1 * 8; +- n -= 1; ++static uint64_t // ++wuffs_private_impl__swizzle_copy_3_3(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len3 < src_len3) ? dst_len3 : src_len3; ++ if (len > 0) { ++ memmove(dst_ptr, src_ptr, len * 3); + } +- + return len; + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; ++wuffs_private_impl__swizzle_copy_4_4(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; + size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- +- size_t n = len; +- while (n >= 1) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- uint8_t s3 = s[3]; +- d[0] = s2; +- d[1] = s2; +- d[2] = s1; +- d[3] = s1; +- d[4] = s0; +- d[5] = s0; +- d[6] = s3; +- d[7] = s3; +- +- s += 1 * 4; +- d += 1 * 8; +- n -= 1; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ if (len > 0) { ++ memmove(dst_ptr, src_ptr, len * 4); + } + return len; + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_copy_8_8(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len8 = dst_len / 8; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- +- size_t n = len; +- while (n >= 1) { +- uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); +- uint64_t s0 = +- wuffs_base__color_u32__as__color_u64(wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), +- wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); +- +- s += 1 * 4; +- d += 1 * 8; +- n -= 1; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len8 < src_len8) ? dst_len8 : src_len8; ++ if (len > 0) { ++ memmove(dst_ptr, src_ptr, len * 8); + } + return len; + } + ++// -------- ++ + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++wuffs_private_impl__swizzle_bgr_565__bgr(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len2 < src_len3) ? dst_len2 : src_len3; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; +- + size_t n = len; ++ ++ // TODO: unroll. ++ + while (n >= 1) { +- uint64_t s0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( +- wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))))); +- wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0); ++ uint32_t b5 = (uint32_t)(s[0] >> 3); ++ uint32_t g6 = (uint32_t)(s[1] >> 2); ++ uint32_t r5 = (uint32_t)(s[2] >> 3); ++ uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); + +- s += 1 * 4; +- d += 1 * 8; ++ s += 1 * 3; ++ d += 1 * 2; + n -= 1; + } ++ + return len; + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; ++wuffs_private_impl__swizzle_bgr_565__bgrx(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; + size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; +- + size_t n = len; ++ ++ // TODO: unroll. ++ + while (n >= 1) { +- uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); +- uint64_t s0 = +- wuffs_base__color_u32__as__color_u64(wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), wuffs_base__composite_nonpremul_premul_u64_axxx(d0, s0)); ++ uint32_t b5 = (uint32_t)(s[0] >> 3); ++ uint32_t g6 = (uint32_t)(s[1] >> 2); ++ uint32_t r5 = (uint32_t)(s[2] >> 3); ++ uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); + + s += 1 * 4; +- d += 1 * 8; ++ d += 1 * 2; + n -= 1; + } ++ + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src( ++wuffs_private_impl__swizzle_bgr_565__bgra_nonpremul__src( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++ size_t dst_len2 = dst_len / 2; + size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22217,13 +23221,14 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src( + // TODO: unroll. + + while (n >= 1) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0)); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), ++ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))))); + + s += 1 * 4; +- d += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22231,16 +23236,16 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src( ++wuffs_private_impl__swizzle_bgr_565__bgra_nonpremul_4x16le__src( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++ size_t dst_len2 = dst_len / 2; + size_t src_len8 = src_len / 8; +- size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ size_t len = (dst_len2 < src_len8) ? dst_len2 : src_len8; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22248,13 +23253,14 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src( + // TODO: unroll. + + while (n >= 1) { +- uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(s0)); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), ++ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( ++ wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))))); + + s += 1 * 8; +- d += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22262,16 +23268,16 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over( ++wuffs_private_impl__swizzle_bgr_565__bgra_nonpremul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++ size_t dst_len2 = dst_len / 2; + size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22279,13 +23285,38 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over( + // TODO: unroll. + + while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0)); ++ // Extract 16-bit color components. ++ uint32_t sa = 0x101 * ((uint32_t)s[3]); ++ uint32_t sr = 0x101 * ((uint32_t)s[2]); ++ uint32_t sg = 0x101 * ((uint32_t)s[1]); ++ uint32_t sb = 0x101 * ((uint32_t)s[0]); ++ ++ // Convert from 565 color to 16-bit color. ++ uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); ++ uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); ++ uint32_t dr = (0x8421 * old_r5) >> 4; ++ uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); ++ uint32_t dg = (0x1041 * old_g6) >> 2; ++ uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); ++ uint32_t db = (0x8421 * old_b5) >> 4; ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (nonpremul) over dst (premul). ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert from 16-bit color to 565 color and combine the components. ++ uint32_t new_r5 = 0x1F & (dr >> 11); ++ uint32_t new_g6 = 0x3F & (dg >> 10); ++ uint32_t new_b5 = 0x1F & (db >> 11); ++ uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); + + s += 1 * 4; +- d += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22293,16 +23324,16 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src_over( ++wuffs_private_impl__swizzle_bgr_565__bgra_nonpremul_4x16le__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++ size_t dst_len2 = dst_len / 2; + size_t src_len8 = src_len / 8; +- size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ size_t len = (dst_len2 < src_len8) ? dst_len2 : src_len8; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22310,16 +23341,38 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src_over( + // TODO: unroll. + + while (n >= 1) { +- uint64_t d0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4))); +- uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u64__as__color_u32( +- wuffs_base__composite_premul_nonpremul_u64_axxx(d0, s0))); ++ // Extract 16-bit color components. ++ uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6)); ++ uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4)); ++ uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2)); ++ uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0)); ++ ++ // Convert from 565 color to 16-bit color. ++ uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); ++ uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); ++ uint32_t dr = (0x8421 * old_r5) >> 4; ++ uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); ++ uint32_t dg = (0x1041 * old_g6) >> 2; ++ uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); ++ uint32_t db = (0x8421 * old_b5) >> 4; ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (nonpremul) over dst (premul). ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert from 16-bit color to 565 color and combine the components. ++ uint32_t new_r5 = 0x1F & (dr >> 11); ++ uint32_t new_g6 = 0x3F & (dg >> 10); ++ uint32_t new_b5 = 0x1F & (db >> 11); ++ uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); + + s += 1 * 8; +- d += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22327,16 +23380,15 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++wuffs_private_impl__swizzle_bgr_565__bgra_premul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; + size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22344,13 +23396,12 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over( + // TODO: unroll. + + while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__composite_premul_premul_u32_axxx(d0, s0)); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); + + s += 1 * 4; +- d += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22358,19 +23409,16 @@ wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over( ++wuffs_private_impl__swizzle_bgr_565__bgra_premul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } +- size_t dst_len4 = dst_len / 4; +- size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22378,14 +23426,38 @@ wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over( + // TODO: unroll. + + while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0)); ++ // Extract 16-bit color components. ++ uint32_t sa = 0x101 * ((uint32_t)s[3]); ++ uint32_t sr = 0x101 * ((uint32_t)s[2]); ++ uint32_t sg = 0x101 * ((uint32_t)s[1]); ++ uint32_t sb = 0x101 * ((uint32_t)s[0]); + +- s += 1 * 1; +- d += 1 * 4; ++ // Convert from 565 color to 16-bit color. ++ uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); ++ uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); ++ uint32_t dr = (0x8421 * old_r5) >> 4; ++ uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); ++ uint32_t dg = (0x1041 * old_g6) >> 2; ++ uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); ++ uint32_t db = (0x8421 * old_b5) >> 4; ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (premul) over dst (premul). ++ dr = sr + ((dr * ia) / 0xFFFF); ++ dg = sg + ((dg * ia) / 0xFFFF); ++ db = sb + ((db * ia) / 0xFFFF); ++ ++ // Convert from 16-bit color to 565 color and combine the components. ++ uint32_t new_r5 = 0x1F & (dr >> 11); ++ uint32_t new_g6 = 0x3F & (dg >> 10); ++ uint32_t new_b5 = 0x1F & (db >> 11); ++ uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); ++ ++ s += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22393,16 +23465,15 @@ wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++wuffs_private_impl__swizzle_bgr_565__rgb(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len2 < src_len3) ? dst_len2 : src_len3; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22410,14 +23481,14 @@ wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src( + // TODO: unroll. + + while (n >= 1) { +- uint32_t s0 = wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0)); ++ uint32_t r5 = (uint32_t)(s[0] >> 3); ++ uint32_t g6 = (uint32_t)(s[1] >> 2); ++ uint32_t b5 = (uint32_t)(s[2] >> 3); ++ uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); + +- s += 1 * 4; +- d += 1 * 4; ++ s += 1 * 3; ++ d += 1 * 2; + n -= 1; + } + +@@ -22425,16 +23496,16 @@ wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over( ++wuffs_private_impl__swizzle_bgr_565__rgba_nonpremul__src( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++ size_t dst_len2 = dst_len / 2; + size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22442,14 +23513,15 @@ wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over( + // TODO: unroll. + + while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0)); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), ++ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( ++ wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))))); + + s += 1 * 4; +- d += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22457,16 +23529,16 @@ wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src( ++wuffs_private_impl__swizzle_bgr_565__rgba_nonpremul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22474,32 +23546,54 @@ wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src( + // TODO: unroll. + + while (n >= 1) { +- uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__swap_u32_argb_abgr( +- wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( +- s0))); +- +- s += 1 * 8; +- d += 1 * 4; +- n -= 1; ++ // Extract 16-bit color components. ++ uint32_t sa = 0x101 * ((uint32_t)s[3]); ++ uint32_t sb = 0x101 * ((uint32_t)s[2]); ++ uint32_t sg = 0x101 * ((uint32_t)s[1]); ++ uint32_t sr = 0x101 * ((uint32_t)s[0]); ++ ++ // Convert from 565 color to 16-bit color. ++ uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); ++ uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); ++ uint32_t dr = (0x8421 * old_r5) >> 4; ++ uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); ++ uint32_t dg = (0x1041 * old_g6) >> 2; ++ uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); ++ uint32_t db = (0x8421 * old_b5) >> 4; ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (nonpremul) over dst (premul). ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert from 16-bit color to 565 color and combine the components. ++ uint32_t new_r5 = 0x1F & (dr >> 11); ++ uint32_t new_g6 = 0x3F & (dg >> 10); ++ uint32_t new_b5 = 0x1F & (db >> 11); ++ uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); ++ ++ s += 1 * 4; ++ d += 1 * 2; ++ n -= 1; + } + + return len; + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src_over( +- uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++wuffs_private_impl__swizzle_bgr_565__rgba_premul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22507,17 +23601,14 @@ wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src_over( + // TODO: unroll. + + while (n >= 1) { +- uint64_t d0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4))); +- uint64_t s0 = wuffs_base__swap_u64_argb_abgr( +- wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u64__as__color_u32( +- wuffs_base__composite_premul_nonpremul_u64_axxx(d0, s0))); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), ++ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( ++ wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))))); + +- s += 1 * 8; +- d += 1 * 4; ++ s += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22525,47 +23616,70 @@ wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over( ++wuffs_private_impl__swizzle_bgr_565__rgba_premul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++ size_t dst_len2 = dst_len / 2; + size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + ++ // TODO: unroll. ++ + while (n >= 1) { +- uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); +- uint32_t s0 = wuffs_base__swap_u32_argb_abgr( +- wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__composite_premul_premul_u32_axxx(d0, s0)); ++ // Extract 16-bit color components. ++ uint32_t sa = 0x101 * ((uint32_t)s[3]); ++ uint32_t sb = 0x101 * ((uint32_t)s[2]); ++ uint32_t sg = 0x101 * ((uint32_t)s[1]); ++ uint32_t sr = 0x101 * ((uint32_t)s[0]); ++ ++ // Convert from 565 color to 16-bit color. ++ uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); ++ uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); ++ uint32_t dr = (0x8421 * old_r5) >> 4; ++ uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); ++ uint32_t dg = (0x1041 * old_g6) >> 2; ++ uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); ++ uint32_t db = (0x8421 * old_b5) >> 4; ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (premul) over dst (premul). ++ dr = sr + ((dr * ia) / 0xFFFF); ++ dg = sg + ((dg * ia) / 0xFFFF); ++ db = sb + ((db * ia) / 0xFFFF); ++ ++ // Convert from 16-bit color to 565 color and combine the components. ++ uint32_t new_r5 = 0x1F & (dr >> 11); ++ uint32_t new_g6 = 0x3F & (dg >> 10); ++ uint32_t new_b5 = 0x1F & (db >> 11); ++ uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); + + s += 1 * 4; +- d += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw__bgr(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len3 = src_len / 3; +- size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3; ++wuffs_private_impl__swizzle_bgr_565__y(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t len = (dst_len2 < src_len) ? dst_len2 : src_len; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22573,12 +23687,13 @@ wuffs_base__pixel_swizzler__bgrw__bgr(uint8_t* dst_ptr, + // TODO: unroll. + + while (n >= 1) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- 0xFF000000 | wuffs_base__peek_u24le__no_bounds_check(s + (0 * 3))); ++ uint32_t y5 = (uint32_t)(s[0] >> 3); ++ uint32_t y6 = (uint32_t)(s[0] >> 2); ++ uint32_t rgb_565 = (y5 << 11) | (y6 << 5) | (y5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); + +- s += 1 * 3; +- d += 1 * 4; ++ s += 1 * 1; ++ d += 1 * 2; + n -= 1; + } + +@@ -22586,15 +23701,15 @@ wuffs_base__pixel_swizzler__bgrw__bgr(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw__bgr_565(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++wuffs_private_impl__swizzle_bgr_565__y_16be(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; + size_t src_len2 = src_len / 2; +- size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; ++ size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22602,12 +23717,13 @@ wuffs_base__pixel_swizzler__bgrw__bgr_565(uint8_t* dst_ptr, + // TODO: unroll. + + while (n >= 1) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( +- wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2)))); ++ uint32_t y5 = (uint32_t)(s[0] >> 3); ++ uint32_t y6 = (uint32_t)(s[0] >> 2); ++ uint32_t rgb_565 = (y5 << 11) | (y6 << 5) | (y5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565); + + s += 1 * 2; +- d += 1 * 4; ++ d += 1 * 2; + n -= 1; + } + +@@ -22615,15 +23731,15 @@ wuffs_base__pixel_swizzler__bgrw__bgr_565(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw__bgrx(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++wuffs_private_impl__swizzle_bgr_565__ya_nonpremul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22631,100 +23747,121 @@ wuffs_base__pixel_swizzler__bgrw__bgrx(uint8_t* dst_ptr, + // TODO: unroll. + + while (n >= 1) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- 0xFF000000 | wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ uint32_t s0 = ((uint32_t)(s[1]) << 24) | ((uint32_t)(s[0]) * 0x010101); + +- s += 1 * 4; +- d += 1 * 4; ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), ++ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ s0))); ++ ++ s += 1 * 2; ++ d += 1 * 2; + n -= 1; + } + + return len; + } + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw__rgb__x86_sse42(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len3 = src_len / 3; +- size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3; ++wuffs_private_impl__swizzle_bgr_565__ya_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- __m128i shuffle = _mm_set_epi8(+0x00, +0x09, +0x0A, +0x0B, // +- +0x00, +0x06, +0x07, +0x08, // +- +0x00, +0x03, +0x04, +0x05, // +- +0x00, +0x00, +0x01, +0x02); +- __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, // +- -0x01, +0x00, +0x00, +0x00, // +- -0x01, +0x00, +0x00, +0x00, // +- -0x01, +0x00, +0x00, +0x00); ++ // TODO: unroll. + +- while (n >= 6) { +- __m128i x; +- x = _mm_lddqu_si128((const __m128i*)(const void*)s); +- x = _mm_shuffle_epi8(x, shuffle); +- x = _mm_or_si128(x, or_ff); +- _mm_storeu_si128((__m128i*)(void*)d, x); ++ while (n >= 1) { ++ // Extract 16-bit color components. ++ uint32_t sa = 0x101 * ((uint32_t)s[1]); ++ uint32_t sy = 0x101 * ((uint32_t)s[0]); + +- s += 4 * 3; +- d += 4 * 4; +- n -= 4; +- } ++ // Convert from 565 color to 16-bit color. ++ uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)); ++ uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11); ++ uint32_t dr = (0x8421 * old_r5) >> 4; ++ uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5); ++ uint32_t dg = (0x1041 * old_g6) >> 2; ++ uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0); ++ uint32_t db = (0x8421 * old_b5) >> 4; + +- while (n >= 1) { +- uint8_t b0 = s[0]; +- uint8_t b1 = s[1]; +- uint8_t b2 = s[2]; +- d[0] = b2; +- d[1] = b1; +- d[2] = b0; +- d[3] = 0xFF; ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; + +- s += 1 * 3; +- d += 1 * 4; ++ // Composite src (nonpremul) over dst (premul). ++ dr = ((sy * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sy * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sy * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert from 16-bit color to 565 color and combine the components. ++ uint32_t new_r5 = 0x1F & (dr >> 11); ++ uint32_t new_g6 = 0x3F & (dg >> 10); ++ uint32_t new_b5 = 0x1F & (db >> 11); ++ uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565); ++ ++ s += 1 * 2; ++ d += 1 * 2; + n -= 1; + } + + return len; + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw__rgb(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len3 = src_len / 3; +- size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3; ++wuffs_private_impl__swizzle_bgr_565__index__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len2 = dst_len / 2; ++ size_t len = (dst_len2 < src_len) ? dst_len2 : src_len; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + ++ const size_t loop_unroll_count = 4; ++ ++ while (n >= loop_unroll_count) { ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), wuffs_base__peek_u16le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[0] * 4))); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (1 * 2), wuffs_base__peek_u16le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[1] * 4))); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (2 * 2), wuffs_base__peek_u16le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[2] * 4))); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (3 * 2), wuffs_base__peek_u16le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[3] * 4))); ++ ++ s += loop_unroll_count * 1; ++ d += loop_unroll_count * 2; ++ n -= loop_unroll_count; ++ } ++ + while (n >= 1) { +- uint8_t b0 = s[0]; +- uint8_t b1 = s[1]; +- uint8_t b2 = s[2]; +- d[0] = b2; +- d[1] = b1; +- d[2] = b0; +- d[3] = 0xFF; ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), wuffs_base__peek_u16le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[0] * 4))); + +- s += 1 * 3; +- d += 1 * 4; ++ s += 1 * 1; ++ d += 1 * 2; + n -= 1; + } + +@@ -22732,15 +23869,19 @@ wuffs_base__pixel_swizzler__bgrw__rgb(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw__rgbx(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++wuffs_private_impl__swizzle_bgr_565__index_bgra_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len2 = dst_len / 2; ++ size_t len = (dst_len2 < src_len) ? dst_len2 : src_len; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22748,82 +23889,83 @@ wuffs_base__pixel_swizzler__bgrw__rgbx(uint8_t* dst_ptr, + // TODO: unroll. + + while (n >= 1) { +- uint8_t b0 = s[0]; +- uint8_t b1 = s[1]; +- uint8_t b2 = s[2]; +- d[0] = b2; +- d[1] = b1; +- d[2] = b0; +- d[3] = 0xFF; ++ uint32_t d0 = wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( ++ wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2))); ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ wuffs_base__poke_u16le__no_bounds_check( ++ d + (0 * 2), ++ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565( ++ wuffs_private_impl__composite_premul_nonpremul_u32_axxx(d0, s0))); + +- s += 1 * 4; +- d += 1 * 4; ++ s += 1 * 1; ++ d += 1 * 2; + n -= 1; + } + + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw_4x16le__bgr(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len3 = src_len / 3; +- size_t len = (dst_len8 < src_len3) ? dst_len8 : src_len3; ++wuffs_private_impl__swizzle_bgr_565__index_binary_alpha__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len2 = dst_len / 2; ++ size_t len = (dst_len2 < src_len) ? dst_len2 : src_len; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + ++ // TODO: unroll. ++ + while (n >= 1) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- d[0] = s0; +- d[1] = s0; +- d[2] = s1; +- d[3] = s1; +- d[4] = s2; +- d[5] = s2; +- d[6] = 0xFF; +- d[7] = 0xFF; ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ if (s0) { ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)s0); ++ } + +- s += 1 * 3; +- d += 1 * 8; ++ s += 1 * 1; ++ d += 1 * 2; + n -= 1; + } + + return len; + } + ++// -------- ++ + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw_4x16le__bgr_565(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; ++wuffs_private_impl__swizzle_bgr__bgr_565(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; + size_t src_len2 = src_len / 2; +- size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2; ++ size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + ++ // TODO: unroll. ++ + while (n >= 1) { +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), +- wuffs_base__color_u32__as__color_u64( +- wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( +- wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))))); ++ uint32_t s0 = wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( ++ wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))); ++ wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); + + s += 1 * 2; +- d += 1 * 8; ++ d += 1 * 3; + n -= 1; + } + +@@ -22831,87 +23973,46 @@ wuffs_base__pixel_swizzler__bgrw_4x16le__bgr_565(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__bgrw_4x16le__bgrx(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; ++wuffs_private_impl__swizzle_bgr__bgra_nonpremul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; + size_t src_len4 = src_len / 4; +- size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- while (n >= 1) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- d[0] = s0; +- d[1] = s0; +- d[2] = s1; +- d[3] = s1; +- d[4] = s2; +- d[5] = s2; +- d[6] = 0xFF; +- d[7] = 0xFF; +- +- s += 1 * 4; +- d += 1 * 8; +- n -= 1; +- } +- +- return len; +-} +- +-static uint64_t // +-wuffs_base__pixel_swizzler__bgrw_4x16le__rgb(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len3 = src_len / 3; +- size_t len = (dst_len8 < src_len3) ? dst_len8 : src_len3; +- uint8_t* d = dst_ptr; +- const uint8_t* s = src_ptr; +- size_t n = len; ++ // TODO: unroll. + + while (n >= 1) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- uint8_t s2 = s[2]; +- d[0] = s2; +- d[1] = s2; +- d[2] = s1; +- d[3] = s1; +- d[4] = s0; +- d[5] = s0; +- d[6] = 0xFF; +- d[7] = 0xFF; ++ uint32_t s0 = ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); + +- s += 1 * 3; +- d += 1 * 8; ++ s += 1 * 4; ++ d += 1 * 3; + n -= 1; + } + + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__rgb__bgr_565(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgr__bgra_nonpremul_4x16le__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len3 = dst_len / 3; +- size_t src_len2 = src_len / 2; +- size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -22919,13 +24020,12 @@ wuffs_base__pixel_swizzler__rgb__bgr_565(uint8_t* dst_ptr, + // TODO: unroll. + + while (n >= 1) { +- wuffs_base__poke_u24le__no_bounds_check( +- d + (0 * 3), +- wuffs_base__swap_u32_argb_abgr( +- wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( +- wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))))); ++ uint32_t s0 = ++ wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))); ++ wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); + +- s += 1 * 2; ++ s += 1 * 8; + d += 1 * 3; + n -= 1; + } +@@ -22933,154 +24033,200 @@ wuffs_base__pixel_swizzler__rgb__bgr_565(uint8_t* dst_ptr, + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src( ++wuffs_private_impl__swizzle_bgr__bgra_nonpremul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len8 = src_len / 8; +- size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; +- + size_t n = len; ++ ++ // TODO: unroll. ++ + while (n >= 1) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__color_u64__as__color_u32__swap_u32_argb_abgr( +- wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)))); ++ // Extract 16-bit color components. ++ uint32_t dr = 0x101 * ((uint32_t)d[2]); ++ uint32_t dg = 0x101 * ((uint32_t)d[1]); ++ uint32_t db = 0x101 * ((uint32_t)d[0]); ++ uint32_t sa = 0x101 * ((uint32_t)s[3]); ++ uint32_t sr = 0x101 * ((uint32_t)s[2]); ++ uint32_t sg = 0x101 * ((uint32_t)s[1]); ++ uint32_t sb = 0x101 * ((uint32_t)s[0]); + +- s += 1 * 8; +- d += 1 * 4; ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (nonpremul) over dst (premul). ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert from 16-bit color to 8-bit color. ++ d[0] = (uint8_t)(db >> 8); ++ d[1] = (uint8_t)(dg >> 8); ++ d[2] = (uint8_t)(dr >> 8); ++ ++ s += 1 * 4; ++ d += 1 * 3; + n -= 1; + } ++ + return len; + } + + static uint64_t // +-wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src_over( ++wuffs_private_impl__swizzle_bgr__bgra_nonpremul_4x16le__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- size_t dst_len4 = dst_len / 4; ++ size_t dst_len3 = dst_len / 3; + size_t src_len8 = src_len / 8; +- size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + ++ // TODO: unroll. ++ + while (n >= 1) { +- uint64_t d0 = wuffs_base__color_u32__as__color_u64( +- wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4))); +- uint64_t s0 = wuffs_base__swap_u64_argb_abgr( +- wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__color_u64__as__color_u32( +- wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0))); ++ // Extract 16-bit color components. ++ uint32_t dr = 0x101 * ((uint32_t)d[2]); ++ uint32_t dg = 0x101 * ((uint32_t)d[1]); ++ uint32_t db = 0x101 * ((uint32_t)d[0]); ++ uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6)); ++ uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4)); ++ uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2)); ++ uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0)); ++ ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (nonpremul) over dst (premul). ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert from 16-bit color to 8-bit color. ++ d[0] = (uint8_t)(db >> 8); ++ d[1] = (uint8_t)(dg >> 8); ++ d[2] = (uint8_t)(dr >> 8); + + s += 1 * 8; +- d += 1 * 4; ++ d += 1 * 3; + n -= 1; + } + + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__rgbw__bgr_565(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len4 = dst_len / 4; +- size_t src_len2 = src_len / 2; +- size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; ++wuffs_private_impl__swizzle_bgr__bgra_premul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- // TODO: unroll. +- + while (n >= 1) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), +- wuffs_base__swap_u32_argb_abgr( +- wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( +- wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))))); ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ d[0] = s0; ++ d[1] = s1; ++ d[2] = s2; + +- s += 1 * 2; +- d += 1 * 4; ++ s += 1 * 4; ++ d += 1 * 3; + n -= 1; + } + + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__xxx__index__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } ++wuffs_private_impl__swizzle_bgr__bgra_premul__src_over(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len3 = dst_len / 3; +- size_t len = (dst_len3 < src_len) ? dst_len3 : src_len; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- const size_t loop_unroll_count = 4; ++ while (n >= 1) { ++ // Extract 16-bit color components. ++ uint32_t dr = 0x101 * ((uint32_t)d[2]); ++ uint32_t dg = 0x101 * ((uint32_t)d[1]); ++ uint32_t db = 0x101 * ((uint32_t)d[0]); ++ uint32_t sa = 0x101 * ((uint32_t)s[3]); ++ uint32_t sr = 0x101 * ((uint32_t)s[2]); ++ uint32_t sg = 0x101 * ((uint32_t)s[1]); ++ uint32_t sb = 0x101 * ((uint32_t)s[0]); + +- // The comparison in the while condition is ">", not ">=", because with +- // ">=", the last 4-byte store could write past the end of the dst slice. +- // +- // Each 4-byte store writes one too many bytes, but a subsequent store +- // will overwrite that with the correct byte. There is always another +- // store, whether a 4-byte store in this loop or a 1-byte store in the +- // next loop. +- while (n > loop_unroll_count) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 3), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[0] * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (1 * 3), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[1] * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (2 * 3), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[2] * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (3 * 3), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[3] * 4))); ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; + +- s += loop_unroll_count * 1; +- d += loop_unroll_count * 3; +- n -= loop_unroll_count; ++ // Composite src (premul) over dst (premul). ++ dr = sr + ((dr * ia) / 0xFFFF); ++ dg = sg + ((dg * ia) / 0xFFFF); ++ db = sb + ((db * ia) / 0xFFFF); ++ ++ // Convert from 16-bit color to 8-bit color. ++ d[0] = (uint8_t)(db >> 8); ++ d[1] = (uint8_t)(dg >> 8); ++ d[2] = (uint8_t)(dr >> 8); ++ ++ s += 1 * 4; ++ d += 1 * 3; ++ n -= 1; + } + ++ return len; ++} ++ ++static uint64_t // ++wuffs_private_impl__swizzle_bgr__rgba_nonpremul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; ++ ++ // TODO: unroll. ++ + while (n >= 1) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); ++ uint32_t s0 = wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); + wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); + +- s += 1 * 1; ++ s += 1 * 4; + d += 1 * 3; + n -= 1; + } +@@ -23089,19 +24235,16 @@ wuffs_base__pixel_swizzler__xxx__index__src(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over( ++wuffs_private_impl__swizzle_bgr__rgba_nonpremul_4x16le__src( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } + size_t dst_len3 = dst_len / 3; +- size_t len = (dst_len3 < src_len) ? dst_len3 : src_len; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -23109,14 +24252,12 @@ wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over( + // TODO: unroll. + + while (n >= 1) { +- uint32_t d0 = +- wuffs_base__peek_u24le__no_bounds_check(d + (0 * 3)) | 0xFF000000; +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- wuffs_base__poke_u24le__no_bounds_check( +- d + (0 * 3), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0)); ++ uint32_t s0 = wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)))); ++ wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); + +- s += 1 * 1; ++ s += 1 * 8; + d += 1 * 3; + n -= 1; + } +@@ -23125,60 +24266,46 @@ wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over( ++wuffs_private_impl__swizzle_bgr__rgba_nonpremul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } + size_t dst_len3 = dst_len / 3; +- size_t len = (dst_len3 < src_len) ? dst_len3 : src_len; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- const size_t loop_unroll_count = 4; ++ // TODO: unroll. + +- while (n >= loop_unroll_count) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- if (s0) { +- wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); +- } +- uint32_t s1 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[1] * 4)); +- if (s1) { +- wuffs_base__poke_u24le__no_bounds_check(d + (1 * 3), s1); +- } +- uint32_t s2 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[2] * 4)); +- if (s2) { +- wuffs_base__poke_u24le__no_bounds_check(d + (2 * 3), s2); +- } +- uint32_t s3 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[3] * 4)); +- if (s3) { +- wuffs_base__poke_u24le__no_bounds_check(d + (3 * 3), s3); +- } ++ while (n >= 1) { ++ // Extract 16-bit color components. ++ uint32_t dr = 0x101 * ((uint32_t)d[2]); ++ uint32_t dg = 0x101 * ((uint32_t)d[1]); ++ uint32_t db = 0x101 * ((uint32_t)d[0]); ++ uint32_t sa = 0x101 * ((uint32_t)s[3]); ++ uint32_t sb = 0x101 * ((uint32_t)s[2]); ++ uint32_t sg = 0x101 * ((uint32_t)s[1]); ++ uint32_t sr = 0x101 * ((uint32_t)s[0]); + +- s += loop_unroll_count * 1; +- d += loop_unroll_count * 3; +- n -= loop_unroll_count; +- } ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; + +- while (n >= 1) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- if (s0) { +- wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); +- } ++ // Composite src (nonpremul) over dst (premul). ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; + +- s += 1 * 1; ++ // Convert from 16-bit color to 8-bit color. ++ d[0] = (uint8_t)(db >> 8); ++ d[1] = (uint8_t)(dg >> 8); ++ d[2] = (uint8_t)(dr >> 8); ++ ++ s += 1 * 4; + d += 1 * 3; + n -= 1; + } +@@ -23187,15 +24314,16 @@ wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxx__xxxx(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgr__rgba_nonpremul_4x16le__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len3 = dst_len / 3; +- size_t src_len4 = src_len / 4; +- size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; +@@ -23203,10 +24331,29 @@ wuffs_base__pixel_swizzler__xxx__xxxx(uint8_t* dst_ptr, + // TODO: unroll. + + while (n >= 1) { +- wuffs_base__poke_u24le__no_bounds_check( +- d + (0 * 3), wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ // Extract 16-bit color components. ++ uint32_t dr = 0x101 * ((uint32_t)d[2]); ++ uint32_t dg = 0x101 * ((uint32_t)d[1]); ++ uint32_t db = 0x101 * ((uint32_t)d[0]); ++ uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6)); ++ uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4)); ++ uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2)); ++ uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0)); + +- s += 1 * 4; ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (nonpremul) over dst (premul). ++ dr = ((sr * sa) + (dr * ia)) / 0xFFFF; ++ dg = ((sg * sa) + (dg * ia)) / 0xFFFF; ++ db = ((sb * sa) + (db * ia)) / 0xFFFF; ++ ++ // Convert from 16-bit color to 8-bit color. ++ d[0] = (uint8_t)(db >> 8); ++ d[1] = (uint8_t)(dg >> 8); ++ d[2] = (uint8_t)(dr >> 8); ++ ++ s += 1 * 8; + d += 1 * 3; + n -= 1; + } +@@ -23215,27 +24362,28 @@ wuffs_base__pixel_swizzler__xxx__xxxx(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxx__y(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgr__rgba_premul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len3 = dst_len / 3; +- size_t len = (dst_len3 < src_len) ? dst_len3 : src_len; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- // TODO: unroll. +- + while (n >= 1) { + uint8_t s0 = s[0]; +- d[0] = s0; +- d[1] = s0; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ d[0] = s2; ++ d[1] = s1; + d[2] = s0; + +- s += 1 * 1; ++ s += 1 * 4; + d += 1 * 3; + n -= 1; + } +@@ -23244,28 +24392,43 @@ wuffs_base__pixel_swizzler__xxx__y(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxx__y_16be(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgr__rgba_premul__src_over(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len3 = dst_len / 3; +- size_t src_len2 = src_len / 2; +- size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- // TODO: unroll. +- + while (n >= 1) { +- uint8_t s0 = s[0]; +- d[0] = s0; +- d[1] = s0; +- d[2] = s0; ++ // Extract 16-bit color components. ++ uint32_t dr = 0x101 * ((uint32_t)d[2]); ++ uint32_t dg = 0x101 * ((uint32_t)d[1]); ++ uint32_t db = 0x101 * ((uint32_t)d[0]); ++ uint32_t sa = 0x101 * ((uint32_t)s[3]); ++ uint32_t sb = 0x101 * ((uint32_t)s[2]); ++ uint32_t sg = 0x101 * ((uint32_t)s[1]); ++ uint32_t sr = 0x101 * ((uint32_t)s[0]); + +- s += 1 * 2; ++ // Calculate the inverse of the src-alpha: how much of the dst to keep. ++ uint32_t ia = 0xFFFF - sa; ++ ++ // Composite src (premul) over dst (premul). ++ dr = sr + ((dr * ia) / 0xFFFF); ++ dg = sg + ((dg * ia) / 0xFFFF); ++ db = sb + ((db * ia) / 0xFFFF); ++ ++ // Convert from 16-bit color to 8-bit color. ++ d[0] = (uint8_t)(db >> 8); ++ d[1] = (uint8_t)(dg >> 8); ++ d[2] = (uint8_t)(dr >> 8); ++ ++ s += 1 * 4; + d += 1 * 3; + n -= 1; + } +@@ -23273,114 +24436,63 @@ wuffs_base__pixel_swizzler__xxx__y_16be(uint8_t* dst_ptr, + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__xxxx__index__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } +- size_t dst_len4 = dst_len / 4; +- size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++wuffs_private_impl__swizzle_bgr__rgbx(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- const size_t loop_unroll_count = 4; +- +- while (n >= loop_unroll_count) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[0] * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (1 * 4), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[1] * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (2 * 4), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[2] * 4))); +- wuffs_base__poke_u32le__no_bounds_check( +- d + (3 * 4), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[3] * 4))); +- +- s += loop_unroll_count * 1; +- d += loop_unroll_count * 4; +- n -= loop_unroll_count; +- } ++ // TODO: unroll. + + while (n >= 1) { +- wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[0] * 4))); ++ uint8_t b0 = s[0]; ++ uint8_t b1 = s[1]; ++ uint8_t b2 = s[2]; ++ d[0] = b2; ++ d[1] = b1; ++ d[2] = b0; + +- s += 1 * 1; +- d += 1 * 4; ++ s += 1 * 4; ++ d += 1 * 3; + n -= 1; + } + + return len; + } + ++// -------- ++ + static uint64_t // +-wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over( ++wuffs_private_impl__swizzle_bgra_nonpremul__bgra_nonpremul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } + size_t dst_len4 = dst_len / 4; +- size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + +- const size_t loop_unroll_count = 4; +- +- while (n >= loop_unroll_count) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- if (s0) { +- wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0); +- } +- uint32_t s1 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[1] * 4)); +- if (s1) { +- wuffs_base__poke_u32le__no_bounds_check(d + (1 * 4), s1); +- } +- uint32_t s2 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[2] * 4)); +- if (s2) { +- wuffs_base__poke_u32le__no_bounds_check(d + (2 * 4), s2); +- } +- uint32_t s3 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[3] * 4)); +- if (s3) { +- wuffs_base__poke_u32le__no_bounds_check(d + (3 * 4), s3); +- } +- +- s += loop_unroll_count * 1; +- d += loop_unroll_count * 4; +- n -= loop_unroll_count; +- } +- + while (n >= 1) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- if (s0) { +- wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0); +- } ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u32_axxx(d0, s0)); + +- s += 1 * 1; ++ s += 1 * 4; + d += 1 * 4; + n -= 1; + } +@@ -23388,75 +24500,88 @@ wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over( + return len; + } + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + static uint64_t // +-wuffs_base__pixel_swizzler__xxxx__y__x86_sse42(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgra_nonpremul__bgra_nonpremul_4x16le__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len4 = dst_len / 4; +- size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; ++ + size_t n = len; ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), wuffs_base__color_u64__as__color_u32( ++ wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)))); + +- __m128i shuffle = _mm_set_epi8(+0x03, +0x03, +0x03, +0x03, // +- +0x02, +0x02, +0x02, +0x02, // +- +0x01, +0x01, +0x01, +0x01, // +- +0x00, +0x00, +0x00, +0x00); +- __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, // +- -0x01, +0x00, +0x00, +0x00, // +- -0x01, +0x00, +0x00, +0x00, // +- -0x01, +0x00, +0x00, +0x00); +- +- while (n >= 4) { +- __m128i x; +- x = _mm_cvtsi32_si128((int)(wuffs_base__peek_u32le__no_bounds_check(s))); +- x = _mm_shuffle_epi8(x, shuffle); +- x = _mm_or_si128(x, or_ff); +- _mm_storeu_si128((__m128i*)(void*)d, x); +- +- s += 4 * 1; +- d += 4 * 4; +- n -= 4; ++ s += 1 * 8; ++ d += 1 * 4; ++ n -= 1; + } ++ return len; ++} ++ ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul__bgra_nonpremul_4x16le__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + + while (n >= 1) { ++ uint64_t d0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4))); ++ uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); + wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0])); ++ d + (0 * 4), ++ wuffs_base__color_u64__as__color_u32( ++ wuffs_private_impl__composite_nonpremul_nonpremul_u64_axxx(d0, ++ s0))); + +- s += 1 * 1; ++ s += 1 * 8; + d += 1 * 4; + n -= 1; + } + + return len; + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + + static uint64_t // +-wuffs_base__pixel_swizzler__xxxx__y(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgra_nonpremul__bgra_premul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len4 = dst_len / 4; +- size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + + while (n >= 1) { ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); + wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0])); ++ d + (0 * 4), ++ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(s0)); + +- s += 1 * 1; ++ s += 1 * 4; + d += 1 * 4; + n -= 1; + } +@@ -23465,24 +24590,28 @@ wuffs_base__pixel_swizzler__xxxx__y(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxxx__y_16be(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgra_nonpremul__bgra_premul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + size_t dst_len4 = dst_len / 4; +- size_t src_len2 = src_len / 2; +- size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + + while (n >= 1) { ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); + wuffs_base__poke_u32le__no_bounds_check( +- d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0])); ++ d + (0 * 4), ++ wuffs_private_impl__composite_nonpremul_premul_u32_axxx(d0, s0)); + +- s += 1 * 2; ++ s += 1 * 4; + d += 1 * 4; + n -= 1; + } +@@ -23490,33 +24619,36 @@ wuffs_base__pixel_swizzler__xxxx__y_16be(uint8_t* dst_ptr, + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__xxxxxxxx__index__src(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgra_nonpremul__index_bgra_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { + if (dst_palette_len != + WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { + return 0; + } +- size_t dst_len8 = dst_len / 8; +- size_t len = (dst_len8 < src_len) ? dst_len8 : src_len; ++ size_t dst_len4 = dst_len / 4; ++ size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + ++ // TODO: unroll. ++ + while (n >= 1) { +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), wuffs_base__color_u32__as__color_u64( +- wuffs_base__peek_u32le__no_bounds_check( +- dst_palette_ptr + ((size_t)s[0] * 4)))); ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u32_axxx(d0, s0)); + + s += 1 * 1; +- d += 1 * 8; ++ d += 1 * 4; + n -= 1; + } + +@@ -23524,33 +24656,30 @@ wuffs_base__pixel_swizzler__xxxxxxxx__index__src(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxxxxxxx__index_binary_alpha__src_over( ++wuffs_private_impl__swizzle_bgra_nonpremul__rgba_nonpremul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, + const uint8_t* src_ptr, + size_t src_len) { +- if (dst_palette_len != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return 0; +- } +- size_t dst_len8 = dst_len / 8; +- size_t len = (dst_len8 < src_len) ? dst_len8 : src_len; ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + + while (n >= 1) { +- uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + +- ((size_t)s[0] * 4)); +- if (s0) { +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), wuffs_base__color_u32__as__color_u64(s0)); +- } ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u32_axxx(d0, s0)); + +- s += 1 * 1; +- d += 1 * 8; ++ s += 1 * 4; ++ d += 1 * 4; + n -= 1; + } + +@@ -23558,24 +24687,29 @@ wuffs_base__pixel_swizzler__xxxxxxxx__index_binary_alpha__src_over( + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxxxxxxx__y(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t len = (dst_len8 < src_len) ? dst_len8 : src_len; ++wuffs_private_impl__swizzle_bgra_nonpremul__rgba_premul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + + while (n >= 1) { +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), 0xFFFF000000000000 | (0x010101010101 * (uint64_t)s[0])); ++ uint32_t s0 = wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(s0)); + +- s += 1 * 1; +- d += 1 * 8; ++ s += 1 * 4; ++ d += 1 * 4; + n -= 1; + } + +@@ -23583,53 +24717,59 @@ wuffs_base__pixel_swizzler__xxxxxxxx__y(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__xxxxxxxx__y_16be(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len8 = dst_len / 8; +- size_t src_len2 = src_len / 2; +- size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2; ++wuffs_private_impl__swizzle_bgra_nonpremul__rgba_premul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + + while (n >= 1) { +- uint64_t s0 = +- ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(s + (0 * 2)))); +- wuffs_base__poke_u64le__no_bounds_check( +- d + (0 * 8), 0xFFFF000000000000 | (0x000100010001 * s0)); ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_nonpremul_premul_u32_axxx(d0, s0)); + +- s += 1 * 2; +- d += 1 * 8; ++ s += 1 * 4; ++ d += 1 * 4; + n -= 1; + } + + return len; + } + +-// -------- +- + static uint64_t // +-wuffs_base__pixel_swizzler__y__y_16be(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { ++wuffs_private_impl__swizzle_bgra_nonpremul__ya_nonpremul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; + size_t src_len2 = src_len / 2; +- size_t len = (dst_len < src_len2) ? dst_len : src_len2; ++ size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + ++ // TODO: unroll. ++ + while (n >= 1) { +- d[0] = s[0]; ++ uint32_t s0 = ((uint32_t)(s[1]) << 24) | ((uint32_t)(s[0]) * 0x010101); ++ wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0); + + s += 1 * 2; +- d += 1 * 1; ++ d += 1 * 4; + n -= 1; + } + +@@ -23637,27 +24777,31 @@ wuffs_base__pixel_swizzler__y__y_16be(uint8_t* dst_ptr, + } + + static uint64_t // +-wuffs_base__pixel_swizzler__y_16le__y_16be(uint8_t* dst_ptr, +- size_t dst_len, +- uint8_t* dst_palette_ptr, +- size_t dst_palette_len, +- const uint8_t* src_ptr, +- size_t src_len) { +- size_t dst_len2 = dst_len / 2; ++wuffs_private_impl__swizzle_bgra_nonpremul__ya_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; + size_t src_len2 = src_len / 2; +- size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; ++ size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; + uint8_t* d = dst_ptr; + const uint8_t* s = src_ptr; + size_t n = len; + ++ // TODO: unroll. ++ + while (n >= 1) { +- uint8_t s0 = s[0]; +- uint8_t s1 = s[1]; +- d[0] = s1; +- d[1] = s0; ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = ((uint32_t)(s[1]) << 24) | ((uint32_t)(s[0]) * 0x010101); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u32_axxx(d0, s0)); + + s += 1 * 2; +- d += 1 * 2; ++ d += 1 * 4; + n -= 1; + } + +@@ -23667,6862 +24811,6000 @@ wuffs_base__pixel_swizzler__y_16le__y_16be(uint8_t* dst_ptr, + // -------- + + static uint64_t // +-wuffs_base__pixel_swizzler__transparent_black_src( ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_nonpremul__src( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, +- uint64_t num_pixels, +- uint32_t dst_pixfmt_bytes_per_pixel) { +- uint64_t n = ((uint64_t)dst_len) / dst_pixfmt_bytes_per_pixel; +- if (n > num_pixels) { +- n = num_pixels; ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ ++ size_t n = len; ++ while (n >= 1) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ uint8_t s3 = s[3]; ++ d[0] = s0; ++ d[1] = s0; ++ d[2] = s1; ++ d[3] = s1; ++ d[4] = s2; ++ d[5] = s2; ++ d[6] = s3; ++ d[7] = s3; ++ ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; + } +- memset(dst_ptr, 0, ((size_t)(n * dst_pixfmt_bytes_per_pixel))); +- return n; ++ return len; + } + + static uint64_t // +-wuffs_base__pixel_swizzler__transparent_black_src_over( ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_nonpremul__src_over( + uint8_t* dst_ptr, + size_t dst_len, + uint8_t* dst_palette_ptr, + size_t dst_palette_len, +- uint64_t num_pixels, +- uint32_t dst_pixfmt_bytes_per_pixel) { +- uint64_t n = ((uint64_t)dst_len) / dst_pixfmt_bytes_per_pixel; +- if (n > num_pixels) { +- n = num_pixels; ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); ++ uint64_t s0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); ++ ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; + } +- return n; ++ return len; + } + +-// -------- ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_nonpremul_4x16le__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len8 < src_len8) ? dst_len8 : src_len8; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__y(wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__Y: +- return wuffs_base__pixel_swizzler__copy_1_1; ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); ++ uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- return wuffs_base__pixel_swizzler__bgr_565__y; ++ s += 1 * 8; ++ d += 1 * 8; ++ n -= 1; ++ } ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- return wuffs_base__pixel_swizzler__xxx__y; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_premul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- if (wuffs_base__cpu_arch__have_x86_sse42()) { +- return wuffs_base__pixel_swizzler__xxxx__y__x86_sse42; +- } +-#endif +- return wuffs_base__pixel_swizzler__xxxx__y; ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t s0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); ++ wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE: +- return wuffs_base__pixel_swizzler__xxxxxxxx__y; ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; + } +- return NULL; ++ return len; + } + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__y_16be(wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__Y: +- return wuffs_base__pixel_swizzler__y__y_16be; +- +- case WUFFS_BASE__PIXEL_FORMAT__Y_16LE: +- return wuffs_base__pixel_swizzler__y_16le__y_16be; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_premul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +- case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: +- return wuffs_base__pixel_swizzler__copy_2_2; ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); ++ uint64_t s0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), ++ wuffs_private_impl__composite_nonpremul_premul_u64_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- return wuffs_base__pixel_swizzler__bgr_565__y_16be; ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; ++ } ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- return wuffs_base__pixel_swizzler__xxx__y_16be; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__index_bgra_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len8 = dst_len / 8; ++ size_t len = (dst_len8 < src_len) ? dst_len8 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- return wuffs_base__pixel_swizzler__xxxx__y_16be; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); ++ uint64_t s0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4))); ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE: +- return wuffs_base__pixel_swizzler__xxxxxxxx__y_16be; ++ s += 1 * 1; ++ d += 1 * 8; ++ n -= 1; + } +- return NULL; +-} + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__indexed__bgra_nonpremul( +- wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__copy_1_1; +- } +- return NULL; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- if (wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888( +- dst_palette.ptr, dst_palette.len, src_palette.ptr, +- src_palette.len, true) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__bgr_565__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__bgr_565__index_bgra_nonpremul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__rgba_nonpremul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- if (wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__xxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over; +- } +- return NULL; ++ size_t n = len; ++ while (n >= 1) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ uint8_t s3 = s[3]; ++ d[0] = s2; ++ d[1] = s2; ++ d[2] = s1; ++ d[3] = s1; ++ d[4] = s0; ++ d[5] = s0; ++ d[6] = s3; ++ d[7] = s3; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__xxxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over; +- } +- return NULL; +- +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__xxxxxxxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__index_bgra_nonpremul__src_over; +- } +- return NULL; +- +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- if (wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__xxxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over; +- } +- return NULL; +- +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- if (wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__xxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over; +- } +- return NULL; ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; ++ } ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__xxxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__rgba_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- if (wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__xxxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- return wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over; +- } +- return NULL; ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); ++ uint64_t s0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- // TODO. +- break; ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; + } +- return NULL; ++ return len; + } + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__indexed__bgra_binary( +- wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__copy_1_1; +- } +- return NULL; +- +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- if (wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888( +- dst_palette.ptr, dst_palette.len, src_palette.ptr, +- src_palette.len, false) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr_565__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr_565__index_binary_alpha__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__rgba_premul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__xxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over; +- } +- return NULL; ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t s0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul( ++ wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))))); ++ wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__xxxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over; +- } +- return NULL; ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; ++ } ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: +- if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) != +- WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__xxxxxxxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__xxxxxxxx__index_binary_alpha__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__rgba_premul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__xxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over; +- } +- return NULL; ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); ++ uint64_t s0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))); ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), ++ wuffs_private_impl__composite_nonpremul_premul_u64_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx( +- dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, +- src_palette.len) != +- (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { +- return NULL; +- } +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__xxxx__index__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over; +- } +- return NULL; ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; + } +- return NULL; ++ return len; + } + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__bgr_565( +- wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- return wuffs_base__pixel_swizzler__copy_2_2; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__ya_nonpremul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- return wuffs_base__pixel_swizzler__bgr__bgr_565; ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t s0 = ((uint64_t)(s[1]) * 0x0101000000000000) | ++ ((uint64_t)(s[0]) * 0x0000010101010101); ++ wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- return wuffs_base__pixel_swizzler__bgrw__bgr_565; ++ s += 1 * 2; ++ d += 1 * 8; ++ n -= 1; ++ } ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: +- return wuffs_base__pixel_swizzler__bgrw_4x16le__bgr_565; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__ya_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- return wuffs_base__pixel_swizzler__rgb__bgr_565; ++ size_t n = len; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8)); ++ uint64_t s0 = ((uint64_t)(s[1]) * 0x0101000000000000) | ++ ((uint64_t)(s[0]) * 0x0000010101010101); ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), ++ wuffs_private_impl__composite_nonpremul_nonpremul_u64_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- return wuffs_base__pixel_swizzler__rgbw__bgr_565; ++ s += 1 * 2; ++ d += 1 * 8; ++ n -= 1; + } +- return NULL; ++ return len; + } + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__bgr(wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- return wuffs_base__pixel_swizzler__bgr_565__bgr; +- +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- return wuffs_base__pixel_swizzler__copy_3_3; ++// -------- + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- return wuffs_base__pixel_swizzler__bgrw__bgr; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: +- return wuffs_base__pixel_swizzler__bgrw_4x16le__bgr; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- return wuffs_base__pixel_swizzler__swap_rgb_bgr; ++ while (n >= 1) { ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- if (wuffs_base__cpu_arch__have_x86_sse42()) { +- return wuffs_base__pixel_swizzler__bgrw__rgb__x86_sse42; +- } +-#endif +- return wuffs_base__pixel_swizzler__bgrw__rgb; ++ s += 1 * 4; ++ d += 1 * 4; ++ n -= 1; + } +- return NULL; +-} + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__bgra_nonpremul( +- wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src_over; +- } +- return NULL; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul_4x16le__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__copy_4_4; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over; +- } +- return NULL; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over; +- } +- return NULL; ++ s += 1 * 8; ++ d += 1 * 4; ++ n -= 1; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- // TODO. +- break; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- if (wuffs_base__cpu_arch__have_x86_sse42()) { +- return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__x86_sse42; +- } +-#endif +- return wuffs_base__pixel_swizzler__swap_rgbx_bgrx; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over; +- } +- return NULL; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_premul_nonpremul_u32_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- // TODO. +- break; ++ s += 1 * 4; ++ d += 1 * 4; ++ n -= 1; + } +- return NULL; ++ ++ return len; + } + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__bgra_nonpremul_4x16le( +- wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul_4x16le__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src_over; +- } +- return NULL; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4))); ++ uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_base__color_u64__as__color_u32( ++ wuffs_private_impl__composite_premul_nonpremul_u64_axxx(d0, s0))); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__copy_8_8; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul_4x16le__src_over; +- } +- return NULL; +- +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src_over; +- } +- return NULL; ++ s += 1 * 8; ++ d += 1 * 4; ++ n -= 1; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- // TODO. +- break; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul_4x16le__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul_4x16le__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__bgra_premul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src_over; +- } +- break; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_premul_premul_u32_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- // TODO. +- break; ++ s += 1 * 4; ++ d += 1 * 4; ++ n -= 1; + } +- return NULL; +-} + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__bgra_premul( +- wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src_over; +- } +- return NULL; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__bgra_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__bgra_premul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__index_bgra_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len4 = dst_len / 4; ++ size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over; +- } +- return NULL; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_premul_nonpremul_u32_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__copy_4_4; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over; +- } +- return NULL; ++ s += 1 * 1; ++ d += 1 * 4; ++ n -= 1; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__rgba_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__rgba_premul__src_over; +- } +- return NULL; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- if (wuffs_base__cpu_arch__have_x86_sse42()) { +- return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__x86_sse42; +- } +-#endif +- return wuffs_base__pixel_swizzler__swap_rgbx_bgrx; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over; +- } +- return NULL; +- } +- return NULL; +-} ++ // TODO: unroll. + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__bgrx(wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- return wuffs_base__pixel_swizzler__bgr_565__bgrx; ++ while (n >= 1) { ++ uint32_t s0 = wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- return wuffs_base__pixel_swizzler__xxx__xxxx; ++ s += 1 * 4; ++ d += 1 * 4; ++ n -= 1; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- return wuffs_base__pixel_swizzler__bgrw__bgrx; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- return wuffs_base__pixel_swizzler__bgrw_4x16le__bgrx; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- return wuffs_base__pixel_swizzler__copy_4_4; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- return wuffs_base__pixel_swizzler__bgr__rgbx; ++ while (n >= 1) { ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_premul_nonpremul_u32_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- return wuffs_base__pixel_swizzler__bgrw__rgbx; ++ s += 1 * 4; ++ d += 1 * 4; ++ n -= 1; + } +- return NULL; +-} + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__rgb(wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- return wuffs_base__pixel_swizzler__bgr_565__rgb; +- +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- return wuffs_base__pixel_swizzler__swap_rgb_bgr; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- if (wuffs_base__cpu_arch__have_x86_sse42()) { +- return wuffs_base__pixel_swizzler__bgrw__rgb__x86_sse42; +- } +-#endif +- return wuffs_base__pixel_swizzler__bgrw__rgb; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul_4x16le__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- return wuffs_base__pixel_swizzler__bgrw_4x16le__rgb; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- return wuffs_base__pixel_swizzler__copy_3_3; ++ while (n >= 1) { ++ uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul( ++ s0))); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- return wuffs_base__pixel_swizzler__bgrw__bgr; ++ s += 1 * 8; ++ d += 1 * 4; ++ n -= 1; + } +- return NULL; +-} +- +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__rgba_nonpremul( +- wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src_over; +- } +- return NULL; + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src_over; +- } +- return NULL; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- if (wuffs_base__cpu_arch__have_x86_sse42()) { +- return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__x86_sse42; +- } +-#endif +- return wuffs_base__pixel_swizzler__swap_rgbx_bgrx; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul_4x16le__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src_over; +- } +- return NULL; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4))); ++ uint64_t s0 = wuffs_private_impl__swap_u64_argb_abgr( ++ wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_base__color_u64__as__color_u32( ++ wuffs_private_impl__composite_premul_nonpremul_u64_axxx(d0, s0))); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- // TODO. +- break; ++ s += 1 * 8; ++ d += 1 * 4; ++ n -= 1; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src_over; +- } +- return NULL; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__copy_4_4; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__rgba_premul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_premul_premul_u32_axxx(d0, s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- // TODO. +- break; ++ s += 1 * 4; ++ d += 1 * 4; ++ n -= 1; + } +- return NULL; ++ ++ return len; + } + +-static wuffs_base__pixel_swizzler__func // +-wuffs_base__pixel_swizzler__prepare__rgba_premul( +- wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- switch (dst_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__ya_nonpremul__src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__rgba_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__rgba_premul__src_over; +- } +- return NULL; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint32_t s0 = ((uint32_t)(s[1]) << 24) | ((uint32_t)(s[0]) * 0x010101); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0)); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src_over; +- } +- return NULL; ++ s += 1 * 2; ++ d += 1 * 4; ++ n -= 1; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- if (wuffs_base__cpu_arch__have_x86_sse42()) { +- return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__x86_sse42; +- } +-#endif +- return wuffs_base__pixel_swizzler__swap_rgbx_bgrx; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over; +- } +- return NULL; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgr__bgra_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgr__bgra_premul__src_over; +- } +- return NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_bgra_premul__ya_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over; +- } +- return NULL; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- return wuffs_base__pixel_swizzler__copy_4_4; +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- return wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over; +- } +- return NULL; ++ while (n >= 1) { ++ uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)); ++ uint32_t s0 = ((uint32_t)(s[1]) << 24) | ((uint32_t)(s[0]) * 0x010101); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__composite_premul_nonpremul_u32_axxx(d0, s0)); ++ ++ s += 1 * 2; ++ d += 1 * 4; ++ n -= 1; + } +- return NULL; ++ ++ return len; + } + + // -------- + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status // +-wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_format dst_pixfmt, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__pixel_format src_pixfmt, +- wuffs_base__slice_u8 src_palette, +- wuffs_base__pixel_blend blend) { +- if (!p) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- p->private_impl.func = NULL; +- p->private_impl.transparent_black_func = NULL; +- p->private_impl.dst_pixfmt_bytes_per_pixel = 0; +- p->private_impl.src_pixfmt_bytes_per_pixel = 0; ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__bgr(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- wuffs_base__pixel_swizzler__func func = NULL; +- wuffs_base__pixel_swizzler__transparent_black_func transparent_black_func = +- NULL; ++ // TODO: unroll. + +- uint32_t dst_pixfmt_bits_per_pixel = +- wuffs_base__pixel_format__bits_per_pixel(&dst_pixfmt); +- if ((dst_pixfmt_bits_per_pixel == 0) || +- ((dst_pixfmt_bits_per_pixel & 7) != 0)) { +- return wuffs_base__make_status( +- wuffs_base__error__unsupported_pixel_swizzler_option); +- } ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ 0xFF000000 | wuffs_base__peek_u24le__no_bounds_check(s + (0 * 3))); + +- uint32_t src_pixfmt_bits_per_pixel = +- wuffs_base__pixel_format__bits_per_pixel(&src_pixfmt); +- if ((src_pixfmt_bits_per_pixel == 0) || +- ((src_pixfmt_bits_per_pixel & 7) != 0)) { +- return wuffs_base__make_status( +- wuffs_base__error__unsupported_pixel_swizzler_option); ++ s += 1 * 3; ++ d += 1 * 4; ++ n -= 1; + } + +- // TODO: support many more formats. +- +- switch (blend) { +- case WUFFS_BASE__PIXEL_BLEND__SRC: +- transparent_black_func = +- wuffs_base__pixel_swizzler__transparent_black_src; +- break; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: +- transparent_black_func = +- wuffs_base__pixel_swizzler__transparent_black_src_over; +- break; +- } ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__bgr_565(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- switch (src_pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__Y: +- func = wuffs_base__pixel_swizzler__prepare__y(p, dst_pixfmt, dst_palette, +- src_palette, blend); +- break; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: +- func = wuffs_base__pixel_swizzler__prepare__y_16be( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( ++ wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2)))); + +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: +- func = wuffs_base__pixel_swizzler__prepare__indexed__bgra_nonpremul( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ s += 1 * 2; ++ d += 1 * 4; ++ n -= 1; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: +- func = wuffs_base__pixel_swizzler__prepare__indexed__bgra_binary( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- func = wuffs_base__pixel_swizzler__prepare__bgr_565( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__bgrx(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- func = wuffs_base__pixel_swizzler__prepare__bgr( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ // TODO: unroll. + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- func = wuffs_base__pixel_swizzler__prepare__bgra_nonpremul( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ 0xFF000000 | wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- func = wuffs_base__pixel_swizzler__prepare__bgra_nonpremul_4x16le( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ s += 1 * 4; ++ d += 1 * 4; ++ n -= 1; ++ } + +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- func = wuffs_base__pixel_swizzler__prepare__bgra_premul( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ return len; ++} + +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- func = wuffs_base__pixel_swizzler__prepare__bgrx( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__bgr__x86_sse42(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- func = wuffs_base__pixel_swizzler__prepare__rgb( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ __m128i shuffle = _mm_set_epi8(+0x00, +0x0B, +0x0A, +0x09, // ++ +0x00, +0x08, +0x07, +0x06, // ++ +0x00, +0x05, +0x04, +0x03, // ++ +0x00, +0x02, +0x01, +0x00); ++ __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- func = wuffs_base__pixel_swizzler__prepare__rgba_nonpremul( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ while (n >= 6) { ++ __m128i x; ++ x = _mm_lddqu_si128((const __m128i*)(const void*)s); ++ x = _mm_shuffle_epi8(x, shuffle); ++ x = _mm_or_si128(x, or_ff); ++ _mm_storeu_si128((__m128i*)(void*)d, x); + +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- func = wuffs_base__pixel_swizzler__prepare__rgba_premul( +- p, dst_pixfmt, dst_palette, src_palette, blend); +- break; ++ s += 4 * 3; ++ d += 4 * 4; ++ n -= 4; + } + +- p->private_impl.func = func; +- p->private_impl.transparent_black_func = transparent_black_func; +- p->private_impl.dst_pixfmt_bytes_per_pixel = dst_pixfmt_bits_per_pixel / 8; +- p->private_impl.src_pixfmt_bytes_per_pixel = src_pixfmt_bits_per_pixel / 8; +- return wuffs_base__make_status( +- func ? NULL : wuffs_base__error__unsupported_pixel_swizzler_option); +-} ++ while (n >= 1) { ++ uint8_t b0 = s[0]; ++ uint8_t b1 = s[1]; ++ uint8_t b2 = s[2]; ++ d[0] = b0; ++ d[1] = b1; ++ d[2] = b2; ++ d[3] = 0xFF; + +-WUFFS_BASE__MAYBE_STATIC uint64_t // +-wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader( +- const wuffs_base__pixel_swizzler* p, +- uint32_t up_to_num_pixels, +- wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 dst_palette, +- const uint8_t** ptr_iop_r, +- const uint8_t* io2_r) { +- if (p && p->private_impl.func) { +- const uint8_t* iop_r = *ptr_iop_r; +- uint64_t src_len = wuffs_base__u64__min( +- ((uint64_t)up_to_num_pixels) * +- ((uint64_t)p->private_impl.src_pixfmt_bytes_per_pixel), +- ((uint64_t)(io2_r - iop_r))); +- uint64_t n = +- (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr, +- dst_palette.len, iop_r, (size_t)src_len); +- *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel; +- return n; ++ s += 1 * 3; ++ d += 1 * 4; ++ n -= 1; + } +- return 0; +-} + +-WUFFS_BASE__MAYBE_STATIC uint64_t // +-wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( +- const wuffs_base__pixel_swizzler* p, +- wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 dst_palette, +- const uint8_t** ptr_iop_r, +- const uint8_t* io2_r) { +- if (p && p->private_impl.func) { +- const uint8_t* iop_r = *ptr_iop_r; +- uint64_t src_len = ((uint64_t)(io2_r - iop_r)); +- uint64_t n = +- (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr, +- dst_palette.len, iop_r, (size_t)src_len); +- *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel; +- return n; +- } +- return 0; ++ return len; + } + +-WUFFS_BASE__MAYBE_STATIC uint64_t // +-wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice( +- const wuffs_base__pixel_swizzler* p, +- wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 dst_palette, +- wuffs_base__slice_u8 src) { +- if (p && p->private_impl.func) { +- return (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr, +- dst_palette.len, src.ptr, src.len); +- } +- return 0; +-} ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__rgb__x86_sse42(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +-WUFFS_BASE__MAYBE_STATIC uint64_t // +-wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black( +- const wuffs_base__pixel_swizzler* p, +- wuffs_base__slice_u8 dst, +- wuffs_base__slice_u8 dst_palette, +- uint64_t num_pixels) { +- if (p && p->private_impl.transparent_black_func) { +- return (*p->private_impl.transparent_black_func)( +- dst.ptr, dst.len, dst_palette.ptr, dst_palette.len, num_pixels, +- p->private_impl.dst_pixfmt_bytes_per_pixel); ++ __m128i shuffle = _mm_set_epi8(+0x00, +0x09, +0x0A, +0x0B, // ++ +0x00, +0x06, +0x07, +0x08, // ++ +0x00, +0x03, +0x04, +0x05, // ++ +0x00, +0x00, +0x01, +0x02); ++ __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00); ++ ++ while (n >= 6) { ++ __m128i x; ++ x = _mm_lddqu_si128((const __m128i*)(const void*)s); ++ x = _mm_shuffle_epi8(x, shuffle); ++ x = _mm_or_si128(x, or_ff); ++ _mm_storeu_si128((__m128i*)(void*)d, x); ++ ++ s += 4 * 3; ++ d += 4 * 4; ++ n -= 4; + } +- return 0; +-} + +-// -------- ++ while (n >= 1) { ++ uint8_t b0 = s[0]; ++ uint8_t b1 = s[1]; ++ uint8_t b2 = s[2]; ++ d[0] = b2; ++ d[1] = b1; ++ d[2] = b0; ++ d[3] = 0xFF; + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_bgrx_x86_avx2( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2); ++ s += 1 * 3; ++ d += 1 * 4; ++ n -= 1; ++ } + +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_rgbx_x86_avx2( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2); ++ return len; ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-#if defined(__GNUC__) && !defined(__clang__) +-// No-op. +-#else +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2v2_triangle_x86_avx2( +- uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor, +- size_t src_len, +- uint32_t h1v2_bias_ignored, +- bool first_column, +- bool last_column); +-#endif +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_64) ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__rgb(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +-// -------- ++ while (n >= 1) { ++ uint8_t b0 = s[0]; ++ uint8_t b1 = s[1]; ++ uint8_t b2 = s[2]; ++ d[0] = b2; ++ d[1] = b1; ++ d[2] = b0; ++ d[3] = 0xFF; + +-static inline uint32_t // +-wuffs_base__u32__max_of_4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { +- return wuffs_base__u32__max( // +- wuffs_base__u32__max(a, b), // +- wuffs_base__u32__max(c, d)); +-} ++ s += 1 * 3; ++ d += 1 * 4; ++ n -= 1; ++ } + +-static inline uint32_t // +-wuffs_base__u32__min_of_5(uint32_t a, +- uint32_t b, +- uint32_t c, +- uint32_t d, +- uint32_t e) { +- return wuffs_base__u32__min( // +- wuffs_base__u32__min( // +- wuffs_base__u32__min(a, b), // +- wuffs_base__u32__min(c, d)), // +- e); ++ return len; + } + +-// -------- ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw__rgbx(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +-typedef void (*wuffs_base__pixel_swizzler__swizzle_ycc__convert_4_func)( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2, +- const uint8_t* up3); ++ // TODO: unroll. + +-static void // +-wuffs_base__pixel_swizzler__swizzle_cmyk__convert_4_general( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2, +- const uint8_t* up3) { +- for (; x < x_end; x++) { +- // It's called CMYK but, but for Adobe CMYK JPEG images in practice, it's +- // RGBW: 0xFFu means no ink instead of full ink. Note that a double +- // inversion is a no-op, so inversions might be implicit in the code below. +- uint32_t r = ((uint32_t)(*up0++)); +- uint32_t g = ((uint32_t)(*up1++)); +- uint32_t b = ((uint32_t)(*up2++)); +- uint32_t w = ((uint32_t)(*up3++)); +- r = ((r * w) + 0x7Fu) / 0xFFu; +- g = ((g * w) + 0x7Fu) / 0xFFu; +- b = ((b * w) + 0x7Fu) / 0xFFu; +- wuffs_base__pixel_buffer__set_color_u32_at( +- dst, x, y, 0xFF000000u | (r << 16u) | (g << 8u) | (b << 0u)); +- } +-} ++ while (n >= 1) { ++ uint8_t b0 = s[0]; ++ uint8_t b1 = s[1]; ++ uint8_t b2 = s[2]; ++ d[0] = b2; ++ d[1] = b1; ++ d[2] = b0; ++ d[3] = 0xFF; + +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycck__convert_4_general( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2, +- const uint8_t* up3) { +- for (; x < x_end; x++) { +- // We invert once again: 0xFFu means no ink instead of full ink. +- uint32_t color = // +- wuffs_base__color_ycc__as__color_u32( // +- *up0++, *up1++, *up2++); +- uint32_t r = 0xFFu - (0xFFu & (color >> 16u)); +- uint32_t g = 0xFFu - (0xFFu & (color >> 8u)); +- uint32_t b = 0xFFu - (0xFFu & (color >> 0u)); +- uint32_t w = ((uint32_t)(*up3++)); +- r = ((r * w) + 0x7Fu) / 0xFFu; +- g = ((g * w) + 0x7Fu) / 0xFFu; +- b = ((b * w) + 0x7Fu) / 0xFFu; +- wuffs_base__pixel_buffer__set_color_u32_at( +- dst, x, y, 0xFF000000u | (r << 16u) | (g << 8u) | (b << 0u)); ++ s += 1 * 4; ++ d += 1 * 4; ++ n -= 1; + } ++ ++ return len; + } + + // -------- + +-typedef void (*wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_func)( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2); ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw_4x16le__bgr(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len8 < src_len3) ? dst_len8 : src_len3; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +-static void // +-wuffs_base__pixel_swizzler__swizzle_rgb__convert_3_general( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2) { +- for (; x < x_end; x++) { +- uint32_t color = 0xFF000000u | // +- (((uint32_t)(*up0++)) << 16u) | // +- (((uint32_t)(*up1++)) << 8u) | // +- (((uint32_t)(*up2++)) << 0u); +- wuffs_base__pixel_buffer__set_color_u32_at(dst, x, y, color); +- } +-} ++ while (n >= 1) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ d[0] = s0; ++ d[1] = s0; ++ d[2] = s1; ++ d[3] = s1; ++ d[4] = s2; ++ d[5] = s2; ++ d[6] = 0xFF; ++ d[7] = 0xFF; + +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_general( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2) { +- for (; x < x_end; x++) { +- uint32_t color = // +- wuffs_base__color_ycc__as__color_u32( // +- *up0++, *up1++, *up2++); +- wuffs_base__pixel_buffer__set_color_u32_at(dst, x, y, color); ++ s += 1 * 3; ++ d += 1 * 8; ++ n -= 1; + } +-} +- +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_bgrx( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2) { +- size_t dst_stride = dst->private_impl.planes[0].stride; +- uint8_t* dst_iter = dst->private_impl.planes[0].ptr + +- (dst_stride * ((size_t)y)) + (4u * ((size_t)x)); + +- for (; x < x_end; x++) { +- uint32_t color = // +- wuffs_base__color_ycc__as__color_u32( // +- *up0++, *up1++, *up2++); +- wuffs_base__poke_u32le__no_bounds_check(dst_iter, color); +- dst_iter += 4u; +- } ++ return len; + } + +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_rgbx( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2) { +- size_t dst_stride = dst->private_impl.planes[0].stride; +- uint8_t* dst_iter = dst->private_impl.planes[0].ptr + +- (dst_stride * ((size_t)y)) + (4u * ((size_t)x)); ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw_4x16le__bgr_565(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- for (; x < x_end; x++) { +- uint32_t color = // +- wuffs_base__color_ycc__as__color_u32_abgr( // +- *up0++, *up1++, *up2++); +- wuffs_base__poke_u32le__no_bounds_check(dst_iter, color); +- dst_iter += 4u; ++ while (n >= 1) { ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), ++ wuffs_base__color_u32__as__color_u64( ++ wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( ++ wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))))); ++ ++ s += 1 * 2; ++ d += 1 * 8; ++ n -= 1; + } ++ ++ return len; + } + +-// -------- ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw_4x16le__bgrx(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +-// wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upsamples to a +-// destination slice at least 480 (YCCK) or 672 (YCC) bytes long and whose +-// src_len (multiplied by 1, 2, 3 or 4) is positive but no more than that. This +-// 480 or 672 length is just under 1/4 or 1/3 of the scratch_buffer_2k slice +-// length. Both (480 * 4) = 1920 and (672 * 3) = 2016 are less than 2048. +-// +-// 480 and 672 are nice round numbers because a JPEG MCU is 1, 2, 3 or 4 blocks +-// wide and each block is 8 pixels wide. We have: +-// 480 = 1 * 8 * 60, 672 = 1 * 8 * 84 +-// 480 = 2 * 8 * 30, 672 = 2 * 8 * 42 +-// 480 = 3 * 8 * 20, 672 = 3 * 8 * 28 +-// 480 = 4 * 8 * 15, 672 = 4 * 8 * 21 +-// +-// Box filters are equivalent to nearest neighbor upsampling. These ignore the +-// src_ptr_minor, h1v2_bias, first_column and last_column arguments. +-// +-// Triangle filters use a 3:1 ratio (in 1 dimension), or 9:3:3:1 (in 2 +-// dimensions), which is higher quality (less blocky) but also higher +-// computational effort. +-// +-// In theory, we could use triangle filters for any (inv_h, inv_v) combination. +-// In practice, matching libjpeg-turbo, we only implement it for the common +-// chroma subsampling ratios (YCC420, YCC422 or YCC440), corresponding to an +-// (inv_h, inv_v) pair of (2, 2), (2, 1) or (1, 2). +-typedef const uint8_t* ( +- *wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func)( +- uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, // Nearest row. +- const uint8_t* src_ptr_minor, // Adjacent row, alternating above or below. +- size_t src_len, +- uint32_t h1v2_bias, +- bool first_column, +- bool last_column); ++ while (n >= 1) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ d[0] = s0; ++ d[1] = s0; ++ d[2] = s1; ++ d[3] = s1; ++ d[4] = s2; ++ d[5] = s2; ++ d[6] = 0xFF; ++ d[7] = 0xFF; + +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h1vn_box( +- uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor_ignored, +- size_t src_len, +- uint32_t h1v2_bias_ignored, +- bool first_column_ignored, +- bool last_column_ignored) { +- return src_ptr_major; ++ s += 1 * 4; ++ d += 1 * 8; ++ n -= 1; ++ } ++ ++ return len; + } + +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2vn_box( +- uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor_ignored, +- size_t src_len, +- uint32_t h1v2_bias_ignored, +- bool first_column_ignored, +- bool last_column_ignored) { +- uint8_t* dp = dst_ptr; +- const uint8_t* sp = src_ptr_major; +- while (src_len--) { +- uint8_t sv = *sp++; +- *dp++ = sv; +- *dp++ = sv; ++static uint64_t // ++wuffs_private_impl__swizzle_bgrw_4x16le__rgb(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len3 = src_len / 3; ++ size_t len = (dst_len8 < src_len3) ? dst_len8 : src_len3; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; ++ ++ while (n >= 1) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ uint8_t s2 = s[2]; ++ d[0] = s2; ++ d[1] = s2; ++ d[2] = s1; ++ d[3] = s1; ++ d[4] = s0; ++ d[5] = s0; ++ d[6] = 0xFF; ++ d[7] = 0xFF; ++ ++ s += 1 * 3; ++ d += 1 * 8; ++ n -= 1; + } +- return dst_ptr; ++ ++ return len; + } + +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h3vn_box( +- uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor_ignored, +- size_t src_len, +- uint32_t h1v2_bias_ignored, +- bool first_column_ignored, +- bool last_column_ignored) { +- uint8_t* dp = dst_ptr; +- const uint8_t* sp = src_ptr_major; +- while (src_len--) { +- uint8_t sv = *sp++; +- *dp++ = sv; +- *dp++ = sv; +- *dp++ = sv; ++// -------- ++ ++static uint64_t // ++wuffs_private_impl__swizzle_rgb__bgr_565(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; ++ ++ // TODO: unroll. ++ ++ while (n >= 1) { ++ wuffs_base__poke_u24le__no_bounds_check( ++ d + (0 * 3), ++ wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( ++ wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))))); ++ ++ s += 1 * 2; ++ d += 1 * 3; ++ n -= 1; + } +- return dst_ptr; ++ ++ return len; + } + +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h4vn_box( ++// -------- ++ ++static uint64_t // ++wuffs_private_impl__swizzle_rgba_nonpremul__bgra_nonpremul_4x16le__src( + uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor_ignored, +- size_t src_len, +- uint32_t h1v2_bias_ignored, +- bool first_column_ignored, +- bool last_column_ignored) { +- uint8_t* dp = dst_ptr; +- const uint8_t* sp = src_ptr_major; +- while (src_len--) { +- uint8_t sv = *sp++; +- *dp++ = sv; +- *dp++ = sv; +- *dp++ = sv; +- *dp++ = sv; ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ ++ size_t n = len; ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__color_u64__as__color_u32__swap_u32_argb_abgr( ++ wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)))); ++ ++ s += 1 * 8; ++ d += 1 * 4; ++ n -= 1; + } +- return dst_ptr; ++ return len; + } + +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h1v2_triangle( ++static uint64_t // ++wuffs_private_impl__swizzle_rgba_nonpremul__bgra_nonpremul_4x16le__src_over( + uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor, +- size_t src_len, +- uint32_t h1v2_bias, +- bool first_column, +- bool last_column) { +- uint8_t* dp = dst_ptr; +- const uint8_t* sp_major = src_ptr_major; +- const uint8_t* sp_minor = src_ptr_minor; +- while (src_len--) { +- *dp++ = (uint8_t)(((3u * ((uint32_t)(*sp_major++))) + // +- (1u * ((uint32_t)(*sp_minor++))) + // +- h1v2_bias) >> +- 2u); ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len8 = src_len / 8; ++ size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; ++ ++ while (n >= 1) { ++ uint64_t d0 = wuffs_base__color_u32__as__color_u64( ++ wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4))); ++ uint64_t s0 = wuffs_private_impl__swap_u64_argb_abgr( ++ wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_base__color_u64__as__color_u32( ++ wuffs_private_impl__composite_nonpremul_nonpremul_u64_axxx(d0, ++ s0))); ++ ++ s += 1 * 8; ++ d += 1 * 4; ++ n -= 1; + } +- return dst_ptr; ++ ++ return len; + } + +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2v1_triangle( +- uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor, +- size_t src_len, +- uint32_t h1v2_bias_ignored, +- bool first_column, +- bool last_column) { +- uint8_t* dp = dst_ptr; +- const uint8_t* sp = src_ptr_major; ++// -------- + +- if (first_column) { +- src_len--; +- if ((src_len <= 0u) && last_column) { +- uint8_t sv = *sp++; +- *dp++ = sv; +- *dp++ = sv; +- return dst_ptr; +- } +- uint32_t svp1 = sp[+1]; +- uint8_t sv = *sp++; +- *dp++ = sv; +- *dp++ = (uint8_t)(((3u * (uint32_t)sv) + svp1 + 2u) >> 2u); +- if (src_len <= 0u) { +- return dst_ptr; +- } +- } ++static uint64_t // ++wuffs_private_impl__swizzle_rgbw__bgr_565(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- if (last_column) { +- src_len--; +- } ++ // TODO: unroll. + +- for (; src_len > 0u; src_len--) { +- uint32_t svm1 = sp[-1]; +- uint32_t svp1 = sp[+1]; +- uint32_t sv3 = 3u * (uint32_t)(*sp++); +- *dp++ = (uint8_t)((sv3 + svm1 + 1u) >> 2u); +- *dp++ = (uint8_t)((sv3 + svp1 + 2u) >> 2u); +- } ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), ++ wuffs_private_impl__swap_u32_argb_abgr( ++ wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul( ++ wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))))); + +- if (last_column) { +- uint32_t svm1 = sp[-1]; +- uint8_t sv = *sp++; +- *dp++ = (uint8_t)(((3u * (uint32_t)sv) + svm1 + 1u) >> 2u); +- *dp++ = sv; ++ s += 1 * 2; ++ d += 1 * 4; ++ n -= 1; + } + +- return dst_ptr; ++ return len; + } + +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2v2_triangle( +- uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor, +- size_t src_len, +- uint32_t h1v2_bias_ignored, +- bool first_column, +- bool last_column) { +- uint8_t* dp = dst_ptr; +- const uint8_t* sp_major = src_ptr_major; +- const uint8_t* sp_minor = src_ptr_minor; ++// -------- + +- if (first_column) { +- src_len--; +- if ((src_len <= 0u) && last_column) { +- uint32_t sv = (12u * ((uint32_t)(*sp_major++))) + // +- (4u * ((uint32_t)(*sp_minor++))); +- *dp++ = (uint8_t)((sv + 8u) >> 4u); +- *dp++ = (uint8_t)((sv + 7u) >> 4u); +- return dst_ptr; +- } ++static uint64_t // ++wuffs_private_impl__swizzle_xxx__index__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len3 = dst_len / 3; ++ size_t len = (dst_len3 < src_len) ? dst_len3 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- uint32_t sv_major_m1 = sp_major[-0]; // Clamp offset to zero. +- uint32_t sv_minor_m1 = sp_minor[-0]; // Clamp offset to zero. +- uint32_t sv_major_p1 = sp_major[+1]; +- uint32_t sv_minor_p1 = sp_minor[+1]; ++ const size_t loop_unroll_count = 4; + +- uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // +- (3u * ((uint32_t)(*sp_minor++))); +- *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); +- *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); +- if (src_len <= 0u) { +- return dst_ptr; +- } +- } ++ // The comparison in the while condition is ">", not ">=", because with ++ // ">=", the last 4-byte store could write past the end of the dst slice. ++ // ++ // Each 4-byte store writes one too many bytes, but a subsequent store ++ // will overwrite that with the correct byte. There is always another ++ // store, whether a 4-byte store in this loop or a 1-byte store in the ++ // next loop. ++ while (n > loop_unroll_count) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 3), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[0] * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (1 * 3), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[1] * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (2 * 3), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[2] * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (3 * 3), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[3] * 4))); + +- if (last_column) { +- src_len--; ++ s += loop_unroll_count * 1; ++ d += loop_unroll_count * 3; ++ n -= loop_unroll_count; + } + +- for (; src_len > 0u; src_len--) { +- uint32_t sv_major_m1 = sp_major[-1]; +- uint32_t sv_minor_m1 = sp_minor[-1]; +- uint32_t sv_major_p1 = sp_major[+1]; +- uint32_t sv_minor_p1 = sp_minor[+1]; ++ while (n >= 1) { ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); + +- uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // +- (3u * ((uint32_t)(*sp_minor++))); +- *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); +- *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); ++ s += 1 * 1; ++ d += 1 * 3; ++ n -= 1; + } + +- if (last_column) { +- uint32_t sv_major_m1 = sp_major[-1]; +- uint32_t sv_minor_m1 = sp_minor[-1]; +- uint32_t sv_major_p1 = sp_major[+0]; // Clamp offset to zero. +- uint32_t sv_minor_p1 = sp_minor[+0]; // Clamp offset to zero. ++ return len; ++} + +- uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // +- (3u * ((uint32_t)(*sp_minor++))); +- *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); +- *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); ++static uint64_t // ++wuffs_private_impl__swizzle_xxx__index_bgra_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; + } ++ size_t dst_len3 = dst_len / 3; ++ size_t len = (dst_len3 < src_len) ? dst_len3 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- return dst_ptr; +-} ++ // TODO: unroll. + +-// wuffs_base__pixel_swizzler__swizzle_ycc__upsample_funcs is indexed by inv_h +-// and then inv_v. +-static const wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_funcs[4][4] = { +- { +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h1vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h1vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h1vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h1vn_box, +- }, +- { +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2vn_box, +- }, +- { +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h3vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h3vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h3vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h3vn_box, +- }, +- { +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h4vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h4vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h4vn_box, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h4vn_box, +- }, +-}; ++ while (n >= 1) { ++ uint32_t d0 = ++ wuffs_base__peek_u24le__no_bounds_check(d + (0 * 3)) | 0xFF000000; ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ wuffs_base__poke_u24le__no_bounds_check( ++ d + (0 * 3), ++ wuffs_private_impl__composite_premul_nonpremul_u32_axxx(d0, s0)); + +-static inline uint32_t // +-wuffs_base__pixel_swizzler__has_triangle_upsampler(uint32_t inv_h, +- uint32_t inv_v) { +- if (inv_h == 1u) { +- return inv_v == 2u; +- } else if (inv_h == 2u) { +- return (inv_v == 1u) || (inv_v == 2u); ++ s += 1 * 1; ++ d += 1 * 3; ++ n -= 1; + } +- return false; ++ ++ return len; + } + +-// -------- ++static uint64_t // ++wuffs_private_impl__swizzle_xxx__index_binary_alpha__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len3 = dst_len / 3; ++ size_t len = (dst_len3 < src_len) ? dst_len3 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +-// All of the wuffs_base__pixel_swizzler__swizzle_ycc__etc functions have +-// preconditions. See all of the checks made in +-// wuffs_base__pixel_swizzler__swizzle_ycck before calling these functions. For +-// example, (width > 0) is a precondition, but there are many more. ++ const size_t loop_unroll_count = 4; + +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycck__general__triangle_filter_edge_row( +- wuffs_base__pixel_buffer* dst, +- uint32_t width, +- uint32_t y, +- const uint8_t* src_ptr0, +- const uint8_t* src_ptr1, +- const uint8_t* src_ptr2, +- const uint8_t* src_ptr3, +- uint32_t stride0, +- uint32_t stride1, +- uint32_t stride2, +- uint32_t stride3, +- uint32_t inv_h0, +- uint32_t inv_h1, +- uint32_t inv_h2, +- uint32_t inv_h3, +- uint32_t inv_v0, +- uint32_t inv_v1, +- uint32_t inv_v2, +- uint32_t inv_v3, +- uint32_t half_width_for_2to1, +- uint32_t h1v2_bias, +- uint8_t* scratch_buffer_2k_ptr, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc0, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc1, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc2, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc3, +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_4_func conv4func) { +- const uint8_t* src0 = src_ptr0 + ((y / inv_v0) * (size_t)stride0); +- const uint8_t* src1 = src_ptr1 + ((y / inv_v1) * (size_t)stride1); +- const uint8_t* src2 = src_ptr2 + ((y / inv_v2) * (size_t)stride2); +- const uint8_t* src3 = src_ptr3 + ((y / inv_v3) * (size_t)stride3); +- uint32_t total_src_len0 = 0u; +- uint32_t total_src_len1 = 0u; +- uint32_t total_src_len2 = 0u; +- uint32_t total_src_len3 = 0u; +- +- uint32_t x = 0u; +- while (x < width) { +- bool first_column = x == 0u; +- uint32_t end = x + 480u; +- if (end > width) { +- end = width; ++ while (n >= loop_unroll_count) { ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ if (s0) { ++ wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); ++ } ++ uint32_t s1 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[1] * 4)); ++ if (s1) { ++ wuffs_base__poke_u24le__no_bounds_check(d + (1 * 3), s1); ++ } ++ uint32_t s2 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[2] * 4)); ++ if (s2) { ++ wuffs_base__poke_u24le__no_bounds_check(d + (2 * 3), s2); ++ } ++ uint32_t s3 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[3] * 4)); ++ if (s3) { ++ wuffs_base__poke_u24le__no_bounds_check(d + (3 * 3), s3); + } + +- uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; +- uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; +- uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; +- uint32_t src_len3 = ((end - x) + inv_h3 - 1u) / inv_h3; +- total_src_len0 += src_len0; +- total_src_len1 += src_len1; +- total_src_len2 += src_len2; +- total_src_len3 += src_len3; +- +- const uint8_t* src_ptr_x0 = src0 + (x / inv_h0); +- const uint8_t* up0 = (*upfunc0)( // +- scratch_buffer_2k_ptr + (0u * 480u), // +- src_ptr_x0, // +- src_ptr_x0, // +- src_len0, // +- h1v2_bias, // +- first_column, // +- (total_src_len0 >= half_width_for_2to1)); +- +- const uint8_t* src_ptr_x1 = src1 + (x / inv_h1); +- const uint8_t* up1 = (*upfunc1)( // +- scratch_buffer_2k_ptr + (1u * 480u), // +- src_ptr_x1, // +- src_ptr_x1, // +- src_len1, // +- h1v2_bias, // +- first_column, // +- (total_src_len1 >= half_width_for_2to1)); +- +- const uint8_t* src_ptr_x2 = src2 + (x / inv_h2); +- const uint8_t* up2 = (*upfunc2)( // +- scratch_buffer_2k_ptr + (2u * 480u), // +- src_ptr_x2, // +- src_ptr_x2, // +- src_len2, // +- h1v2_bias, // +- first_column, // +- (total_src_len2 >= half_width_for_2to1)); ++ s += loop_unroll_count * 1; ++ d += loop_unroll_count * 3; ++ n -= loop_unroll_count; ++ } + +- const uint8_t* src_ptr_x3 = src3 + (x / inv_h3); +- const uint8_t* up3 = (*upfunc3)( // +- scratch_buffer_2k_ptr + (3u * 480u), // +- src_ptr_x3, // +- src_ptr_x3, // +- src_len3, // +- h1v2_bias, // +- first_column, // +- (total_src_len3 >= half_width_for_2to1)); ++ while (n >= 1) { ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ if (s0) { ++ wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0); ++ } + +- (*conv4func)(dst, x, end, y, up0, up1, up2, up3); +- x = end; ++ s += 1 * 1; ++ d += 1 * 3; ++ n -= 1; + } +-} +- +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycck__general__triangle_filter( +- wuffs_base__pixel_buffer* dst, +- uint32_t width, +- uint32_t height, +- const uint8_t* src_ptr0, +- const uint8_t* src_ptr1, +- const uint8_t* src_ptr2, +- const uint8_t* src_ptr3, +- uint32_t stride0, +- uint32_t stride1, +- uint32_t stride2, +- uint32_t stride3, +- uint32_t inv_h0, +- uint32_t inv_h1, +- uint32_t inv_h2, +- uint32_t inv_h3, +- uint32_t inv_v0, +- uint32_t inv_v1, +- uint32_t inv_v2, +- uint32_t inv_v3, +- uint32_t half_width_for_2to1, +- uint32_t half_height_for_2to1, +- uint8_t* scratch_buffer_2k_ptr, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func (*upfuncs)[4][4], +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_4_func conv4func) { +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc0 = +- (*upfuncs)[(inv_h0 - 1u) & 3u][(inv_v0 - 1u) & 3u]; +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc1 = +- (*upfuncs)[(inv_h1 - 1u) & 3u][(inv_v1 - 1u) & 3u]; +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc2 = +- (*upfuncs)[(inv_h2 - 1u) & 3u][(inv_v2 - 1u) & 3u]; +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc3 = +- (*upfuncs)[(inv_h3 - 1u) & 3u][(inv_v3 - 1u) & 3u]; + +- // First row. +- uint32_t h1v2_bias = 1u; +- wuffs_base__pixel_swizzler__swizzle_ycck__general__triangle_filter_edge_row( +- dst, width, 0u, // +- src_ptr0, src_ptr1, src_ptr2, src_ptr3, // +- stride0, stride1, stride2, stride3, // +- inv_h0, inv_h1, inv_h2, inv_h3, // +- inv_v0, inv_v1, inv_v2, inv_v3, // +- half_width_for_2to1, // +- h1v2_bias, // +- scratch_buffer_2k_ptr, // +- upfunc0, upfunc1, upfunc2, upfunc3, conv4func); +- h1v2_bias = 2u; ++ return len; ++} + +- // Middle rows. +- bool last_row = height == 2u * half_height_for_2to1; +- uint32_t y_max_excl = last_row ? (height - 1u) : height; +- uint32_t y; +- for (y = 1u; y < y_max_excl; y++) { +- const uint8_t* src0_major = src_ptr0 + ((y / inv_v0) * (size_t)stride0); +- const uint8_t* src0_minor = +- (inv_v0 != 2u) +- ? src0_major +- : ((y & 1u) ? (src0_major + stride0) : (src0_major - stride0)); +- const uint8_t* src1_major = src_ptr1 + ((y / inv_v1) * (size_t)stride1); +- const uint8_t* src1_minor = +- (inv_v1 != 2u) +- ? src1_major +- : ((y & 1u) ? (src1_major + stride1) : (src1_major - stride1)); +- const uint8_t* src2_major = src_ptr2 + ((y / inv_v2) * (size_t)stride2); +- const uint8_t* src2_minor = +- (inv_v2 != 2u) +- ? src2_major +- : ((y & 1u) ? (src2_major + stride2) : (src2_major - stride2)); +- const uint8_t* src3_major = src_ptr3 + ((y / inv_v3) * (size_t)stride3); +- const uint8_t* src3_minor = +- (inv_v3 != 2u) +- ? src3_major +- : ((y & 1u) ? (src3_major + stride3) : (src3_major - stride3)); +- uint32_t total_src_len0 = 0u; +- uint32_t total_src_len1 = 0u; +- uint32_t total_src_len2 = 0u; +- uint32_t total_src_len3 = 0u; ++static uint64_t // ++wuffs_private_impl__swizzle_xxx__xxxx(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- uint32_t x = 0u; +- while (x < width) { +- bool first_column = x == 0u; +- uint32_t end = x + 480u; +- if (end > width) { +- end = width; +- } ++ // TODO: unroll. + +- uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; +- uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; +- uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; +- uint32_t src_len3 = ((end - x) + inv_h3 - 1u) / inv_h3; +- total_src_len0 += src_len0; +- total_src_len1 += src_len1; +- total_src_len2 += src_len2; +- total_src_len3 += src_len3; ++ while (n >= 1) { ++ wuffs_base__poke_u24le__no_bounds_check( ++ d + (0 * 3), wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); + +- const uint8_t* up0 = (*upfunc0)( // +- scratch_buffer_2k_ptr + (0u * 480u), // +- src0_major + (x / inv_h0), // +- src0_minor + (x / inv_h0), // +- src_len0, // +- h1v2_bias, // +- first_column, // +- (total_src_len0 >= half_width_for_2to1)); ++ s += 1 * 4; ++ d += 1 * 3; ++ n -= 1; ++ } + +- const uint8_t* up1 = (*upfunc1)( // +- scratch_buffer_2k_ptr + (1u * 480u), // +- src1_major + (x / inv_h1), // +- src1_minor + (x / inv_h1), // +- src_len1, // +- h1v2_bias, // +- first_column, // +- (total_src_len1 >= half_width_for_2to1)); ++ return len; ++} + +- const uint8_t* up2 = (*upfunc2)( // +- scratch_buffer_2k_ptr + (2u * 480u), // +- src2_major + (x / inv_h2), // +- src2_minor + (x / inv_h2), // +- src_len2, // +- h1v2_bias, // +- first_column, // +- (total_src_len2 >= half_width_for_2to1)); ++static uint64_t // ++wuffs_private_impl__swizzle_xxx__y(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t len = (dst_len3 < src_len) ? dst_len3 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- const uint8_t* up3 = (*upfunc3)( // +- scratch_buffer_2k_ptr + (3u * 480u), // +- src3_major + (x / inv_h3), // +- src3_minor + (x / inv_h3), // +- src_len3, // +- h1v2_bias, // +- first_column, // +- (total_src_len3 >= half_width_for_2to1)); ++ // TODO: unroll. + +- (*conv4func)(dst, x, end, y, up0, up1, up2, up3); +- x = end; +- } ++ while (n >= 1) { ++ uint8_t s0 = s[0]; ++ d[0] = s0; ++ d[1] = s0; ++ d[2] = s0; + +- h1v2_bias ^= 3u; ++ s += 1 * 1; ++ d += 1 * 3; ++ n -= 1; + } + +- // Last row. +- if (y_max_excl != height) { +- wuffs_base__pixel_swizzler__swizzle_ycck__general__triangle_filter_edge_row( +- dst, width, height - 1u, // +- src_ptr0, src_ptr1, src_ptr2, src_ptr3, // +- stride0, stride1, stride2, stride3, // +- inv_h0, inv_h1, inv_h2, inv_h3, // +- inv_v0, inv_v1, inv_v2, inv_v3, // +- half_width_for_2to1, // +- h1v2_bias, // +- scratch_buffer_2k_ptr, // +- upfunc0, upfunc1, upfunc2, upfunc3, conv4func); +- } ++ return len; + } + +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__general__triangle_filter_edge_row( +- wuffs_base__pixel_buffer* dst, +- uint32_t width, +- uint32_t y, +- const uint8_t* src_ptr0, +- const uint8_t* src_ptr1, +- const uint8_t* src_ptr2, +- uint32_t stride0, +- uint32_t stride1, +- uint32_t stride2, +- uint32_t inv_h0, +- uint32_t inv_h1, +- uint32_t inv_h2, +- uint32_t inv_v0, +- uint32_t inv_v1, +- uint32_t inv_v2, +- uint32_t half_width_for_2to1, +- uint32_t h1v2_bias, +- uint8_t* scratch_buffer_2k_ptr, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc0, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc1, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc2, +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_func conv3func) { +- const uint8_t* src0 = src_ptr0 + ((y / inv_v0) * (size_t)stride0); +- const uint8_t* src1 = src_ptr1 + ((y / inv_v1) * (size_t)stride1); +- const uint8_t* src2 = src_ptr2 + ((y / inv_v2) * (size_t)stride2); +- uint32_t total_src_len0 = 0u; +- uint32_t total_src_len1 = 0u; +- uint32_t total_src_len2 = 0u; +- +- uint32_t x = 0u; +- while (x < width) { +- bool first_column = x == 0u; +- uint32_t end = x + 672u; +- if (end > width) { +- end = width; +- } +- +- uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; +- uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; +- uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; +- total_src_len0 += src_len0; +- total_src_len1 += src_len1; +- total_src_len2 += src_len2; +- +- const uint8_t* src_ptr_x0 = src0 + (x / inv_h0); +- const uint8_t* up0 = (*upfunc0)( // +- scratch_buffer_2k_ptr + (0u * 672u), // +- src_ptr_x0, // +- src_ptr_x0, // +- src_len0, // +- h1v2_bias, // +- first_column, // +- (total_src_len0 >= half_width_for_2to1)); ++static uint64_t // ++wuffs_private_impl__swizzle_xxx__y_16be(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- const uint8_t* src_ptr_x1 = src1 + (x / inv_h1); +- const uint8_t* up1 = (*upfunc1)( // +- scratch_buffer_2k_ptr + (1u * 672u), // +- src_ptr_x1, // +- src_ptr_x1, // +- src_len1, // +- h1v2_bias, // +- first_column, // +- (total_src_len1 >= half_width_for_2to1)); ++ // TODO: unroll. + +- const uint8_t* src_ptr_x2 = src2 + (x / inv_h2); +- const uint8_t* up2 = (*upfunc2)( // +- scratch_buffer_2k_ptr + (2u * 672u), // +- src_ptr_x2, // +- src_ptr_x2, // +- src_len2, // +- h1v2_bias, // +- first_column, // +- (total_src_len2 >= half_width_for_2to1)); ++ while (n >= 1) { ++ uint8_t s0 = s[0]; ++ d[0] = s0; ++ d[1] = s0; ++ d[2] = s0; + +- (*conv3func)(dst, x, end, y, up0, up1, up2); +- x = end; ++ s += 1 * 2; ++ d += 1 * 3; ++ n -= 1; + } +-} + +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__general__triangle_filter( +- wuffs_base__pixel_buffer* dst, +- uint32_t width, +- uint32_t height, +- const uint8_t* src_ptr0, +- const uint8_t* src_ptr1, +- const uint8_t* src_ptr2, +- uint32_t stride0, +- uint32_t stride1, +- uint32_t stride2, +- uint32_t inv_h0, +- uint32_t inv_h1, +- uint32_t inv_h2, +- uint32_t inv_v0, +- uint32_t inv_v1, +- uint32_t inv_v2, +- uint32_t half_width_for_2to1, +- uint32_t half_height_for_2to1, +- uint8_t* scratch_buffer_2k_ptr, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func (*upfuncs)[4][4], +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_func conv3func) { +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc0 = +- (*upfuncs)[(inv_h0 - 1u) & 3u][(inv_v0 - 1u) & 3u]; +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc1 = +- (*upfuncs)[(inv_h1 - 1u) & 3u][(inv_v1 - 1u) & 3u]; +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc2 = +- (*upfuncs)[(inv_h2 - 1u) & 3u][(inv_v2 - 1u) & 3u]; ++ return len; ++} + +- // First row. +- uint32_t h1v2_bias = 1u; +- wuffs_base__pixel_swizzler__swizzle_ycc__general__triangle_filter_edge_row( +- dst, width, 0u, // +- src_ptr0, src_ptr1, src_ptr2, // +- stride0, stride1, stride2, // +- inv_h0, inv_h1, inv_h2, // +- inv_v0, inv_v1, inv_v2, // +- half_width_for_2to1, // +- h1v2_bias, // +- scratch_buffer_2k_ptr, // +- upfunc0, upfunc1, upfunc2, conv3func); +- h1v2_bias = 2u; ++static uint64_t // ++wuffs_private_impl__swizzle_xxx__ya_nonpremul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- // Middle rows. +- bool last_row = height == 2u * half_height_for_2to1; +- uint32_t y_max_excl = last_row ? (height - 1u) : height; +- uint32_t y; +- for (y = 1u; y < y_max_excl; y++) { +- const uint8_t* src0_major = src_ptr0 + ((y / inv_v0) * (size_t)stride0); +- const uint8_t* src0_minor = +- (inv_v0 != 2u) +- ? src0_major +- : ((y & 1u) ? (src0_major + stride0) : (src0_major - stride0)); +- const uint8_t* src1_major = src_ptr1 + ((y / inv_v1) * (size_t)stride1); +- const uint8_t* src1_minor = +- (inv_v1 != 2u) +- ? src1_major +- : ((y & 1u) ? (src1_major + stride1) : (src1_major - stride1)); +- const uint8_t* src2_major = src_ptr2 + ((y / inv_v2) * (size_t)stride2); +- const uint8_t* src2_minor = +- (inv_v2 != 2u) +- ? src2_major +- : ((y & 1u) ? (src2_major + stride2) : (src2_major - stride2)); +- uint32_t total_src_len0 = 0u; +- uint32_t total_src_len1 = 0u; +- uint32_t total_src_len2 = 0u; ++ // TODO: unroll. + +- uint32_t x = 0u; +- while (x < width) { +- bool first_column = x == 0u; +- uint32_t end = x + 672u; +- if (end > width) { +- end = width; +- } ++ while (n >= 1) { ++ uint32_t s0 = ((uint32_t)(s[1]) << 24) | ((uint32_t)(s[0]) * 0x010101); ++ wuffs_base__poke_u24le__no_bounds_check( ++ d + (0 * 3), ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0)); + +- uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; +- uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; +- uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; +- total_src_len0 += src_len0; +- total_src_len1 += src_len1; +- total_src_len2 += src_len2; ++ s += 1 * 2; ++ d += 1 * 3; ++ n -= 1; ++ } + +- const uint8_t* up0 = (*upfunc0)( // +- scratch_buffer_2k_ptr + (0u * 672u), // +- src0_major + (x / inv_h0), // +- src0_minor + (x / inv_h0), // +- src_len0, // +- h1v2_bias, // +- first_column, // +- (total_src_len0 >= half_width_for_2to1)); ++ return len; ++} + +- const uint8_t* up1 = (*upfunc1)( // +- scratch_buffer_2k_ptr + (1u * 672u), // +- src1_major + (x / inv_h1), // +- src1_minor + (x / inv_h1), // +- src_len1, // +- h1v2_bias, // +- first_column, // +- (total_src_len1 >= half_width_for_2to1)); ++static uint64_t // ++wuffs_private_impl__swizzle_xxx__ya_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len3 = dst_len / 3; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- const uint8_t* up2 = (*upfunc2)( // +- scratch_buffer_2k_ptr + (2u * 672u), // +- src2_major + (x / inv_h2), // +- src2_minor + (x / inv_h2), // +- src_len2, // +- h1v2_bias, // +- first_column, // +- (total_src_len2 >= half_width_for_2to1)); ++ // TODO: unroll. + +- (*conv3func)(dst, x, end, y, up0, up1, up2); +- x = end; +- } ++ while (n >= 1) { ++ uint32_t d0 = ++ wuffs_base__peek_u24le__no_bounds_check(d + (0 * 3)) | 0xFF000000; ++ uint32_t s0 = ((uint32_t)(s[1]) << 24) | ((uint32_t)(s[0]) * 0x010101); ++ wuffs_base__poke_u24le__no_bounds_check( ++ d + (0 * 3), ++ wuffs_private_impl__composite_premul_nonpremul_u32_axxx(d0, s0)); + +- h1v2_bias ^= 3u; ++ s += 1 * 2; ++ d += 1 * 3; ++ n -= 1; + } + +- // Last row. +- if (y_max_excl != height) { +- wuffs_base__pixel_swizzler__swizzle_ycc__general__triangle_filter_edge_row( +- dst, width, height - 1u, // +- src_ptr0, src_ptr1, src_ptr2, // +- stride0, stride1, stride2, // +- inv_h0, inv_h1, inv_h2, // +- inv_v0, inv_v1, inv_v2, // +- half_width_for_2to1, // +- h1v2_bias, // +- scratch_buffer_2k_ptr, // +- upfunc0, upfunc1, upfunc2, conv3func); +- } ++ return len; + } + +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__general__box_filter( +- wuffs_base__pixel_buffer* dst, +- uint32_t width, +- uint32_t height, +- const uint8_t* src_ptr0, +- const uint8_t* src_ptr1, +- const uint8_t* src_ptr2, +- uint32_t stride0, +- uint32_t stride1, +- uint32_t stride2, +- uint32_t inv_h0, +- uint32_t inv_h1, +- uint32_t inv_h2, +- uint32_t inv_v0, +- uint32_t inv_v1, +- uint32_t inv_v2, +- uint32_t half_width_for_2to1, +- uint32_t half_height_for_2to1, +- uint8_t* scratch_buffer_2k_ptr, +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func (*upfuncs)[4][4], +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_func conv3func) { +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc0 = +- (*upfuncs)[(inv_h0 - 1u) & 3u][(inv_v0 - 1u) & 3u]; +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc1 = +- (*upfuncs)[(inv_h1 - 1u) & 3u][(inv_v1 - 1u) & 3u]; +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfunc2 = +- (*upfuncs)[(inv_h2 - 1u) & 3u][(inv_v2 - 1u) & 3u]; +- +- uint32_t y; +- for (y = 0u; y < height; y++) { +- const uint8_t* src0_major = src_ptr0 + ((y / inv_v0) * (size_t)stride0); +- const uint8_t* src1_major = src_ptr1 + ((y / inv_v1) * (size_t)stride1); +- const uint8_t* src2_major = src_ptr2 + ((y / inv_v2) * (size_t)stride2); ++// -------- + +- uint32_t x = 0u; +- while (x < width) { +- uint32_t end = x + 672u; +- if (end > width) { +- end = width; +- } ++static uint64_t // ++wuffs_private_impl__swizzle_xxxx__index__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len4 = dst_len / 4; ++ size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; +- uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; +- uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; ++ const size_t loop_unroll_count = 4; + +- const uint8_t* up0 = (*upfunc0)( // +- scratch_buffer_2k_ptr + (0u * 672u), // +- src0_major + (x / inv_h0), // +- src0_major + (x / inv_h0), // +- src_len0, // +- 0u, false, false); ++ while (n >= loop_unroll_count) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[0] * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (1 * 4), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[1] * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (2 * 4), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[2] * 4))); ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (3 * 4), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[3] * 4))); + +- const uint8_t* up1 = (*upfunc1)( // +- scratch_buffer_2k_ptr + (1u * 672u), // +- src1_major + (x / inv_h1), // +- src1_major + (x / inv_h1), // +- src_len1, // +- 0u, false, false); ++ s += loop_unroll_count * 1; ++ d += loop_unroll_count * 4; ++ n -= loop_unroll_count; ++ } + +- const uint8_t* up2 = (*upfunc2)( // +- scratch_buffer_2k_ptr + (2u * 672u), // +- src2_major + (x / inv_h2), // +- src2_major + (x / inv_h2), // +- src_len2, // +- 0u, false, false); ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[0] * 4))); + +- (*conv3func)(dst, x, end, y, up0, up1, up2); +- x = end; +- } ++ s += 1 * 1; ++ d += 1 * 4; ++ n -= 1; + } +-} + +-// -------- ++ return len; ++} + +-// wuffs_base__pixel_swizzler__flattened_length is like +-// wuffs_base__table__flattened_length but returns uint64_t (not size_t) and +-// also accounts for subsampling. + static uint64_t // +-wuffs_base__pixel_swizzler__flattened_length(uint32_t width, +- uint32_t height, +- uint32_t stride, +- uint32_t inv_h, +- uint32_t inv_v) { +- uint64_t scaled_width = (((uint64_t)width) + (inv_h - 1u)) / inv_h; +- uint64_t scaled_height = (((uint64_t)height) + (inv_v - 1u)) / inv_v; +- if (scaled_height <= 0u) { +- return 0u; ++wuffs_private_impl__swizzle_xxxx__index_binary_alpha__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; + } +- return ((scaled_height - 1u) * stride) + scaled_width; +-} ++ size_t dst_len4 = dst_len / 4; ++ size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status // +-wuffs_base__pixel_swizzler__swizzle_ycck( +- const wuffs_base__pixel_swizzler* p, +- wuffs_base__pixel_buffer* dst, +- wuffs_base__slice_u8 dst_palette, +- uint32_t width, +- uint32_t height, +- wuffs_base__slice_u8 src0, +- wuffs_base__slice_u8 src1, +- wuffs_base__slice_u8 src2, +- wuffs_base__slice_u8 src3, +- uint32_t width0, +- uint32_t width1, +- uint32_t width2, +- uint32_t width3, +- uint32_t height0, +- uint32_t height1, +- uint32_t height2, +- uint32_t height3, +- uint32_t stride0, +- uint32_t stride1, +- uint32_t stride2, +- uint32_t stride3, +- uint8_t h0, +- uint8_t h1, +- uint8_t h2, +- uint8_t h3, +- uint8_t v0, +- uint8_t v1, +- uint8_t v2, +- uint8_t v3, +- bool is_rgb_or_cmyk, +- bool triangle_filter_for_2to1, +- wuffs_base__slice_u8 scratch_buffer_2k) { +- if (!p) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } else if (!dst || (width > 0xFFFFu) || (height > 0xFFFFu) || // +- (4u <= ((unsigned int)h0 - 1u)) || // +- (4u <= ((unsigned int)h1 - 1u)) || // +- (4u <= ((unsigned int)h2 - 1u)) || // +- (4u <= ((unsigned int)v0 - 1u)) || // +- (4u <= ((unsigned int)v1 - 1u)) || // +- (4u <= ((unsigned int)v2 - 1u)) || // +- (scratch_buffer_2k.len < 2048u)) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ const size_t loop_unroll_count = 4; ++ ++ while (n >= loop_unroll_count) { ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ if (s0) { ++ wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0); ++ } ++ uint32_t s1 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[1] * 4)); ++ if (s1) { ++ wuffs_base__poke_u32le__no_bounds_check(d + (1 * 4), s1); ++ } ++ uint32_t s2 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[2] * 4)); ++ if (s2) { ++ wuffs_base__poke_u32le__no_bounds_check(d + (2 * 4), s2); ++ } ++ uint32_t s3 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[3] * 4)); ++ if (s3) { ++ wuffs_base__poke_u32le__no_bounds_check(d + (3 * 4), s3); ++ } ++ ++ s += loop_unroll_count * 1; ++ d += loop_unroll_count * 4; ++ n -= loop_unroll_count; + } +- if ((h3 != 0u) || (v3 != 0u)) { +- if ((4u <= ((unsigned int)h3 - 1u)) || // +- (4u <= ((unsigned int)v3 - 1u))) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ ++ while (n >= 1) { ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ if (s0) { ++ wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0); + } ++ ++ s += 1 * 1; ++ d += 1 * 4; ++ n -= 1; + } + +- uint32_t max_incl_h = wuffs_base__u32__max_of_4(h0, h1, h2, h3); +- uint32_t max_incl_v = wuffs_base__u32__max_of_4(v0, v1, v2, v3); ++ return len; ++} + +- // Calculate the inverse h and v ratios. +- // +- // It also canonicalizes (h=2 and max_incl_h=4) as equivalent to (h=1 and +- // max_incl_h=2). In both cases, the inv_h value is 2. +- uint32_t inv_h0 = max_incl_h / h0; +- uint32_t inv_h1 = max_incl_h / h1; +- uint32_t inv_h2 = max_incl_h / h2; +- uint32_t inv_h3 = h3 ? (max_incl_h / h3) : 0u; +- uint32_t inv_v0 = max_incl_v / v0; +- uint32_t inv_v1 = max_incl_v / v1; +- uint32_t inv_v2 = max_incl_v / v2; +- uint32_t inv_v3 = v3 ? (max_incl_v / v3) : 0u; ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") ++static uint64_t // ++wuffs_private_impl__swizzle_xxxx__y__x86_sse42(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- uint32_t half_width_for_2to1 = (width + 1u) / 2u; +- uint32_t half_height_for_2to1 = (height + 1u) / 2u; +- +- width = wuffs_base__u32__min_of_5( // +- width, // +- width0 * inv_h0, // +- width1 * inv_h1, // +- width2 * inv_h2, // +- wuffs_base__pixel_config__width(&dst->pixcfg)); +- height = wuffs_base__u32__min_of_5( // +- height, // +- height0 * inv_v0, // +- height1 * inv_v1, // +- height2 * inv_v2, // +- wuffs_base__pixel_config__height(&dst->pixcfg)); ++ __m128i shuffle = _mm_set_epi8(+0x03, +0x03, +0x03, +0x03, // ++ +0x02, +0x02, +0x02, +0x02, // ++ +0x01, +0x01, +0x01, +0x01, // ++ +0x00, +0x00, +0x00, +0x00); ++ __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00, // ++ -0x01, +0x00, +0x00, +0x00); + +- if (((h0 * inv_h0) != max_incl_h) || // +- ((h1 * inv_h1) != max_incl_h) || // +- ((h2 * inv_h2) != max_incl_h) || // +- ((v0 * inv_v0) != max_incl_v) || // +- ((v1 * inv_v1) != max_incl_v) || // +- ((v2 * inv_v2) != max_incl_v) || // +- (src0.len < wuffs_base__pixel_swizzler__flattened_length( +- width, height, stride0, inv_h0, inv_v0)) || +- (src1.len < wuffs_base__pixel_swizzler__flattened_length( +- width, height, stride1, inv_h1, inv_v1)) || +- (src2.len < wuffs_base__pixel_swizzler__flattened_length( +- width, height, stride2, inv_h2, inv_v2))) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((h3 != 0u) || (v3 != 0u)) { +- if (((h3 * inv_h3) != max_incl_h) || // +- ((v3 * inv_v3) != max_incl_v) || // +- (src3.len < wuffs_base__pixel_swizzler__flattened_length( +- width, height, stride3, inv_h3, inv_v3))) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- } ++ while (n >= 4) { ++ __m128i x; ++ x = _mm_cvtsi32_si128((int)(wuffs_base__peek_u32le__no_bounds_check(s))); ++ x = _mm_shuffle_epi8(x, shuffle); ++ x = _mm_or_si128(x, or_ff); ++ _mm_storeu_si128((__m128i*)(void*)d, x); + +- if (wuffs_base__pixel_format__is_planar(&dst->pixcfg.private_impl.pixfmt)) { +- // TODO: see wuffs_base__pixel_buffer__set_color_u32_at's TODO. +- return wuffs_base__make_status( +- wuffs_base__error__unsupported_pixel_swizzler_option); ++ s += 4 * 1; ++ d += 4 * 4; ++ n -= 4; + } + +- switch (dst->pixcfg.private_impl.pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__Y: +- case WUFFS_BASE__PIXEL_FORMAT__Y_16LE: +- case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: +- case WUFFS_BASE__PIXEL_FORMAT__BGR_565: +- case WUFFS_BASE__PIXEL_FORMAT__BGR: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +- case WUFFS_BASE__PIXEL_FORMAT__RGB: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +- break; ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0])); + +- default: +- // TODO: see wuffs_base__pixel_buffer__set_color_u32_at's TODO. +- return wuffs_base__make_status( +- wuffs_base__error__unsupported_pixel_swizzler_option); ++ s += 1 * 1; ++ d += 1 * 4; ++ n -= 1; + } + +- if ((width <= 0u) || (height <= 0u)) { +- return wuffs_base__make_status(NULL); +- } ++ return len; ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_func conv3func = NULL; ++static uint64_t // ++wuffs_private_impl__swizzle_xxxx__y(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t len = (dst_len4 < src_len) ? dst_len4 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- if (is_rgb_or_cmyk) { +- conv3func = &wuffs_base__pixel_swizzler__swizzle_rgb__convert_3_general; +- } else { +- switch (dst->pixcfg.private_impl.pixfmt.repr) { +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__BGRX: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +- if (wuffs_base__cpu_arch__have_x86_avx2()) { +- conv3func = +- &wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_bgrx_x86_avx2; +- break; +- } +-#endif +- conv3func = &wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_bgrx; +- break; +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: +- case WUFFS_BASE__PIXEL_FORMAT__RGBX: +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +- if (wuffs_base__cpu_arch__have_x86_avx2()) { +- conv3func = +- &wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_rgbx_x86_avx2; +- break; +- } +-#endif +- conv3func = &wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_rgbx; +- break; +- default: +- conv3func = &wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_general; +- break; +- } ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0])); ++ ++ s += 1 * 1; ++ d += 1 * 4; ++ n -= 1; + } + +- void (*func)( +- wuffs_base__pixel_buffer * dst, // +- uint32_t width, // +- uint32_t height, // +- const uint8_t* src_ptr0, // +- const uint8_t* src_ptr1, // +- const uint8_t* src_ptr2, // +- uint32_t stride0, // +- uint32_t stride1, // +- uint32_t stride2, // +- uint32_t inv_h0, // +- uint32_t inv_h1, // +- uint32_t inv_h2, // +- uint32_t inv_v0, // +- uint32_t inv_v1, // +- uint32_t inv_v2, // +- uint32_t half_width_for_2to1, // +- uint32_t half_height_for_2to1, // +- uint8_t* scratch_buffer_2k_ptr, // +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func(*upfuncs)[4][4], +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_func conv3func) = +- &wuffs_base__pixel_swizzler__swizzle_ycc__general__box_filter; +- +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_func upfuncs[4][4]; +- memcpy(&upfuncs, &wuffs_base__pixel_swizzler__swizzle_ycc__upsample_funcs, +- sizeof upfuncs); ++ return len; ++} + +- if (triangle_filter_for_2to1 && +- (wuffs_base__pixel_swizzler__has_triangle_upsampler(inv_h0, inv_v0) || +- wuffs_base__pixel_swizzler__has_triangle_upsampler(inv_h1, inv_v1) || +- wuffs_base__pixel_swizzler__has_triangle_upsampler(inv_h2, inv_v2))) { +- func = &wuffs_base__pixel_swizzler__swizzle_ycc__general__triangle_filter; +- +- upfuncs[0][1] = +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h1v2_triangle; +- upfuncs[1][0] = +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2v1_triangle; +- upfuncs[1][1] = +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2v2_triangle; +- +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +-#if defined(__GNUC__) && !defined(__clang__) +- // Don't use our AVX2 implementation for GCC (but do use it for clang). For +- // some unknown reason, GCC performs noticably better on the non-SIMD +- // version. Possibly because GCC's auto-vectorizer is smarter (just with +- // SSE2, not AVX2) than our hand-written code, but that's just a guess. +- // +- // See commits 51bc60ef9298cb2efc1b29a9681191f66d49820d and +- // cd769a0cdf1b5affee13f6089b995f3d39569cb4 for benchmark numbers. +- // +- // See also https://godbolt.org/z/MbhbPGEz4 for Debian Bullseye's clang 11 +- // versus gcc 10, where only gcc auto-vectorizes, although later clang +- // versions will also auto-vectorize. +-#else +- if (wuffs_base__cpu_arch__have_x86_avx2()) { +- upfuncs[1][1] = +- wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2v2_triangle_x86_avx2; +- } +-#endif +-#endif +- } ++static uint64_t // ++wuffs_private_impl__swizzle_xxxx__y_16be(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len4 = dst_len / 4; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- if ((h3 != 0u) || (v3 != 0u)) { +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_4_func conv4func = +- is_rgb_or_cmyk +- ? &wuffs_base__pixel_swizzler__swizzle_cmyk__convert_4_general +- : &wuffs_base__pixel_swizzler__swizzle_ycck__convert_4_general; +- wuffs_base__pixel_swizzler__swizzle_ycck__general__triangle_filter( // +- dst, width, height, // +- src0.ptr, src1.ptr, src2.ptr, src3.ptr, // +- stride0, stride1, stride2, stride3, // +- inv_h0, inv_h1, inv_h2, inv_h3, // +- inv_v0, inv_v1, inv_v2, inv_v3, // +- half_width_for_2to1, half_height_for_2to1, // +- scratch_buffer_2k.ptr, &upfuncs, conv4func); ++ while (n >= 1) { ++ wuffs_base__poke_u32le__no_bounds_check( ++ d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0])); + +- } else { +- (*func)( // +- dst, width, height, // +- src0.ptr, src1.ptr, src2.ptr, // +- stride0, stride1, stride2, // +- inv_h0, inv_h1, inv_h2, // +- inv_v0, inv_v1, inv_v2, // +- half_width_for_2to1, half_height_for_2to1, // +- scratch_buffer_2k.ptr, &upfuncs, conv3func); ++ s += 1 * 2; ++ d += 1 * 4; ++ n -= 1; + } + +- return wuffs_base__make_status(NULL); ++ return len; + } + + // -------- + +-// ‼ WUFFS MULTI-FILE SECTION +x86_avx2 +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_bgrx_x86_avx2( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2) { +- if ((x + 32u) > x_end) { +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_bgrx( // +- dst, x, x_end, y, up0, up1, up2); +- return; ++static uint64_t // ++wuffs_private_impl__swizzle_xxxxxxxx__index__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; + } ++ size_t dst_len8 = dst_len / 8; ++ size_t len = (dst_len8 < src_len) ? dst_len8 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- size_t dst_stride = dst->private_impl.planes[0].stride; +- uint8_t* dst_iter = dst->private_impl.planes[0].ptr + +- (dst_stride * ((size_t)y)) + (4u * ((size_t)x)); +- +- // u0001 = u16x16 [0x0001 .. 0x0001] +- // u00FF = u16x16 [0x00FF .. 0x00FF] +- // uFF80 = u16x16 [0xFF80 .. 0xFF80] +- // uFFFF = u16x16 [0xFFFF .. 0xFFFF] +- const __m256i u0001 = _mm256_set1_epi16(+0x0001); +- const __m256i u00FF = _mm256_set1_epi16(+0x00FF); +- const __m256i uFF80 = _mm256_set1_epi16(-0x0080); +- const __m256i uFFFF = _mm256_set1_epi16(-0x0001); ++ while (n >= 1) { ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), wuffs_base__color_u32__as__color_u64( ++ wuffs_base__peek_u32le__no_bounds_check( ++ dst_palette_ptr + ((size_t)s[0] * 4)))); + +- // p8000_p0000 = u16x16 [0x8000 0x0000 .. 0x8000 0x0000] +- const __m256i p8000_p0000 = _mm256_set_epi16( // +- +0x0000, -0x8000, +0x0000, -0x8000, // +- +0x0000, -0x8000, +0x0000, -0x8000, // +- +0x0000, -0x8000, +0x0000, -0x8000, // +- +0x0000, -0x8000, +0x0000, -0x8000); ++ s += 1 * 1; ++ d += 1 * 8; ++ n -= 1; ++ } + +- // Per wuffs_base__color_ycc__as__color_u32, the formulae: +- // +- // R = Y + 1.40200 * Cr +- // G = Y - 0.34414 * Cb - 0.71414 * Cr +- // B = Y + 1.77200 * Cb +- // +- // When scaled by 1<<16: +- // +- // 0.34414 becomes 0x0581A = 22554. +- // 0.71414 becomes 0x0B6D2 = 46802. +- // 1.40200 becomes 0x166E9 = 91881. +- // 1.77200 becomes 0x1C5A2 = 116130. +- // +- // Separate the integer and fractional parts, since we work with signed +- // 16-bit SIMD lanes. The fractional parts range from -0.5 .. +0.5 (as +- // floating-point) which is from -0x8000 .. +0x8000 (as fixed-point). +- // +- // -0x3A5E = -0x20000 + 0x1C5A2 The B:Cb factor. +- // +0x66E9 = -0x10000 + 0x166E9 The R:Cr factor. +- // -0x581A = +0x00000 - 0x0581A The G:Cb factor. +- // +0x492E = +0x10000 - 0x0B6D2 The G:Cr factor. +- const __m256i m3A5E = _mm256_set1_epi16(-0x3A5E); +- const __m256i p66E9 = _mm256_set1_epi16(+0x66E9); +- const __m256i m581A_p492E = _mm256_set_epi16( // +- +0x492E, -0x581A, +0x492E, -0x581A, // +- +0x492E, -0x581A, +0x492E, -0x581A, // +- +0x492E, -0x581A, +0x492E, -0x581A, // +- +0x492E, -0x581A, +0x492E, -0x581A); ++ return len; ++} + +- while (x < x_end) { +- // Load chroma values in even and odd columns (the high 8 bits of each +- // u16x16 element are zero) and then subtract 0x0080. +- // +- // cb_all = u8x32 [cb.00 cb.01 cb.02 cb.03 .. cb.1C cb.1D cb.1E cb.1F] +- // cb_eve = i16x16 [cb.00-0x80 cb.02-0x80 .. cb.1C-0x80 cb.1E-0x80 ] +- // cb_odd = i16x16 [cb.01-0x80 cb.03-0x80 .. cb.1D-0x80 cb.1F-0x80 ] +- // +- // Ditto for the cr_xxx Chroma-Red values. +- __m256i cb_all = _mm256_lddqu_si256((const __m256i*)(const void*)up1); +- __m256i cr_all = _mm256_lddqu_si256((const __m256i*)(const void*)up2); +- __m256i cb_eve = _mm256_add_epi16(uFF80, _mm256_and_si256(cb_all, u00FF)); +- __m256i cr_eve = _mm256_add_epi16(uFF80, _mm256_and_si256(cr_all, u00FF)); +- __m256i cb_odd = _mm256_add_epi16(uFF80, _mm256_srli_epi16(cb_all, 8)); +- __m256i cr_odd = _mm256_add_epi16(uFF80, _mm256_srli_epi16(cr_all, 8)); ++static uint64_t // ++wuffs_private_impl__swizzle_xxxxxxxx__index_binary_alpha__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ if (dst_palette_len != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return 0; ++ } ++ size_t dst_len8 = dst_len / 8; ++ size_t len = (dst_len8 < src_len) ? dst_len8 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- // ---- ++ while (n >= 1) { ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr + ++ ((size_t)s[0] * 4)); ++ if (s0) { ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), wuffs_base__color_u32__as__color_u64(s0)); ++ } + +- // Calculate: +- // +- // B-Y = (+1.77200 * Cb) as floating-point +- // R-Y = (+1.40200 * Cr) as floating-point +- // +- // B-Y = ((0x2_0000 - 0x3A5E) * Cb) as fixed-point +- // R-Y = ((0x1_0000 + 0x66E9) * Cr) as fixed-point +- // +- // B-Y = ((-0x3A5E * Cb) + ("2.0" * Cb)) +- // R-Y = ((+0x66E9 * Cr) + ("1.0" * Cr)) ++ s += 1 * 1; ++ d += 1 * 8; ++ n -= 1; ++ } + +- // Multiply by m3A5E or p66E9, taking the high 16 bits. There's also a +- // doubling (add x to itself), adding-of-1 and halving (shift right by 1). +- // That makes multiply-and-take-high round to nearest (instead of down). +- __m256i tmp_by_eve = _mm256_srai_epi16( +- _mm256_add_epi16( +- _mm256_mulhi_epi16(_mm256_add_epi16(cb_eve, cb_eve), m3A5E), u0001), +- 1); +- __m256i tmp_by_odd = _mm256_srai_epi16( +- _mm256_add_epi16( +- _mm256_mulhi_epi16(_mm256_add_epi16(cb_odd, cb_odd), m3A5E), u0001), +- 1); +- __m256i tmp_ry_eve = _mm256_srai_epi16( +- _mm256_add_epi16( +- _mm256_mulhi_epi16(_mm256_add_epi16(cr_eve, cr_eve), p66E9), u0001), +- 1); +- __m256i tmp_ry_odd = _mm256_srai_epi16( +- _mm256_add_epi16( +- _mm256_mulhi_epi16(_mm256_add_epi16(cr_odd, cr_odd), p66E9), u0001), +- 1); ++ return len; ++} + +- // Add (2 * Cb) and (1 * Cr). +- __m256i by_eve = +- _mm256_add_epi16(tmp_by_eve, _mm256_add_epi16(cb_eve, cb_eve)); +- __m256i by_odd = +- _mm256_add_epi16(tmp_by_odd, _mm256_add_epi16(cb_odd, cb_odd)); +- __m256i ry_eve = _mm256_add_epi16(tmp_ry_eve, cr_eve); +- __m256i ry_odd = _mm256_add_epi16(tmp_ry_odd, cr_odd); ++static uint64_t // ++wuffs_private_impl__swizzle_xxxxxxxx__y(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t len = (dst_len8 < src_len) ? dst_len8 : src_len; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- // ---- ++ while (n >= 1) { ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), 0xFFFF000000000000 | (0x010101010101 * (uint64_t)s[0])); + +- // Calculate: +- // +- // G-Y = (-0.34414 * Cb) + +- // (-0.71414 * Cr) as floating-point +- // +- // G-Y = ((+0x0_0000 - 0x581A) * Cb) + +- // ((-0x1_0000 + 0x492E) * Cr) as fixed-point +- // +- // G-Y = (-0x581A * Cb) + +- // (+0x492E * Cr) - ("1.0" * Cr) ++ s += 1 * 1; ++ d += 1 * 8; ++ n -= 1; ++ } + +- // Multiply-add to get ((-0x581A * Cb) + (+0x492E * Cr)). +- __m256i tmp0_gy_eve_lo = _mm256_madd_epi16( // +- _mm256_unpacklo_epi16(cb_eve, cr_eve), m581A_p492E); +- __m256i tmp0_gy_eve_hi = _mm256_madd_epi16( // +- _mm256_unpackhi_epi16(cb_eve, cr_eve), m581A_p492E); +- __m256i tmp0_gy_odd_lo = _mm256_madd_epi16( // +- _mm256_unpacklo_epi16(cb_odd, cr_odd), m581A_p492E); +- __m256i tmp0_gy_odd_hi = _mm256_madd_epi16( // +- _mm256_unpackhi_epi16(cb_odd, cr_odd), m581A_p492E); ++ return len; ++} + +- // Divide the i32x8 vectors by (1 << 16), rounding to nearest. +- __m256i tmp1_gy_eve_lo = +- _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_eve_lo, p8000_p0000), 16); +- __m256i tmp1_gy_eve_hi = +- _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_eve_hi, p8000_p0000), 16); +- __m256i tmp1_gy_odd_lo = +- _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_odd_lo, p8000_p0000), 16); +- __m256i tmp1_gy_odd_hi = +- _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_odd_hi, p8000_p0000), 16); ++static uint64_t // ++wuffs_private_impl__swizzle_xxxxxxxx__y_16be(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len8 = dst_len / 8; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- // Pack the ((-0x581A * Cb) + (+0x492E * Cr)) as i16x16 and subtract Cr. +- __m256i gy_eve = _mm256_sub_epi16( +- _mm256_packs_epi32(tmp1_gy_eve_lo, tmp1_gy_eve_hi), cr_eve); +- __m256i gy_odd = _mm256_sub_epi16( +- _mm256_packs_epi32(tmp1_gy_odd_lo, tmp1_gy_odd_hi), cr_odd); ++ while (n >= 1) { ++ uint64_t s0 = ++ ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(s + (0 * 2)))); ++ wuffs_base__poke_u64le__no_bounds_check( ++ d + (0 * 8), 0xFFFF000000000000 | (0x000100010001 * s0)); + +- // ---- ++ s += 1 * 2; ++ d += 1 * 8; ++ n -= 1; ++ } + +- // Add Y to (B-Y), (G-Y) and (R-Y) to produce B, G and R. +- // +- // For the resultant packed_x_xxx vectors, only elements 0 ..= 7 and 16 ..= +- // 23 of the 32-element vectors matter (since we'll unpacklo but not +- // unpackhi them). Let … denote 8 ignored consecutive u8 values and let % +- // denote 0xFF. We'll end this section with: +- // +- // packed_b_eve = u8x32 [b00 b02 .. b0C b0E … b10 b12 .. b1C b1E …] +- // packed_b_odd = u8x32 [b01 b03 .. b0D b0F … b11 b13 .. b1D b1F …] +- // packed_g_eve = u8x32 [g00 g02 .. g0C g0E … g10 g12 .. g1C g1E …] +- // packed_g_odd = u8x32 [g01 g03 .. g0D g0F … g11 g13 .. g1D g1F …] +- // packed_r_eve = u8x32 [r00 r02 .. r0C r0E … r10 r12 .. r1C r1E …] +- // packed_r_odd = u8x32 [r01 r03 .. r0D r0F … r11 r13 .. r1D r1F …] +- // uFFFF = u8x32 [ % % .. % % … % % .. % % …] ++ return len; ++} + +- __m256i yy_all = _mm256_lddqu_si256((const __m256i*)(const void*)up0); +- __m256i yy_eve = _mm256_and_si256(yy_all, u00FF); +- __m256i yy_odd = _mm256_srli_epi16(yy_all, 8); ++// -------- + +- __m256i loose_b_eve = _mm256_add_epi16(by_eve, yy_eve); +- __m256i loose_b_odd = _mm256_add_epi16(by_odd, yy_odd); +- __m256i packed_b_eve = _mm256_packus_epi16(loose_b_eve, loose_b_eve); +- __m256i packed_b_odd = _mm256_packus_epi16(loose_b_odd, loose_b_odd); ++static uint64_t // ++wuffs_private_impl__swizzle_y__bgra_nonpremul__src(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len < src_len4) ? dst_len : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- __m256i loose_g_eve = _mm256_add_epi16(gy_eve, yy_eve); +- __m256i loose_g_odd = _mm256_add_epi16(gy_odd, yy_odd); +- __m256i packed_g_eve = _mm256_packus_epi16(loose_g_eve, loose_g_eve); +- __m256i packed_g_odd = _mm256_packus_epi16(loose_g_odd, loose_g_odd); ++ while (n >= 1) { ++ uint32_t s0 = ++ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul( ++ wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))); ++ d[0] = wuffs_base__color_u32_argb_premul__as__color_u8_gray(s0); + +- __m256i loose_r_eve = _mm256_add_epi16(ry_eve, yy_eve); +- __m256i loose_r_odd = _mm256_add_epi16(ry_odd, yy_odd); +- __m256i packed_r_eve = _mm256_packus_epi16(loose_r_eve, loose_r_eve); +- __m256i packed_r_odd = _mm256_packus_epi16(loose_r_odd, loose_r_odd); ++ s += 1 * 4; ++ d += 1 * 1; ++ n -= 1; ++ } + +- // ---- ++ return len; ++} + +- // Mix those values (unpacking in 8, 16 and then 32 bit units) to get the +- // desired BGRX/RGBX order. +- // +- // From here onwards, all of our __m256i registers are u8x32. ++static uint64_t // ++wuffs_private_impl__swizzle_y__bgra_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len < src_len4) ? dst_len : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- // mix00 = [b00 g00 b02 g02 .. b0E g0E b10 g10 .. b1C g1C b1E g1E] +- // mix01 = [b01 g01 b03 g03 .. b0F g0F b11 g11 .. b1D g1D b1F g1F] +- // mix02 = [r00 % r02 % .. r0E % r10 % .. r1C % r1E %] +- // mix03 = [r01 % r03 % .. r0F % r11 % .. r1D % r1F %] +- // +- // See also § below. +- __m256i mix00 = _mm256_unpacklo_epi8(packed_b_eve, packed_g_eve); +- __m256i mix01 = _mm256_unpacklo_epi8(packed_b_odd, packed_g_odd); +- __m256i mix02 = _mm256_unpacklo_epi8(packed_r_eve, uFFFF); +- __m256i mix03 = _mm256_unpacklo_epi8(packed_r_odd, uFFFF); ++ while (n >= 1) { ++ uint32_t d0 = 0xFF000000 | (0x00010101 * ((uint32_t)(d[0]))); ++ uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); ++ d[0] = wuffs_base__color_u32_argb_premul__as__color_u8_gray( ++ wuffs_private_impl__composite_premul_nonpremul_u32_axxx(d0, s0)); + +- // mix10 = [b00 g00 r00 % b02 g02 r02 % b04 g04 r04 % b06 g06 r06 % +- // b10 g10 r10 % b12 g12 r12 % b14 g14 r14 % b16 g16 r16 %] +- // mix11 = [b01 g01 r01 % b03 g03 r03 % b05 g05 r05 % b07 g07 r07 % +- // b11 g11 r11 % b13 g13 r13 % b15 g15 r15 % b17 g17 r17 %] +- // mix12 = [b08 g08 r08 % b0A g0A r0A % b0C g0C r0C % b0E g0E r0E % +- // b18 g18 r18 % b1A g1A r1A % b1C g1C r1C % b1E g1E r1E %] +- // mix13 = [b09 g09 r09 % b0B g0B r0B % b0D g0D r0D % b0F g0F r0F % +- // b19 g19 r19 % b1B g1B r1B % b1D g1D r1D % b1F g1F r1F %] +- __m256i mix10 = _mm256_unpacklo_epi16(mix00, mix02); +- __m256i mix11 = _mm256_unpacklo_epi16(mix01, mix03); +- __m256i mix12 = _mm256_unpackhi_epi16(mix00, mix02); +- __m256i mix13 = _mm256_unpackhi_epi16(mix01, mix03); ++ s += 1 * 4; ++ d += 1 * 1; ++ n -= 1; ++ } + +- // mix20 = [b00 g00 r00 % b01 g01 r01 % b02 g02 r02 % b03 g03 r03 % +- // b10 g10 r10 % b11 g11 r11 % b12 g12 r12 % b13 g13 r13 %] +- // mix21 = [b04 g04 r04 % b05 g05 r05 % b06 g06 r06 % b07 g07 r07 % +- // b14 g14 r14 % b15 g15 r15 % b16 g16 r16 % b17 g17 r17 %] +- // mix22 = [b08 g08 r08 % b09 g09 r09 % b0A g0A r0A % b0B g0B r0B % +- // b18 g18 r18 % b19 g19 r19 % b1A g1A r1A % b1B g1B r1B %] +- // mix23 = [b0C g0C r0C % b0D g0D r0D % b0E g0E r0E % b0F g0F r0F % +- // b1C g1C r1C % b1D g1D r1D % b1E g1E r1E % b1F g1F r1F %] +- __m256i mix20 = _mm256_unpacklo_epi32(mix10, mix11); +- __m256i mix21 = _mm256_unpackhi_epi32(mix10, mix11); +- __m256i mix22 = _mm256_unpacklo_epi32(mix12, mix13); +- __m256i mix23 = _mm256_unpackhi_epi32(mix12, mix13); ++ return len; ++} + +- // mix30 = [b00 g00 r00 % b01 g01 r01 % b02 g02 r02 % b03 g03 r03 % +- // b04 g04 r04 % b05 g05 r05 % b06 g06 r06 % b07 g07 r07 %] +- // mix31 = [b08 g08 r08 % b09 g09 r09 % b0A g0A r0A % b0B g0B r0B % +- // b0C g0C r0C % b0D g0D r0D % b0E g0E r0E % b0F g0F r0F %] +- // mix32 = [b10 g10 r10 % b11 g11 r11 % b12 g12 r12 % b13 g13 r13 % +- // b14 g14 r14 % b15 g15 r15 % b16 g16 r16 % b17 g17 r17 %] +- // mix33 = [b18 g18 r18 % b19 g19 r19 % b1A g1A r1A % b1B g1B r1B % +- // b1C g1C r1C % b1D g1D r1D % b1E g1E r1E % b1F g1F r1F %] +- __m256i mix30 = _mm256_permute2x128_si256(mix20, mix21, 0x20); +- __m256i mix31 = _mm256_permute2x128_si256(mix22, mix23, 0x20); +- __m256i mix32 = _mm256_permute2x128_si256(mix20, mix21, 0x31); +- __m256i mix33 = _mm256_permute2x128_si256(mix22, mix23, 0x31); ++static uint64_t // ++wuffs_private_impl__swizzle_y__bgrx(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t src_len4 = src_len / 4; ++ size_t len = (dst_len < src_len4) ? dst_len : src_len4; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- // Write out four u8x32 SIMD registers (128 bytes, 32 BGRX/RGBX pixels). +- _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x00), mix30); +- _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x20), mix31); +- _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x40), mix32); +- _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x60), mix33); ++ while (n >= 1) { ++ uint32_t s0 = ++ 0xFF000000 | wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)); ++ d[0] = wuffs_base__color_u32_argb_premul__as__color_u8_gray(s0); + +- // Advance by up to 32 pixels. The first iteration might be smaller than 32 +- // so that all of the remaining steps are exactly 32. +- uint32_t n = 32u - (31u & (x - x_end)); +- dst_iter += 4u * n; +- up0 += n; +- up1 += n; +- up2 += n; +- x += n; ++ s += 1 * 4; ++ d += 1 * 1; ++ n -= 1; + } ++ ++ return len; + } + +-// The rgbx flavor (below) is exactly the same as the bgrx flavor (above) +-// except for the lines marked with a § and that comments were stripped. +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") +-static void // +-wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_rgbx_x86_avx2( +- wuffs_base__pixel_buffer* dst, +- uint32_t x, +- uint32_t x_end, +- uint32_t y, +- const uint8_t* up0, +- const uint8_t* up1, +- const uint8_t* up2) { +- if ((x + 32u) > x_end) { +- wuffs_base__pixel_swizzler__swizzle_ycc__convert_3_bgrx( // +- dst, x, x_end, y, up0, up1, up2); +- return; +- } ++static uint64_t // ++wuffs_private_impl__swizzle_y__y_16be(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len < src_len2) ? dst_len : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- size_t dst_stride = dst->private_impl.planes[0].stride; +- uint8_t* dst_iter = dst->private_impl.planes[0].ptr + +- (dst_stride * ((size_t)y)) + (4u * ((size_t)x)); ++ while (n >= 1) { ++ d[0] = s[0]; + +- const __m256i u0001 = _mm256_set1_epi16(+0x0001); +- const __m256i u00FF = _mm256_set1_epi16(+0x00FF); +- const __m256i uFF80 = _mm256_set1_epi16(-0x0080); +- const __m256i uFFFF = _mm256_set1_epi16(-0x0001); ++ s += 1 * 2; ++ d += 1 * 1; ++ n -= 1; ++ } + +- const __m256i p8000_p0000 = _mm256_set_epi16( // +- +0x0000, -0x8000, +0x0000, -0x8000, // +- +0x0000, -0x8000, +0x0000, -0x8000, // +- +0x0000, -0x8000, +0x0000, -0x8000, // +- +0x0000, -0x8000, +0x0000, -0x8000); ++ return len; ++} + +- const __m256i m3A5E = _mm256_set1_epi16(-0x3A5E); +- const __m256i p66E9 = _mm256_set1_epi16(+0x66E9); +- const __m256i m581A_p492E = _mm256_set_epi16( // +- +0x492E, -0x581A, +0x492E, -0x581A, // +- +0x492E, -0x581A, +0x492E, -0x581A, // +- +0x492E, -0x581A, +0x492E, -0x581A, // +- +0x492E, -0x581A, +0x492E, -0x581A); ++static uint64_t // ++wuffs_private_impl__swizzle_y_16le__y_16be(uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- while (x < x_end) { +- __m256i cb_all = _mm256_lddqu_si256((const __m256i*)(const void*)up1); +- __m256i cr_all = _mm256_lddqu_si256((const __m256i*)(const void*)up2); +- __m256i cb_eve = _mm256_add_epi16(uFF80, _mm256_and_si256(cb_all, u00FF)); +- __m256i cr_eve = _mm256_add_epi16(uFF80, _mm256_and_si256(cr_all, u00FF)); +- __m256i cb_odd = _mm256_add_epi16(uFF80, _mm256_srli_epi16(cb_all, 8)); +- __m256i cr_odd = _mm256_add_epi16(uFF80, _mm256_srli_epi16(cr_all, 8)); ++ while (n >= 1) { ++ uint8_t s0 = s[0]; ++ uint8_t s1 = s[1]; ++ d[0] = s1; ++ d[1] = s0; + +- __m256i tmp_by_eve = _mm256_srai_epi16( +- _mm256_add_epi16( +- _mm256_mulhi_epi16(_mm256_add_epi16(cb_eve, cb_eve), m3A5E), u0001), +- 1); +- __m256i tmp_by_odd = _mm256_srai_epi16( +- _mm256_add_epi16( +- _mm256_mulhi_epi16(_mm256_add_epi16(cb_odd, cb_odd), m3A5E), u0001), +- 1); +- __m256i tmp_ry_eve = _mm256_srai_epi16( +- _mm256_add_epi16( +- _mm256_mulhi_epi16(_mm256_add_epi16(cr_eve, cr_eve), p66E9), u0001), +- 1); +- __m256i tmp_ry_odd = _mm256_srai_epi16( +- _mm256_add_epi16( +- _mm256_mulhi_epi16(_mm256_add_epi16(cr_odd, cr_odd), p66E9), u0001), +- 1); ++ s += 1 * 2; ++ d += 1 * 2; ++ n -= 1; ++ } + +- __m256i by_eve = +- _mm256_add_epi16(tmp_by_eve, _mm256_add_epi16(cb_eve, cb_eve)); +- __m256i by_odd = +- _mm256_add_epi16(tmp_by_odd, _mm256_add_epi16(cb_odd, cb_odd)); +- __m256i ry_eve = _mm256_add_epi16(tmp_ry_eve, cr_eve); +- __m256i ry_odd = _mm256_add_epi16(tmp_ry_odd, cr_odd); ++ return len; ++} + +- __m256i tmp0_gy_eve_lo = _mm256_madd_epi16( // +- _mm256_unpacklo_epi16(cb_eve, cr_eve), m581A_p492E); +- __m256i tmp0_gy_eve_hi = _mm256_madd_epi16( // +- _mm256_unpackhi_epi16(cb_eve, cr_eve), m581A_p492E); +- __m256i tmp0_gy_odd_lo = _mm256_madd_epi16( // +- _mm256_unpacklo_epi16(cb_odd, cr_odd), m581A_p492E); +- __m256i tmp0_gy_odd_hi = _mm256_madd_epi16( // +- _mm256_unpackhi_epi16(cb_odd, cr_odd), m581A_p492E); ++// -------- + +- __m256i tmp1_gy_eve_lo = +- _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_eve_lo, p8000_p0000), 16); +- __m256i tmp1_gy_eve_hi = +- _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_eve_hi, p8000_p0000), 16); +- __m256i tmp1_gy_odd_lo = +- _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_odd_lo, p8000_p0000), 16); +- __m256i tmp1_gy_odd_hi = +- _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_odd_hi, p8000_p0000), 16); ++static uint64_t // ++wuffs_private_impl__swizzle_ya_nonpremul__ya_nonpremul__src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ const uint8_t* src_ptr, ++ size_t src_len) { ++ size_t dst_len2 = dst_len / 2; ++ size_t src_len2 = src_len / 2; ++ size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2; ++ uint8_t* d = dst_ptr; ++ const uint8_t* s = src_ptr; ++ size_t n = len; + +- __m256i gy_eve = _mm256_sub_epi16( +- _mm256_packs_epi32(tmp1_gy_eve_lo, tmp1_gy_eve_hi), cr_eve); +- __m256i gy_odd = _mm256_sub_epi16( +- _mm256_packs_epi32(tmp1_gy_odd_lo, tmp1_gy_odd_hi), cr_odd); ++ while (n >= 1) { ++ uint32_t d0 = ((uint32_t)(d[1]) << 24) | ((uint32_t)(d[0]) * 0x010101); ++ uint32_t s0 = ((uint32_t)(s[1]) << 24) | ((uint32_t)(s[0]) * 0x010101); ++ uint32_t c0 = ++ wuffs_private_impl__composite_nonpremul_nonpremul_u32_axxx(d0, s0); ++ wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)(c0 >> 16)); + +- __m256i yy_all = _mm256_lddqu_si256((const __m256i*)(const void*)up0); +- __m256i yy_eve = _mm256_and_si256(yy_all, u00FF); +- __m256i yy_odd = _mm256_srli_epi16(yy_all, 8); ++ s += 1 * 2; ++ d += 1 * 2; ++ n -= 1; ++ } + +- __m256i loose_b_eve = _mm256_add_epi16(by_eve, yy_eve); +- __m256i loose_b_odd = _mm256_add_epi16(by_odd, yy_odd); +- __m256i packed_b_eve = _mm256_packus_epi16(loose_b_eve, loose_b_eve); +- __m256i packed_b_odd = _mm256_packus_epi16(loose_b_odd, loose_b_odd); ++ return len; ++} + +- __m256i loose_g_eve = _mm256_add_epi16(gy_eve, yy_eve); +- __m256i loose_g_odd = _mm256_add_epi16(gy_odd, yy_odd); +- __m256i packed_g_eve = _mm256_packus_epi16(loose_g_eve, loose_g_eve); +- __m256i packed_g_odd = _mm256_packus_epi16(loose_g_odd, loose_g_odd); ++// -------- + +- __m256i loose_r_eve = _mm256_add_epi16(ry_eve, yy_eve); +- __m256i loose_r_odd = _mm256_add_epi16(ry_odd, yy_odd); +- __m256i packed_r_eve = _mm256_packus_epi16(loose_r_eve, loose_r_eve); +- __m256i packed_r_odd = _mm256_packus_epi16(loose_r_odd, loose_r_odd); ++static uint64_t // ++wuffs_private_impl__swizzle_transparent_black_src( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ uint64_t num_pixels, ++ uint32_t dst_pixfmt_bytes_per_pixel) { ++ uint64_t n = ((uint64_t)dst_len) / dst_pixfmt_bytes_per_pixel; ++ if (n > num_pixels) { ++ n = num_pixels; ++ } ++ memset(dst_ptr, 0, ((size_t)(n * dst_pixfmt_bytes_per_pixel))); ++ return n; ++} + +- // § Note the swapped B and R channels. +- __m256i mix00 = _mm256_unpacklo_epi8(packed_r_eve, packed_g_eve); +- __m256i mix01 = _mm256_unpacklo_epi8(packed_r_odd, packed_g_odd); +- __m256i mix02 = _mm256_unpacklo_epi8(packed_b_eve, uFFFF); +- __m256i mix03 = _mm256_unpacklo_epi8(packed_b_odd, uFFFF); ++static uint64_t // ++wuffs_private_impl__swizzle_transparent_black_src_over( ++ uint8_t* dst_ptr, ++ size_t dst_len, ++ uint8_t* dst_palette_ptr, ++ size_t dst_palette_len, ++ uint64_t num_pixels, ++ uint32_t dst_pixfmt_bytes_per_pixel) { ++ uint64_t n = ((uint64_t)dst_len) / dst_pixfmt_bytes_per_pixel; ++ if (n > num_pixels) { ++ n = num_pixels; ++ } ++ return n; ++} + +- __m256i mix10 = _mm256_unpacklo_epi16(mix00, mix02); +- __m256i mix11 = _mm256_unpacklo_epi16(mix01, mix03); +- __m256i mix12 = _mm256_unpackhi_epi16(mix00, mix02); +- __m256i mix13 = _mm256_unpackhi_epi16(mix01, mix03); ++// -------- + +- __m256i mix20 = _mm256_unpacklo_epi32(mix10, mix11); +- __m256i mix21 = _mm256_unpackhi_epi32(mix10, mix11); +- __m256i mix22 = _mm256_unpacklo_epi32(mix12, mix13); +- __m256i mix23 = _mm256_unpackhi_epi32(mix12, mix13); ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__y( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__Y: ++ return wuffs_private_impl__swizzle_copy_1_1; + +- __m256i mix30 = _mm256_permute2x128_si256(mix20, mix21, 0x20); +- __m256i mix31 = _mm256_permute2x128_si256(mix22, mix23, 0x20); +- __m256i mix32 = _mm256_permute2x128_si256(mix20, mix21, 0x31); +- __m256i mix33 = _mm256_permute2x128_si256(mix22, mix23, 0x31); ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ return wuffs_private_impl__swizzle_bgr_565__y; + +- _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x00), mix30); +- _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x20), mix31); +- _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x40), mix32); +- _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x60), mix33); ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ return wuffs_private_impl__swizzle_xxx__y; + +- uint32_t n = 32u - (31u & (x - x_end)); +- dst_iter += 4u * n; +- up0 += n; +- up1 += n; +- up2 += n; +- x += n; ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_xxxx__y__x86_sse42; ++ } ++#endif ++ return wuffs_private_impl__swizzle_xxxx__y; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE: ++ return wuffs_private_impl__swizzle_xxxxxxxx__y; + } ++ return NULL; + } + +-#if defined(__GNUC__) && !defined(__clang__) +-// No-op. +-#else +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") +-static const uint8_t* // +-wuffs_base__pixel_swizzler__swizzle_ycc__upsample_inv_h2v2_triangle_x86_avx2( +- uint8_t* dst_ptr, +- const uint8_t* src_ptr_major, +- const uint8_t* src_ptr_minor, +- size_t src_len, +- uint32_t h1v2_bias_ignored, +- bool first_column, +- bool last_column) { +- uint8_t* dp = dst_ptr; +- const uint8_t* sp_major = src_ptr_major; +- const uint8_t* sp_minor = src_ptr_minor; +- +- if (first_column) { +- src_len--; +- if ((src_len <= 0u) && last_column) { +- uint32_t sv = (12u * ((uint32_t)(*sp_major++))) + // +- (4u * ((uint32_t)(*sp_minor++))); +- *dp++ = (uint8_t)((sv + 8u) >> 4u); +- *dp++ = (uint8_t)((sv + 7u) >> 4u); +- return dst_ptr; +- } +- +- uint32_t sv_major_m1 = sp_major[-0]; // Clamp offset to zero. +- uint32_t sv_minor_m1 = sp_minor[-0]; // Clamp offset to zero. +- uint32_t sv_major_p1 = sp_major[+1]; +- uint32_t sv_minor_p1 = sp_minor[+1]; +- +- uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // +- (3u * ((uint32_t)(*sp_minor++))); +- *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); +- *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); +- if (src_len <= 0u) { +- return dst_ptr; +- } +- } +- +- if (last_column) { +- src_len--; +- } +- +- if (src_len < 32) { +- // This fallback is the same as the non-SIMD-capable code path. +- for (; src_len > 0u; src_len--) { +- uint32_t sv_major_m1 = sp_major[-1]; +- uint32_t sv_minor_m1 = sp_minor[-1]; +- uint32_t sv_major_p1 = sp_major[+1]; +- uint32_t sv_minor_p1 = sp_minor[+1]; +- +- uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // +- (3u * ((uint32_t)(*sp_minor++))); +- *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); +- *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); +- } +- +- } else { +- while (src_len > 0u) { +- // Load 1+32+1 samples (six u8x32 vectors) from the major (jxx) and minor +- // (nxx) rows. +- // +- // major_p0 = [j00 j01 j02 j03 .. j28 j29 j30 j31] // p0 = "plus 0" +- // minor_p0 = [n00 n01 n02 n03 .. n28 n29 n30 n31] // p0 = "plus 0" +- // major_m1 = [jm1 j00 j01 j02 .. j27 j28 j29 j30] // m1 = "minus 1" +- // minor_m1 = [nm1 n00 n01 n02 .. n27 n28 n29 n30] // m1 = "minus 1" +- // major_p1 = [j01 j02 j03 j04 .. j29 j30 j31 j32] // p1 = "plus 1" +- // minor_p1 = [n01 n02 n03 n04 .. n29 n30 n31 n32] // p1 = "plus 1" +- __m256i major_p0 = +- _mm256_lddqu_si256((const __m256i*)(const void*)(sp_major + 0)); +- __m256i minor_p0 = +- _mm256_lddqu_si256((const __m256i*)(const void*)(sp_minor + 0)); +- __m256i major_m1 = +- _mm256_lddqu_si256((const __m256i*)(const void*)(sp_major - 1)); +- __m256i minor_m1 = +- _mm256_lddqu_si256((const __m256i*)(const void*)(sp_minor - 1)); +- __m256i major_p1 = +- _mm256_lddqu_si256((const __m256i*)(const void*)(sp_major + 1)); +- __m256i minor_p1 = +- _mm256_lddqu_si256((const __m256i*)(const void*)(sp_minor + 1)); +- +- // Unpack, staying with u8x32 vectors. +- // +- // step1_p0_lo = [j00 n00 j01 n01 .. j07 n07 j16 n16 j17 n17 .. j23 n23] +- // step1_p0_hi = [j08 n08 j09 n09 .. j15 n15 j24 n24 j25 n25 .. j31 n31] +- // step1_m1_lo = [jm1 nm1 j00 n00 .. j06 n06 j15 n15 j16 n16 .. j22 n22] +- // step1_m1_hi = [j07 n07 j08 n08 .. j14 n14 j23 n23 j24 n24 .. j30 n30] +- // step1_p1_lo = [j01 n01 j02 n02 .. j08 n08 j17 n17 j18 n18 .. j24 n24] +- // step1_p1_hi = [j09 n09 j10 n10 .. j16 n16 j25 n25 j26 n26 .. j32 n32] +- __m256i step1_p0_lo = _mm256_unpacklo_epi8(major_p0, minor_p0); +- __m256i step1_p0_hi = _mm256_unpackhi_epi8(major_p0, minor_p0); +- __m256i step1_m1_lo = _mm256_unpacklo_epi8(major_m1, minor_m1); +- __m256i step1_m1_hi = _mm256_unpackhi_epi8(major_m1, minor_m1); +- __m256i step1_p1_lo = _mm256_unpacklo_epi8(major_p1, minor_p1); +- __m256i step1_p1_hi = _mm256_unpackhi_epi8(major_p1, minor_p1); +- +- // Multiply-add to get u16x16 vectors. +- // +- // step2_p0_lo = [9*j00+3*n00 9*j01+3*n01 .. 9*j23+3*n23] +- // step2_p0_hi = [9*j08+3*n08 9*j09+3*n09 .. 9*j31+3*n31] +- // step2_m1_lo = [3*jm1+1*nm1 3*j00+1*n00 .. 3*j22+1*n22] +- // step2_m1_hi = [3*j07+1*n07 3*j08+1*n08 .. 3*j30+1*n30] +- // step2_p1_lo = [3*j01+1*n01 3*j02+1*n02 .. 3*j24+1*n24] +- // step2_p1_hi = [3*j09+1*n09 3*j10+1*n10 .. 3*j32+1*n32] +- const __m256i k0309 = _mm256_set1_epi16(0x0309); +- const __m256i k0103 = _mm256_set1_epi16(0x0103); +- __m256i step2_p0_lo = _mm256_maddubs_epi16(step1_p0_lo, k0309); +- __m256i step2_p0_hi = _mm256_maddubs_epi16(step1_p0_hi, k0309); +- __m256i step2_m1_lo = _mm256_maddubs_epi16(step1_m1_lo, k0103); +- __m256i step2_m1_hi = _mm256_maddubs_epi16(step1_m1_hi, k0103); +- __m256i step2_p1_lo = _mm256_maddubs_epi16(step1_p1_lo, k0103); +- __m256i step2_p1_hi = _mm256_maddubs_epi16(step1_p1_hi, k0103); +- +- // Compute the weighted sums of (p0, m1) and (p0, p1). For example: +- // +- // step3_m1_lo[00] = ((9*j00) + (3*n00) + (3*jm1) + (1*nm1)) as u16 +- // step3_p1_hi[15] = ((9*j31) + (3*n31) + (3*j32) + (1*n32)) as u16 +- __m256i step3_m1_lo = _mm256_add_epi16(step2_p0_lo, step2_m1_lo); +- __m256i step3_m1_hi = _mm256_add_epi16(step2_p0_hi, step2_m1_hi); +- __m256i step3_p1_lo = _mm256_add_epi16(step2_p0_lo, step2_p1_lo); +- __m256i step3_p1_hi = _mm256_add_epi16(step2_p0_hi, step2_p1_hi); ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__y_16be( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__Y: ++ return wuffs_private_impl__swizzle_y__y_16be; + +- // Bias by 8 (on the left) or 7 (on the right) and then divide by 16 +- // (which is 9+3+3+1) to get a weighted average. On the left (m1), shift +- // the u16 right value by 4. On the right (p1), shift right by 4 and then +- // shift left by 8 so that, when still in the u16x16 little-endian +- // interpretation, we have: +- // - m1_element = (etcetera + 8) >> 4 +- // - p1_element = ((etcetera + 7) >> 4) << 8 +- // +- // step4_m1_lo = [0x00?? 0x00?? ... 0x00?? 0x00??] +- // step4_p1_lo = [0x??00 0x??00 ... 0x??00 0x??00] +- // step4_m1_hi = [0x00?? 0x00?? ... 0x00?? 0x00??] +- // step4_p1_hi = [0x??00 0x??00 ... 0x??00 0x??00] +- __m256i step4_m1_lo = _mm256_srli_epi16( +- _mm256_add_epi16(step3_m1_lo, _mm256_set1_epi16(8)), 4); +- __m256i step4_p1_lo = _mm256_slli_epi16( +- _mm256_srli_epi16(_mm256_add_epi16(step3_p1_lo, _mm256_set1_epi16(7)), +- 4), +- 8); +- __m256i step4_m1_hi = _mm256_srli_epi16( +- _mm256_add_epi16(step3_m1_hi, _mm256_set1_epi16(8)), 4); +- __m256i step4_p1_hi = _mm256_slli_epi16( +- _mm256_srli_epi16(_mm256_add_epi16(step3_p1_hi, _mm256_set1_epi16(7)), +- 4), +- 8); ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16LE: ++ return wuffs_private_impl__swizzle_y_16le__y_16be; + +- // Bitwise-or two "0x00"-rich u16x16 vectors to get a u8x32 vector. Do +- // that twice. Once for the low columns and once for the high columns. +- // +- // In terms of jxx (major row) or nxx (minor row) source samples: +- // - low columns means ( 0 .. 8; 16 .. 24). +- // - high columns means ( 8 .. 16; 24 .. 32). +- // +- // In terms of dxx destination samples (there are twice as many): +- // - low columns means ( 0 .. 16; 32 .. 48). +- // - high columns means (16 .. 32; 48 .. 64). +- // +- // step5_lo = [d00 d01 .. d14 d15 d32 d33 .. d46 d47] +- // step5_hi = [d16 d17 .. d30 d31 d48 d49 .. d62 d63] +- // +- // The d00, d02 ... d62 even elements come from (p0, m1) weighted sums. +- // The d01, d03 ... d63 odd elements come from (p0, p1) weighted sums. +- __m256i step5_lo = _mm256_or_si256(step4_m1_lo, step4_p1_lo); +- __m256i step5_hi = _mm256_or_si256(step4_m1_hi, step4_p1_hi); ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: ++ return wuffs_private_impl__swizzle_copy_2_2; + +- // Permute and store. +- // +- // step6_00_31 = [d00 d01 .. d14 d15 d16 d17 .. d30 d31] +- // step6_32_63 = [d32 d33 .. d46 d47 d48 d49 .. d62 d63] +- __m256i step6_00_31 = _mm256_permute2x128_si256(step5_lo, step5_hi, 0x20); +- __m256i step6_32_63 = _mm256_permute2x128_si256(step5_lo, step5_hi, 0x31); +- _mm256_storeu_si256((__m256i*)(void*)(dp + 0x00), step6_00_31); +- _mm256_storeu_si256((__m256i*)(void*)(dp + 0x20), step6_32_63); ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ return wuffs_private_impl__swizzle_bgr_565__y_16be; + +- // Advance by up to 32 source samples (64 destination samples). The first +- // iteration might be smaller than 32 so that all of the remaining steps +- // are exactly 32. +- size_t n = 32u - (31u & (0u - src_len)); +- dp += 2u * n; +- sp_major += n; +- sp_minor += n; +- src_len -= n; +- } +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ return wuffs_private_impl__swizzle_xxx__y_16be; + +- if (last_column) { +- uint32_t sv_major_m1 = sp_major[-1]; +- uint32_t sv_minor_m1 = sp_minor[-1]; +- uint32_t sv_major_p1 = sp_major[+0]; // Clamp offset to zero. +- uint32_t sv_minor_p1 = sp_minor[+0]; // Clamp offset to zero. ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ return wuffs_private_impl__swizzle_xxxx__y_16be; + +- uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // +- (3u * ((uint32_t)(*sp_minor++))); +- *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); +- *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE: ++ return wuffs_private_impl__swizzle_xxxxxxxx__y_16be; + } +- +- return dst_ptr; ++ return NULL; + } +-#endif +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_64) +-// ‼ WUFFS MULTI-FILE SECTION -x86_avx2 + +-#endif // !defined(WUFFS_CONFIG__MODULES) || +- // defined(WUFFS_CONFIG__MODULE__BASE) || +- // defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ +- defined(WUFFS_CONFIG__MODULE__BASE__UTF8) ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__ya_nonpremul( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_copy_2_2; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_ya_nonpremul__ya_nonpremul__src_over; ++ } ++ return NULL; + +-// ---------------- Unicode and UTF-8 ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr_565__ya_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr_565__ya_nonpremul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__MAYBE_STATIC size_t // +-wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point) { +- if (code_point <= 0x7F) { +- if (dst.len >= 1) { +- dst.ptr[0] = (uint8_t)(code_point); +- return 1; +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxx__ya_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_xxx__ya_nonpremul__src_over; ++ } ++ return NULL; + +- } else if (code_point <= 0x07FF) { +- if (dst.len >= 2) { +- dst.ptr[0] = (uint8_t)(0xC0 | ((code_point >> 6))); +- dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); +- return 2; +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__ya_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__ya_nonpremul__src_over; ++ } ++ return NULL; + +- } else if (code_point <= 0xFFFF) { +- if ((dst.len >= 3) && ((code_point < 0xD800) || (0xDFFF < code_point))) { +- dst.ptr[0] = (uint8_t)(0xE0 | ((code_point >> 12))); +- dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F)); +- dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); +- return 3; +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_premul__ya_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__ya_nonpremul__src_over; ++ } ++ return NULL; + +- } else if (code_point <= 0x10FFFF) { +- if (dst.len >= 4) { +- dst.ptr[0] = (uint8_t)(0xF0 | ((code_point >> 18))); +- dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 12) & 0x3F)); +- dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F)); +- dst.ptr[3] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); +- return 4; +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__ya_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__ya_nonpremul__src_over; ++ } ++ return NULL; + } +- +- return 0; ++ return NULL; + } + +-// wuffs_base__utf_8__byte_length_minus_1 is the byte length (minus 1) of a +-// UTF-8 encoded code point, based on the encoding's initial byte. +-// - 0x00 is 1-byte UTF-8 (ASCII). +-// - 0x01 is the start of 2-byte UTF-8. +-// - 0x02 is the start of 3-byte UTF-8. +-// - 0x03 is the start of 4-byte UTF-8. +-// - 0x40 is a UTF-8 tail byte. +-// - 0x80 is invalid UTF-8. +-// +-// RFC 3629 (UTF-8) gives this grammar for valid UTF-8: +-// UTF8-1 = %x00-7F +-// UTF8-2 = %xC2-DF UTF8-tail +-// UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) / +-// %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail ) +-// UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) / +-// %xF4 %x80-8F 2( UTF8-tail ) +-// UTF8-tail = %x80-BF +-static const uint8_t wuffs_base__utf_8__byte_length_minus_1[256] = { +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 ..= 0x37. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. +- +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 ..= 0x47. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 ..= 0x67. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77. +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F. +- +- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x80 ..= 0x87. +- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x88 ..= 0x8F. +- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x90 ..= 0x97. +- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x98 ..= 0x9F. +- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xA0 ..= 0xA7. +- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xA8 ..= 0xAF. +- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xB0 ..= 0xB7. +- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xB8 ..= 0xBF. ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__indexed__bgra_nonpremul( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; ++ } ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_copy_1_1; ++ } ++ return NULL; + +- 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xC0 ..= 0xC7. +- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xC8 ..= 0xCF. +- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xD0 ..= 0xD7. +- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xD8 ..= 0xDF. +- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xE0 ..= 0xE7. +- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xE8 ..= 0xEF. +- 0x03, 0x03, 0x03, 0x03, 0x03, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7. +- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF. +- // 0 1 2 3 4 5 6 7 +- // 8 9 A B C D E F +-}; ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ if (wuffs_private_impl__swizzle_squash_align4_bgr_565_8888( ++ dst_palette.ptr, dst_palette.len, src_palette.ptr, ++ src_palette.len, true) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_bgr_565__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_bgr_565__index_bgra_nonpremul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output // +-wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len) { +- if (s_len == 0) { +- return wuffs_base__make_utf_8__next__output(0, 0); +- } +- uint32_t c = s_ptr[0]; +- switch (wuffs_base__utf_8__byte_length_minus_1[c & 0xFF]) { +- case 0: +- return wuffs_base__make_utf_8__next__output(c, 1); ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ if (wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul__src( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_xxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_xxx__index_bgra_nonpremul__src_over; ++ } ++ return NULL; + +- case 1: +- if (s_len < 2) { +- break; ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; + } +- c = wuffs_base__peek_u16le__no_bounds_check(s_ptr); +- if ((c & 0xC000) != 0x8000) { +- break; ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__index_bgra_nonpremul__src_over; + } +- c = (0x0007C0 & (c << 6)) | (0x00003F & (c >> 8)); +- return wuffs_base__make_utf_8__next__output(c, 2); ++ return NULL; + +- case 2: +- if (s_len < 3) { +- break; ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; + } +- c = wuffs_base__peek_u24le__no_bounds_check(s_ptr); +- if ((c & 0xC0C000) != 0x808000) { +- break; ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxxxxxxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__index_bgra_nonpremul__src_over; + } +- c = (0x00F000 & (c << 12)) | (0x000FC0 & (c >> 2)) | +- (0x00003F & (c >> 16)); +- if ((c <= 0x07FF) || ((0xD800 <= c) && (c <= 0xDFFF))) { +- break; ++ return NULL; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ if (wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul__src( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_xxxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_bgra_premul__index_bgra_nonpremul__src_over; + } +- return wuffs_base__make_utf_8__next__output(c, 3); ++ return NULL; + +- case 3: +- if (s_len < 4) { +- break; ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ if (wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul__src( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_xxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ if (wuffs_private_impl__swizzle_swap_rgbx_bgrx( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_xxx__index_bgra_nonpremul__src_over; + } +- c = wuffs_base__peek_u32le__no_bounds_check(s_ptr); +- if ((c & 0xC0C0C000) != 0x80808000) { +- break; ++ return NULL; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ if (wuffs_private_impl__swizzle_swap_rgbx_bgrx( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; + } +- c = (0x1C0000 & (c << 18)) | (0x03F000 & (c << 4)) | +- (0x000FC0 & (c >> 10)) | (0x00003F & (c >> 24)); +- if ((c <= 0xFFFF) || (0x110000 <= c)) { +- break; ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__index_bgra_nonpremul__src_over; + } +- return wuffs_base__make_utf_8__next__output(c, 4); +- } ++ return NULL; + +- return wuffs_base__make_utf_8__next__output( +- WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1); +-} ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ if (wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul__src( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_xxxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ if (wuffs_private_impl__swizzle_swap_rgbx_bgrx( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ return wuffs_private_impl__swizzle_bgra_premul__index_bgra_nonpremul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output // +-wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len) { +- if (s_len == 0) { +- return wuffs_base__make_utf_8__next__output(0, 0); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ // TODO. ++ break; + } +- const uint8_t* ptr = &s_ptr[s_len - 1]; +- if (*ptr < 0x80) { +- return wuffs_base__make_utf_8__next__output(*ptr, 1); ++ return NULL; ++} + +- } else if (*ptr < 0xC0) { +- const uint8_t* too_far = &s_ptr[(s_len > 4) ? (s_len - 4) : 0]; +- uint32_t n = 1; +- while (ptr != too_far) { +- ptr--; +- n++; +- if (*ptr < 0x80) { +- break; +- } else if (*ptr < 0xC0) { +- continue; ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__indexed__bgra_binary( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; + } +- wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(ptr, n); +- if (o.byte_length != n) { +- break; ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_copy_1_1; + } +- return o; +- } +- } +- +- return wuffs_base__make_utf_8__next__output( +- WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1); +-} ++ return NULL; + +-WUFFS_BASE__MAYBE_STATIC size_t // +-wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) { +- // TODO: possibly optimize the all-ASCII case (4 or 8 bytes at a time). +- // +- // TODO: possibly optimize this by manually inlining the +- // wuffs_base__utf_8__next calls. +- size_t original_len = s_len; +- while (s_len > 0) { +- wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(s_ptr, s_len); +- if ((o.code_point > 0x7F) && (o.byte_length == 1)) { +- break; +- } +- s_ptr += o.byte_length; +- s_len -= o.byte_length; +- } +- return original_len - s_len; +-} ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ if (wuffs_private_impl__swizzle_squash_align4_bgr_565_8888( ++ dst_palette.ptr, dst_palette.len, src_palette.ptr, ++ src_palette.len, false) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr_565__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr_565__index_binary_alpha__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__MAYBE_STATIC size_t // +-wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) { +- // TODO: possibly optimize this by checking 4 or 8 bytes at a time. +- const uint8_t* original_ptr = s_ptr; +- const uint8_t* p = s_ptr; +- const uint8_t* q = s_ptr + s_len; +- for (; (p != q) && ((*p & 0x80) == 0); p++) { +- } +- return (size_t)(p - original_ptr); +-} ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; ++ } ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_xxx__index_binary_alpha__src_over; ++ } ++ return NULL; + +-#endif // !defined(WUFFS_CONFIG__MODULES) || +- // defined(WUFFS_CONFIG__MODULE__BASE) || +- // defined(WUFFS_CONFIG__MODULE__BASE__UTF8) ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; ++ } ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_xxxx__index_binary_alpha__src_over; ++ } ++ return NULL; + +-#ifdef __cplusplus +-} // extern "C" +-#endif ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: ++ if (wuffs_private_impl__slice_u8__copy_from_slice(dst_palette, ++ src_palette) != ++ WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) { ++ return NULL; ++ } ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxxxxxxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_xxxxxxxx__index_binary_alpha__src_over; ++ } ++ return NULL; + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32) ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ if (wuffs_private_impl__swizzle_swap_rgbx_bgrx( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_xxx__index_binary_alpha__src_over; ++ } ++ return NULL; + +-// ---------------- Status Codes Implementations ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ if (wuffs_private_impl__swizzle_swap_rgbx_bgrx( ++ dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr, ++ src_palette.len) != ++ (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) { ++ return NULL; ++ } ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_xxxx__index__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_xxxx__index_binary_alpha__src_over; ++ } ++ return NULL; ++ } ++ return NULL; ++} + +-// ---------------- Private Consts ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__bgr_565( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ return wuffs_private_impl__swizzle_copy_2_2; + +-// ---------------- Private Initializer Prototypes ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ return wuffs_private_impl__swizzle_bgr__bgr_565; + +-// ---------------- Private Function Prototypes ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ return wuffs_private_impl__swizzle_bgrw__bgr_565; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_adler32__hasher__up( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x); ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: ++ return wuffs_private_impl__swizzle_bgrw_4x16le__bgr_565; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_adler32__hasher__up__choosy_default( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x); ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ return wuffs_private_impl__swizzle_rgb__bgr_565; + +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_adler32__hasher__up_arm_neon( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x); +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ return wuffs_private_impl__swizzle_rgbw__bgr_565; ++ } ++ return NULL; ++} + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_adler32__hasher__up_x86_sse42( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__bgr( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ return wuffs_private_impl__swizzle_bgr_565__bgr; + +-// ---------------- VTables ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ return wuffs_private_impl__swizzle_copy_3_3; + +-const wuffs_base__hasher_u32__func_ptrs +-wuffs_adler32__hasher__func_ptrs_for__wuffs_base__hasher_u32 = { +- (uint32_t(*)(const void*))(&wuffs_adler32__hasher__checksum_u32), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_adler32__hasher__get_quirk), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_adler32__hasher__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- wuffs_base__slice_u8))(&wuffs_adler32__hasher__update), +- (uint32_t(*)(void*, +- wuffs_base__slice_u8))(&wuffs_adler32__hasher__update_u32), +-}; ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_bgrw__bgr__x86_sse42; ++ } ++#endif ++ return wuffs_private_impl__swizzle_bgrw__bgr; + +-// ---------------- Initializer Implementations ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE: ++ return wuffs_private_impl__swizzle_bgrw_4x16le__bgr; + +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_adler32__hasher__initialize( +- wuffs_adler32__hasher* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); +- } ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ return wuffs_private_impl__swizzle_swap_rgb_bgr; + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); +- } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_bgrw__rgb__x86_sse42; ++ } + #endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); +- } ++ return wuffs_private_impl__swizzle_bgrw__rgb; + } ++ return NULL; ++} + +- self->private_impl.choosy_up = &wuffs_adler32__hasher__up__choosy_default; ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__bgra_nonpremul( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__Y: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_y__bgra_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_y__bgra_nonpremul__src_over; ++ } ++ return NULL; + +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name = +- wuffs_base__hasher_u32__vtable_name; +- self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers = +- (const void*)(&wuffs_adler32__hasher__func_ptrs_for__wuffs_base__hasher_u32); +- return wuffs_base__make_status(NULL); +-} ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr_565__bgra_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr_565__bgra_nonpremul__src_over; ++ } ++ return NULL; + +-wuffs_adler32__hasher* +-wuffs_adler32__hasher__alloc(void) { +- wuffs_adler32__hasher* x = +- (wuffs_adler32__hasher*)(calloc(sizeof(wuffs_adler32__hasher), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_adler32__hasher__initialize( +- x, sizeof(wuffs_adler32__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; +- } +- return x; +-} ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__bgra_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__bgra_nonpremul__src_over; ++ } ++ return NULL; + +-size_t +-sizeof__wuffs_adler32__hasher(void) { +- return sizeof(wuffs_adler32__hasher); +-} ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_copy_4_4; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__bgra_nonpremul__src_over; ++ } ++ return NULL; + +-// ---------------- Function Implementations ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_nonpremul__src_over; ++ } ++ return NULL; + +-// -------- func adler32.hasher.get_quirk ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_adler32__hasher__get_quirk( +- const wuffs_adler32__hasher* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ // TODO. ++ break; + +- return 0u; +-} ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__rgba_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__rgba_nonpremul__src_over; ++ } ++ return NULL; + +-// -------- func adler32.hasher.set_quirk ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_swap_rgbx_bgrx__x86_sse42; ++ } ++#endif ++ return wuffs_private_impl__swizzle_swap_rgbx_bgrx; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__rgba_nonpremul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_adler32__hasher__set_quirk( +- wuffs_adler32__hasher* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul__src_over; ++ } ++ return NULL; + +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ // TODO. ++ break; ++ } ++ return NULL; + } + +-// -------- func adler32.hasher.update ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__bgra_nonpremul_4x16le( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr_565__bgra_nonpremul_4x16le__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr_565__bgra_nonpremul_4x16le__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_adler32__hasher__update( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return wuffs_base__make_empty_struct(); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__bgra_nonpremul_4x16le__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__bgra_nonpremul_4x16le__src_over; ++ } ++ return NULL; + +- if ( ! self->private_impl.f_started) { +- self->private_impl.f_started = true; +- self->private_impl.f_state = 1u; +- self->private_impl.choosy_up = ( +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_adler32__hasher__up_arm_neon : +-#endif +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_adler32__hasher__up_x86_sse42 : +-#endif +- self->private_impl.choosy_up); +- } +- wuffs_adler32__hasher__up(self, a_x); +- return wuffs_base__make_empty_struct(); +-} ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__bgra_nonpremul_4x16le__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__bgra_nonpremul_4x16le__src_over; ++ } ++ return NULL; + +-// -------- func adler32.hasher.update_u32 ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_copy_8_8; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_nonpremul_4x16le__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_adler32__hasher__update_u32( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return 0; +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return 0; +- } ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul_4x16le__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul_4x16le__src_over; ++ } ++ return NULL; + +- wuffs_adler32__hasher__update(self, a_x); +- return self->private_impl.f_state; +-} ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ // TODO. ++ break; + +-// -------- func adler32.hasher.up ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__rgba_nonpremul_4x16le__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__rgba_nonpremul_4x16le__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_adler32__hasher__up( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x) { +- return (*self->private_impl.choosy_up)(self, a_x); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_rgba_nonpremul__bgra_nonpremul_4x16le__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_rgba_nonpremul__bgra_nonpremul_4x16le__src_over; ++ } ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul_4x16le__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul_4x16le__src_over; ++ } ++ return NULL; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ // TODO. ++ break; ++ } ++ return NULL; + } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_adler32__hasher__up__choosy_default( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x) { +- uint32_t v_s1 = 0; +- uint32_t v_s2 = 0; +- wuffs_base__slice_u8 v_remaining = {0}; +- wuffs_base__slice_u8 v_p = {0}; +- +- v_s1 = ((self->private_impl.f_state) & 0xFFFFu); +- v_s2 = ((self->private_impl.f_state) >> (32u - 16u)); +- while (((uint64_t)(a_x.len)) > 0u) { +- v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0u); +- if (((uint64_t)(a_x.len)) > 5552u) { +- v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5552u); +- a_x = wuffs_base__slice_u8__subslice_j(a_x, 5552u); +- } +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 1; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8); +- while (v_p.ptr < i_end0_p) { +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- } +- v_p.len = 1; +- uint8_t* i_end1_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end1_p) { +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__bgra_premul( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr_565__bgra_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr_565__bgra_premul__src_over; + } +- v_p.len = 0; +- } +- v_s1 %= 65521u; +- v_s2 %= 65521u; +- a_x = v_remaining; +- } +- self->private_impl.f_state = (((v_s2 & 65535u) << 16u) | (v_s1 & 65535u)); +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func adler32.hasher.checksum_u32 +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_adler32__hasher__checksum_u32( +- const wuffs_adler32__hasher* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return self->private_impl.f_state; +-} +- +-// ‼ WUFFS MULTI-FILE SECTION +arm_neon +-// -------- func adler32.hasher.up_arm_neon ++ return NULL; + +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_adler32__hasher__up_arm_neon( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x) { +- uint32_t v_s1 = 0; +- uint32_t v_s2 = 0; +- wuffs_base__slice_u8 v_remaining = {0}; +- wuffs_base__slice_u8 v_p = {0}; +- uint8x16_t v_p__left = {0}; +- uint8x16_t v_p_right = {0}; +- uint32x4_t v_v1 = {0}; +- uint32x4_t v_v2 = {0}; +- uint16x8_t v_col0 = {0}; +- uint16x8_t v_col1 = {0}; +- uint16x8_t v_col2 = {0}; +- uint16x8_t v_col3 = {0}; +- uint32x2_t v_sum1 = {0}; +- uint32x2_t v_sum2 = {0}; +- uint32x2_t v_sum12 = {0}; +- uint32_t v_num_iterate_bytes = 0; +- uint64_t v_tail_index = 0; ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__bgra_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__bgra_premul__src_over; ++ } ++ return NULL; + +- v_s1 = ((self->private_impl.f_state) & 0xFFFFu); +- v_s2 = ((self->private_impl.f_state) >> (32u - 16u)); +- while ((((uint64_t)(a_x.len)) > 0u) && ((15u & ((uint32_t)(0xFFFu & (uintptr_t)(a_x.ptr)))) != 0u)) { +- v_s1 += ((uint32_t)(a_x.ptr[0u])); +- v_s2 += v_s1; +- a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); +- } +- v_s1 %= 65521u; +- v_s2 %= 65521u; +- while (((uint64_t)(a_x.len)) > 0u) { +- v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0u); +- if (((uint64_t)(a_x.len)) > 5536u) { +- v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5536u); +- a_x = wuffs_base__slice_u8__subslice_j(a_x, 5536u); +- } +- v_num_iterate_bytes = ((uint32_t)((((uint64_t)(a_x.len)) & 4294967264u))); +- v_s2 += ((uint32_t)(v_s1 * v_num_iterate_bytes)); +- v_v1 = vdupq_n_u32(0u); +- v_v2 = vdupq_n_u32(0u); +- v_col0 = vdupq_n_u16(0u); +- v_col1 = vdupq_n_u16(0u); +- v_col2 = vdupq_n_u16(0u); +- v_col3 = vdupq_n_u16(0u); +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 32; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32); +- while (v_p.ptr < i_end0_p) { +- v_p__left = vld1q_u8(v_p.ptr); +- v_p_right = vld1q_u8(v_p.ptr + 16u); +- v_v2 = vaddq_u32(v_v2, v_v1); +- v_v1 = vpadalq_u16(v_v1, vpadalq_u8(vpaddlq_u8(v_p__left), v_p_right)); +- v_col0 = vaddw_u8(v_col0, vget_low_u8(v_p__left)); +- v_col1 = vaddw_u8(v_col1, vget_high_u8(v_p__left)); +- v_col2 = vaddw_u8(v_col2, vget_low_u8(v_p_right)); +- v_col3 = vaddw_u8(v_col3, vget_high_u8(v_p_right)); +- v_p.ptr += 32; ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__bgra_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__bgra_premul__src_over; + } +- v_p.len = 0; +- } +- v_v2 = vshlq_n_u32(v_v2, 5u); +- v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col0), ((uint16x4_t){32u, 31u, 30u, 29u})); +- v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col0), ((uint16x4_t){28u, 27u, 26u, 25u})); +- v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col1), ((uint16x4_t){24u, 23u, 22u, 21u})); +- v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col1), ((uint16x4_t){20u, 19u, 18u, 17u})); +- v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col2), ((uint16x4_t){16u, 15u, 14u, 13u})); +- v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col2), ((uint16x4_t){12u, 11u, 10u, 9u})); +- v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col3), ((uint16x4_t){8u, 7u, 6u, 5u})); +- v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col3), ((uint16x4_t){4u, 3u, 2u, 1u})); +- v_sum1 = vpadd_u32(vget_low_u32(v_v1), vget_high_u32(v_v1)); +- v_sum2 = vpadd_u32(vget_low_u32(v_v2), vget_high_u32(v_v2)); +- v_sum12 = vpadd_u32(v_sum1, v_sum2); +- v_s1 += vget_lane_u32(v_sum12, 0u); +- v_s2 += vget_lane_u32(v_sum12, 1u); +- v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551584u); +- if (v_tail_index < ((uint64_t)(a_x.len))) { +- { +- wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index); +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 1; +- uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end0_p) { +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- } +- v_p.len = 0; ++ return NULL; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__bgra_premul__src_over; + } +- } +- v_s1 %= 65521u; +- v_s2 %= 65521u; +- a_x = v_remaining; +- } +- self->private_impl.f_state = (((v_s2 & 65535u) << 16u) | (v_s1 & 65535u)); +- return wuffs_base__make_empty_struct(); +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-// ‼ WUFFS MULTI-FILE SECTION -arm_neon ++ return NULL; + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-// -------- func adler32.hasher.up_x86_sse42 ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_copy_4_4; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__bgra_premul__src_over; ++ } ++ return NULL; + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_adler32__hasher__up_x86_sse42( +- wuffs_adler32__hasher* self, +- wuffs_base__slice_u8 a_x) { +- uint32_t v_s1 = 0; +- uint32_t v_s2 = 0; +- wuffs_base__slice_u8 v_remaining = {0}; +- wuffs_base__slice_u8 v_p = {0}; +- __m128i v_zeroes = {0}; +- __m128i v_ones = {0}; +- __m128i v_weights__left = {0}; +- __m128i v_weights_right = {0}; +- __m128i v_q__left = {0}; +- __m128i v_q_right = {0}; +- __m128i v_v1 = {0}; +- __m128i v_v2 = {0}; +- __m128i v_v2j = {0}; +- __m128i v_v2k = {0}; +- uint32_t v_num_iterate_bytes = 0; +- uint64_t v_tail_index = 0; ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__rgba_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__rgba_premul__src_over; ++ } ++ return NULL; + +- v_zeroes = _mm_set1_epi16((int16_t)(0u)); +- v_ones = _mm_set1_epi16((int16_t)(1u)); +- v_weights__left = _mm_set_epi8((int8_t)(17u), (int8_t)(18u), (int8_t)(19u), (int8_t)(20u), (int8_t)(21u), (int8_t)(22u), (int8_t)(23u), (int8_t)(24u), (int8_t)(25u), (int8_t)(26u), (int8_t)(27u), (int8_t)(28u), (int8_t)(29u), (int8_t)(30u), (int8_t)(31u), (int8_t)(32u)); +- v_weights_right = _mm_set_epi8((int8_t)(1u), (int8_t)(2u), (int8_t)(3u), (int8_t)(4u), (int8_t)(5u), (int8_t)(6u), (int8_t)(7u), (int8_t)(8u), (int8_t)(9u), (int8_t)(10u), (int8_t)(11u), (int8_t)(12u), (int8_t)(13u), (int8_t)(14u), (int8_t)(15u), (int8_t)(16u)); +- v_s1 = ((self->private_impl.f_state) & 0xFFFFu); +- v_s2 = ((self->private_impl.f_state) >> (32u - 16u)); +- while (((uint64_t)(a_x.len)) > 0u) { +- v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0u); +- if (((uint64_t)(a_x.len)) > 5536u) { +- v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5536u); +- a_x = wuffs_base__slice_u8__subslice_j(a_x, 5536u); +- } +- v_num_iterate_bytes = ((uint32_t)((((uint64_t)(a_x.len)) & 4294967264u))); +- v_s2 += ((uint32_t)(v_s1 * v_num_iterate_bytes)); +- v_v1 = _mm_setzero_si128(); +- v_v2j = _mm_setzero_si128(); +- v_v2k = _mm_setzero_si128(); +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 32; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32); +- while (v_p.ptr < i_end0_p) { +- v_q__left = _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr)); +- v_q_right = _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16u)); +- v_v2j = _mm_add_epi32(v_v2j, v_v1); +- v_v1 = _mm_add_epi32(v_v1, _mm_sad_epu8(v_q__left, v_zeroes)); +- v_v1 = _mm_add_epi32(v_v1, _mm_sad_epu8(v_q_right, v_zeroes)); +- v_v2k = _mm_add_epi32(v_v2k, _mm_madd_epi16(v_ones, _mm_maddubs_epi16(v_q__left, v_weights__left))); +- v_v2k = _mm_add_epi32(v_v2k, _mm_madd_epi16(v_ones, _mm_maddubs_epi16(v_q_right, v_weights_right))); +- v_p.ptr += 32; ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__rgba_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__rgba_premul__src_over; + } +- v_p.len = 0; +- } +- v_v1 = _mm_add_epi32(v_v1, _mm_shuffle_epi32(v_v1, (int32_t)(177u))); +- v_v1 = _mm_add_epi32(v_v1, _mm_shuffle_epi32(v_v1, (int32_t)(78u))); +- v_s1 += ((uint32_t)(_mm_cvtsi128_si32(v_v1))); +- v_v2 = _mm_add_epi32(v_v2k, _mm_slli_epi32(v_v2j, (int32_t)(5u))); +- v_v2 = _mm_add_epi32(v_v2, _mm_shuffle_epi32(v_v2, (int32_t)(177u))); +- v_v2 = _mm_add_epi32(v_v2, _mm_shuffle_epi32(v_v2, (int32_t)(78u))); +- v_s2 += ((uint32_t)(_mm_cvtsi128_si32(v_v2))); +- v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551584u); +- if (v_tail_index < ((uint64_t)(a_x.len))) { +- { +- wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index); +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 1; +- uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end0_p) { +- v_s1 += ((uint32_t)(v_p.ptr[0u])); +- v_s2 += v_s1; +- v_p.ptr += 1; +- } +- v_p.len = 0; ++ return NULL; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_swap_rgbx_bgrx__x86_sse42; ++ } ++#endif ++ return wuffs_private_impl__swizzle_swap_rgbx_bgrx; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__rgba_premul__src_over; + } +- } +- v_s1 %= 65521u; +- v_s2 %= 65521u; +- a_x = v_remaining; ++ return NULL; + } +- self->private_impl.f_state = (((v_s2 & 65535u) << 16u) | (v_s1 & 65535u)); +- return wuffs_base__make_empty_struct(); ++ return NULL; + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32) ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__bgrx( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__Y: ++ return wuffs_private_impl__swizzle_y__bgrx; + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP) ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ return wuffs_private_impl__swizzle_bgr_565__bgrx; + +-// ---------------- Status Codes Implementations ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ return wuffs_private_impl__swizzle_xxx__xxxx; + +-const char wuffs_bmp__error__bad_header[] = "#bmp: bad header"; +-const char wuffs_bmp__error__bad_rle_compression[] = "#bmp: bad RLE compression"; +-const char wuffs_bmp__error__truncated_input[] = "#bmp: truncated input"; +-const char wuffs_bmp__error__unsupported_bmp_file[] = "#bmp: unsupported BMP file"; +-const char wuffs_bmp__note__internal_note_short_read[] = "@bmp: internal note: short read"; ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ return wuffs_private_impl__swizzle_bgrw__bgrx; + +-// ---------------- Private Consts ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ return wuffs_private_impl__swizzle_bgrw_4x16le__bgrx; + +-#define WUFFS_BMP__COMPRESSION_NONE 0 ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ return wuffs_private_impl__swizzle_copy_4_4; + +-#define WUFFS_BMP__COMPRESSION_RLE8 1 ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ return wuffs_private_impl__swizzle_bgr__rgbx; + +-#define WUFFS_BMP__COMPRESSION_RLE4 2 ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ return wuffs_private_impl__swizzle_bgrw__rgbx; ++ } ++ return NULL; ++} + +-#define WUFFS_BMP__COMPRESSION_BITFIELDS 3 ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__rgb( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ return wuffs_private_impl__swizzle_bgr_565__rgb; + +-#define WUFFS_BMP__COMPRESSION_JPEG 4 ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ return wuffs_private_impl__swizzle_swap_rgb_bgr; + +-#define WUFFS_BMP__COMPRESSION_PNG 5 ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_bgrw__rgb__x86_sse42; ++ } ++#endif ++ return wuffs_private_impl__swizzle_bgrw__rgb; + +-#define WUFFS_BMP__COMPRESSION_ALPHABITFIELDS 6 ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ return wuffs_private_impl__swizzle_bgrw_4x16le__rgb; + +-#define WUFFS_BMP__COMPRESSION_LOW_BIT_DEPTH 256 ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ return wuffs_private_impl__swizzle_copy_3_3; + +-#define WUFFS_BMP__RLE_STATE_NEUTRAL 0 ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_bgrw__bgr__x86_sse42; ++ } ++#endif ++ return wuffs_private_impl__swizzle_bgrw__bgr; ++ } ++ return NULL; ++} + +-#define WUFFS_BMP__RLE_STATE_RUN 1 ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__rgba_nonpremul( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr_565__rgba_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr_565__rgba_nonpremul__src_over; ++ } ++ return NULL; + +-#define WUFFS_BMP__RLE_STATE_ESCAPE 2 ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__rgba_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__rgba_nonpremul__src_over; ++ } ++ return NULL; + +-#define WUFFS_BMP__RLE_STATE_LITERAL 3 ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_swap_rgbx_bgrx__x86_sse42; ++ } ++#endif ++ return wuffs_private_impl__swizzle_swap_rgbx_bgrx; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__rgba_nonpremul__src_over; ++ } ++ return NULL; + +-#define WUFFS_BMP__RLE_STATE_DELTA_X 4 ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__rgba_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__rgba_nonpremul__src_over; ++ } ++ return NULL; + +-#define WUFFS_BMP__RLE_STATE_DELTA_Y 5 ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__rgba_nonpremul__src_over; ++ } ++ return NULL; + +-// ---------------- Private Initializer Prototypes ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ // TODO. ++ break; + +-// ---------------- Private Function Prototypes ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__bgra_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__bgra_nonpremul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__do_decode_image_config( +- wuffs_bmp__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_copy_4_4; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__bgra_nonpremul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__do_decode_frame_config( +- wuffs_bmp__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__bgra_nonpremul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__do_decode_frame( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ // TODO. ++ break; ++ } ++ return NULL; ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__swizzle_none( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src); ++static inline WUFFS_BASE__FORCE_INLINE wuffs_base__pixel_swizzler__func // ++wuffs_private_impl__pixel_swizzler__prepare__rgba_premul( ++ wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ switch (dst_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr_565__rgba_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr_565__rgba_premul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__swizzle_rle( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src); ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__rgba_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__rgba_premul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__swizzle_bitfields( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src); ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__rgba_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__rgba_premul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__swizzle_low_bit_depth( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__do_tell_me_more( +- wuffs_bmp__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src); ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__rgba_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul_4x16le__rgba_premul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__read_palette( +- wuffs_bmp__decoder* self, +- wuffs_base__io_buffer* a_src); ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ if (wuffs_base__cpu_arch__have_x86_sse42()) { ++ return wuffs_private_impl__swizzle_swap_rgbx_bgrx__x86_sse42; ++ } ++#endif ++ return wuffs_private_impl__swizzle_swap_rgbx_bgrx; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__rgba_premul__src_over; ++ } ++ return NULL; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__process_masks( +- wuffs_bmp__decoder* self); ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgr__bgra_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgr__bgra_premul__src_over; ++ } ++ return NULL; + +-// ---------------- VTables ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__bgra_premul__src; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_nonpremul__bgra_premul__src_over; ++ } ++ return NULL; + +-const wuffs_base__image_decoder__func_ptrs +-wuffs_bmp__decoder__func_ptrs_for__wuffs_base__image_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__pixel_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__pixel_blend, +- wuffs_base__slice_u8, +- wuffs_base__decode_frame_options*))(&wuffs_bmp__decoder__decode_frame), +- (wuffs_base__status(*)(void*, +- wuffs_base__frame_config*, +- wuffs_base__io_buffer*))(&wuffs_bmp__decoder__decode_frame_config), +- (wuffs_base__status(*)(void*, +- wuffs_base__image_config*, +- wuffs_base__io_buffer*))(&wuffs_bmp__decoder__decode_image_config), +- (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_bmp__decoder__frame_dirty_rect), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_bmp__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_bmp__decoder__history_retain_length), +- (uint32_t(*)(const void*))(&wuffs_bmp__decoder__num_animation_loops), +- (uint64_t(*)(const void*))(&wuffs_bmp__decoder__num_decoded_frame_configs), +- (uint64_t(*)(const void*))(&wuffs_bmp__decoder__num_decoded_frames), +- (wuffs_base__status(*)(void*, +- uint64_t, +- uint64_t))(&wuffs_bmp__decoder__restart_frame), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_bmp__decoder__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- uint32_t, +- bool))(&wuffs_bmp__decoder__set_report_metadata), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__more_information*, +- wuffs_base__io_buffer*))(&wuffs_bmp__decoder__tell_me_more), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_bmp__decoder__workbuf_len), +-}; ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ return wuffs_private_impl__swizzle_copy_4_4; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ return wuffs_private_impl__swizzle_bgra_premul__bgra_premul__src_over; ++ } ++ return NULL; ++ } ++ return NULL; ++} + +-// ---------------- Initializer Implementations ++// -------- + +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_bmp__decoder__initialize( +- wuffs_bmp__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status // ++wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_format dst_pixfmt, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__pixel_format src_pixfmt, ++ wuffs_base__slice_u8 src_palette, ++ wuffs_base__pixel_blend blend) { ++ if (!p) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); +- } ++ p->private_impl.func = NULL; ++ p->private_impl.transparent_black_func = NULL; ++ p->private_impl.dst_pixfmt_bytes_per_pixel = 0; ++ p->private_impl.src_pixfmt_bytes_per_pixel = 0; + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++ // ---- ++ ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ENABLE_ALLOWLIST) ++ switch (dst_pixfmt.repr) { ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGR_565) ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ break; + #endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); +- } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGR) ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ break; + #endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); +- } ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGRA_NONPREMUL) ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGRA_NONPREMUL_4X16LE) ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGRA_PREMUL) ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_RGB) ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_RGBA_NONPREMUL) ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_RGBA_PREMUL) ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ break; ++#endif ++ default: ++ return wuffs_base__make_status( ++ wuffs_base__error__disabled_by_wuffs_config_dst_pixel_format_enable_allowlist); + } ++#endif // defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ENABLE_ALLOWLIST) + +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = +- wuffs_base__image_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = +- (const void*)(&wuffs_bmp__decoder__func_ptrs_for__wuffs_base__image_decoder); +- return wuffs_base__make_status(NULL); +-} ++ // ---- + +-wuffs_bmp__decoder* +-wuffs_bmp__decoder__alloc(void) { +- wuffs_bmp__decoder* x = +- (wuffs_bmp__decoder*)(calloc(sizeof(wuffs_bmp__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_bmp__decoder__initialize( +- x, sizeof(wuffs_bmp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; ++ wuffs_base__pixel_swizzler__func func = NULL; ++ wuffs_base__pixel_swizzler__transparent_black_func transparent_black_func = ++ NULL; ++ ++ uint32_t dst_pixfmt_bits_per_pixel = ++ wuffs_base__pixel_format__bits_per_pixel(&dst_pixfmt); ++ if ((dst_pixfmt_bits_per_pixel == 0) || ++ ((dst_pixfmt_bits_per_pixel & 7) != 0)) { ++ return wuffs_base__make_status( ++ wuffs_base__error__unsupported_pixel_swizzler_option); + } +- return x; +-} + +-size_t +-sizeof__wuffs_bmp__decoder(void) { +- return sizeof(wuffs_bmp__decoder); +-} ++ uint32_t src_pixfmt_bits_per_pixel = ++ wuffs_base__pixel_format__bits_per_pixel(&src_pixfmt); ++ if ((src_pixfmt_bits_per_pixel == 0) || ++ ((src_pixfmt_bits_per_pixel & 7) != 0)) { ++ return wuffs_base__make_status( ++ wuffs_base__error__unsupported_pixel_swizzler_option); ++ } + +-// ---------------- Function Implementations ++ // TODO: support many more formats. + +-// -------- func bmp.decoder.get_quirk ++ switch (blend) { ++ case WUFFS_BASE__PIXEL_BLEND__SRC: ++ transparent_black_func = ++ wuffs_private_impl__swizzle_transparent_black_src; ++ break; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_bmp__decoder__get_quirk( +- const wuffs_bmp__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ case WUFFS_BASE__PIXEL_BLEND__SRC_OVER: ++ transparent_black_func = ++ wuffs_private_impl__swizzle_transparent_black_src_over; ++ break; + } + +- return 0u; +-} ++ switch (src_pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__Y: ++ func = wuffs_private_impl__pixel_swizzler__prepare__y( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; + +-// -------- func bmp.decoder.set_quirk ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: ++ func = wuffs_private_impl__pixel_swizzler__prepare__y_16be( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_bmp__decoder__set_quirk( +- wuffs_bmp__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ case WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL: ++ func = wuffs_private_impl__pixel_swizzler__prepare__ya_nonpremul( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: ++ func = ++ wuffs_private_impl__pixel_swizzler__prepare__indexed__bgra_nonpremul( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: ++ func = wuffs_private_impl__pixel_swizzler__prepare__indexed__bgra_binary( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ func = wuffs_private_impl__pixel_swizzler__prepare__bgr_565( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ func = wuffs_private_impl__pixel_swizzler__prepare__bgr( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ func = wuffs_private_impl__pixel_swizzler__prepare__bgra_nonpremul( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ func = wuffs_private_impl__pixel_swizzler__prepare__bgra_nonpremul_4x16le( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ func = wuffs_private_impl__pixel_swizzler__prepare__bgra_premul( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ func = wuffs_private_impl__pixel_swizzler__prepare__bgrx( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ func = wuffs_private_impl__pixel_swizzler__prepare__rgb( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ func = wuffs_private_impl__pixel_swizzler__prepare__rgba_nonpremul( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; ++ ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ func = wuffs_private_impl__pixel_swizzler__prepare__rgba_premul( ++ p, dst_pixfmt, dst_palette, src_palette, blend); ++ break; + } + +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ p->private_impl.func = func; ++ p->private_impl.transparent_black_func = transparent_black_func; ++ p->private_impl.dst_pixfmt_bytes_per_pixel = dst_pixfmt_bits_per_pixel / 8; ++ p->private_impl.src_pixfmt_bytes_per_pixel = src_pixfmt_bits_per_pixel / 8; ++ return wuffs_base__make_status( ++ func ? NULL : wuffs_base__error__unsupported_pixel_swizzler_option); + } + +-// -------- func bmp.decoder.decode_image_config +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_bmp__decoder__decode_image_config( +- wuffs_bmp__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++WUFFS_BASE__MAYBE_STATIC uint64_t // ++wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader( ++ const wuffs_base__pixel_swizzler* p, ++ uint32_t up_to_num_pixels, ++ wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 dst_palette, ++ const uint8_t** ptr_iop_r, ++ const uint8_t* io2_r) { ++ if (p && p->private_impl.func) { ++ const uint8_t* iop_r = *ptr_iop_r; ++ uint64_t src_len = wuffs_base__u64__min( ++ ((uint64_t)up_to_num_pixels) * ++ ((uint64_t)p->private_impl.src_pixfmt_bytes_per_pixel), ++ ((uint64_t)(io2_r - iop_r))); ++ uint64_t n = ++ (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr, ++ dst_palette.len, iop_r, (size_t)src_len); ++ *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel; ++ return n; + } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ return 0; ++} ++ ++WUFFS_BASE__MAYBE_STATIC uint64_t // ++wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( ++ const wuffs_base__pixel_swizzler* p, ++ wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 dst_palette, ++ const uint8_t** ptr_iop_r, ++ const uint8_t* io2_r) { ++ if (p && p->private_impl.func) { ++ const uint8_t* iop_r = *ptr_iop_r; ++ uint64_t src_len = ((uint64_t)(io2_r - iop_r)); ++ uint64_t n = ++ (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr, ++ dst_palette.len, iop_r, (size_t)src_len); ++ *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel; ++ return n; + } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ return 0; ++} ++ ++WUFFS_BASE__MAYBE_STATIC uint64_t // ++wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice( ++ const wuffs_base__pixel_swizzler* p, ++ wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 dst_palette, ++ wuffs_base__slice_u8 src) { ++ if (p && p->private_impl.func) { ++ return (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr, ++ dst_palette.len, src.ptr, src.len); + } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ return 0; ++} ++ ++WUFFS_BASE__MAYBE_STATIC uint64_t // ++wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black( ++ const wuffs_base__pixel_swizzler* p, ++ wuffs_base__slice_u8 dst, ++ wuffs_base__slice_u8 dst_palette, ++ uint64_t num_pixels) { ++ if (p && p->private_impl.transparent_black_func) { ++ return (*p->private_impl.transparent_black_func)( ++ dst.ptr, dst.len, dst_palette.ptr, dst_palette.len, num_pixels, ++ p->private_impl.dst_pixfmt_bytes_per_pixel); + } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ return 0; ++} + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++// -------- + +- uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") ++static void // ++wuffs_private_impl__swizzle_ycc__convert_3_bgrx_x86_avx2( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2); + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_bmp__decoder__do_decode_image_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_bmp__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") ++static void // ++wuffs_private_impl__swizzle_ycc__convert_3_rgbx_x86_avx2( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2); + +- ok: +- self->private_impl.p_decode_image_config[0] = 0; +- goto exit; +- } ++#if defined(__GNUC__) && !defined(__clang__) ++// No-op. ++#else ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h2v2_triangle_x86_avx2( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor, ++ size_t src_len, ++ uint32_t h1v2_bias_ignored, ++ bool first_column, ++ bool last_column); ++#endif ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) + +- goto suspend; +- suspend: +- self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++// -------- + +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; ++static inline uint32_t // ++wuffs_private_impl__u32__max_of_4(uint32_t a, ++ uint32_t b, ++ uint32_t c, ++ uint32_t d) { ++ return wuffs_base__u32__max( // ++ wuffs_base__u32__max(a, b), // ++ wuffs_base__u32__max(c, d)); + } + +-// -------- func bmp.decoder.do_decode_image_config ++static inline uint32_t // ++wuffs_private_impl__u32__min_of_5(uint32_t a, ++ uint32_t b, ++ uint32_t c, ++ uint32_t d, ++ uint32_t e) { ++ return wuffs_base__u32__min( // ++ wuffs_base__u32__min( // ++ wuffs_base__u32__min(a, b), // ++ wuffs_base__u32__min(c, d)), // ++ e); ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__do_decode_image_config( +- wuffs_bmp__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++// -------- + +- uint32_t v_magic = 0; +- uint32_t v_width = 0; +- uint32_t v_height = 0; +- uint32_t v_planes = 0; +- uint32_t v_dst_pixfmt = 0; +- uint32_t v_byte_width = 0; ++typedef void (*wuffs_private_impl__swizzle_ycc__convert_4_func)( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2, ++ const uint8_t* up3); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++static void // ++wuffs_private_impl__swizzle_cmyk__convert_4_general( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2, ++ const uint8_t* up3) { ++ for (; x < x_end; x++) { ++ // It's called CMYK but, but for Adobe CMYK JPEG images in practice, it's ++ // RGBW: 0xFFu means no ink instead of full ink. Note that a double ++ // inversion is a no-op, so inversions might be implicit in the code below. ++ uint32_t r = ((uint32_t)(*up0++)); ++ uint32_t g = ((uint32_t)(*up1++)); ++ uint32_t b = ((uint32_t)(*up2++)); ++ uint32_t w = ((uint32_t)(*up3++)); ++ r = ((r * w) + 0x7Fu) / 0xFFu; ++ g = ((g * w) + 0x7Fu) / 0xFFu; ++ b = ((b * w) + 0x7Fu) / 0xFFu; ++ wuffs_base__pixel_buffer__set_color_u32_at( ++ dst, x, y, 0xFF000000u | (r << 16u) | (g << 8u) | (b << 0u)); + } ++} + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++static void // ++wuffs_private_impl__swizzle_ycck__convert_4_general( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2, ++ const uint8_t* up3) { ++ for (; x < x_end; x++) { ++ // We invert once again: 0xFFu means no ink instead of full ink. ++ uint32_t color = // ++ wuffs_base__color_ycc__as__color_u32( // ++ *up0++, *up1++, *up2++); ++ uint32_t r = 0xFFu - (0xFFu & (color >> 16u)); ++ uint32_t g = 0xFFu - (0xFFu & (color >> 8u)); ++ uint32_t b = 0xFFu - (0xFFu & (color >> 0u)); ++ uint32_t w = ((uint32_t)(*up3++)); ++ r = ((r * w) + 0x7Fu) / 0xFFu; ++ g = ((g * w) + 0x7Fu) / 0xFFu; ++ b = ((b * w) + 0x7Fu) / 0xFFu; ++ wuffs_base__pixel_buffer__set_color_u32_at( ++ dst, x, y, 0xFF000000u | (r << 16u) | (g << 8u) | (b << 0u)); ++ } ++} + +- if ((self->private_impl.f_call_sequence != 0u) || (self->private_impl.f_io_redirect_fourcc == 1u)) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } else if (self->private_impl.f_io_redirect_fourcc != 0u) { +- status = wuffs_base__make_status(wuffs_base__note__i_o_redirect); +- goto ok; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; +- if (num_bits_0 == 8) { +- t_0 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)) << 56; +- } +- } +- v_magic = t_0; +- } +- if (v_magic != 19778u) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; +- } +- self->private_data.s_do_decode_image_config[0].scratch = 8u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (self->private_data.s_do_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++// -------- ++ ++typedef void (*wuffs_private_impl__swizzle_ycc__convert_3_func)( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2); ++ ++static void // ++wuffs_private_impl__swizzle_rgb__convert_3_general( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2) { ++ for (; x < x_end; x++) { ++ uint32_t color = 0xFF000000u | // ++ (((uint32_t)(*up0++)) << 16u) | // ++ (((uint32_t)(*up1++)) << 8u) | // ++ (((uint32_t)(*up2++)) << 0u); ++ wuffs_base__pixel_buffer__set_color_u32_at(dst, x, y, color); ++ } ++} ++ ++static void // ++wuffs_private_impl__swizzle_ycc__convert_3_general( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2) { ++ for (; x < x_end; x++) { ++ uint32_t color = // ++ wuffs_base__color_ycc__as__color_u32( // ++ *up0++, *up1++, *up2++); ++ wuffs_base__pixel_buffer__set_color_u32_at(dst, x, y, color); ++ } ++} ++ ++static void // ++wuffs_private_impl__swizzle_ycc__convert_3_bgrx(wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2) { ++ size_t dst_stride = dst->private_impl.planes[0].stride; ++ uint8_t* dst_iter = dst->private_impl.planes[0].ptr + ++ (dst_stride * ((size_t)y)) + (4u * ((size_t)x)); ++ ++ for (; x < x_end; x++) { ++ uint32_t color = // ++ wuffs_base__color_ycc__as__color_u32( // ++ *up0++, *up1++, *up2++); ++ wuffs_base__poke_u32le__no_bounds_check(dst_iter, color); ++ dst_iter += 4u; ++ } ++} ++ ++static void // ++wuffs_private_impl__swizzle_ycc__convert_3_rgbx(wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2) { ++ size_t dst_stride = dst->private_impl.planes[0].stride; ++ uint8_t* dst_iter = dst->private_impl.planes[0].ptr + ++ (dst_stride * ((size_t)y)) + (4u * ((size_t)x)); ++ ++ for (; x < x_end; x++) { ++ uint32_t color = // ++ wuffs_base__color_ycc__as__color_u32_abgr( // ++ *up0++, *up1++, *up2++); ++ wuffs_base__poke_u32le__no_bounds_check(dst_iter, color); ++ dst_iter += 4u; ++ } ++} ++ ++// -------- ++ ++// wuffs_private_impl__swizzle_ycc__upsample_func upsamples to a destination ++// slice at least 480 (YCCK) or 672 (YCC) bytes long and whose src_len ++// (multiplied by 1, 2, 3 or 4) is positive but no more than that. This 480 or ++// 672 length is just under 1/4 or 1/3 of the scratch_buffer_2k slice length. ++// Both (480 * 4) = 1920 and (672 * 3) = 2016 are less than 2048. ++// ++// 480 and 672 are nice round numbers because a JPEG MCU is 1, 2, 3 or 4 blocks ++// wide and each block is 8 pixels wide. We have: ++// 480 = 1 * 8 * 60, 672 = 1 * 8 * 84 ++// 480 = 2 * 8 * 30, 672 = 2 * 8 * 42 ++// 480 = 3 * 8 * 20, 672 = 3 * 8 * 28 ++// 480 = 4 * 8 * 15, 672 = 4 * 8 * 21 ++// ++// Box filters are equivalent to nearest neighbor upsampling. These ignore the ++// src_ptr_minor, h1v2_bias, first_column and last_column arguments. ++// ++// Triangle filters use a 3:1 ratio (in 1 dimension), or 9:3:3:1 (in 2 ++// dimensions), which is higher quality (less blocky) but also higher ++// computational effort. ++// ++// In theory, we could use triangle filters for any (inv_h, inv_v) combination. ++// In practice, matching libjpeg-turbo, we only implement it for the common ++// chroma subsampling ratios (YCC420, YCC422 or YCC440), corresponding to an ++// (inv_h, inv_v) pair of (2, 2), (2, 1) or (1, 2). ++typedef const uint8_t* (*wuffs_private_impl__swizzle_ycc__upsample_func)( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, // Nearest row. ++ const uint8_t* src_ptr_minor, // Adjacent row, alternating above or below. ++ size_t src_len, ++ uint32_t h1v2_bias, ++ bool first_column, ++ bool last_column); ++ ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h1vn_box( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor_ignored, ++ size_t src_len, ++ uint32_t h1v2_bias_ignored, ++ bool first_column_ignored, ++ bool last_column_ignored) { ++ return src_ptr_major; ++} ++ ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h2vn_box( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor_ignored, ++ size_t src_len, ++ uint32_t h1v2_bias_ignored, ++ bool first_column_ignored, ++ bool last_column_ignored) { ++ uint8_t* dp = dst_ptr; ++ const uint8_t* sp = src_ptr_major; ++ while (src_len--) { ++ uint8_t sv = *sp++; ++ *dp++ = sv; ++ *dp++ = sv; ++ } ++ return dst_ptr; ++} ++ ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h3vn_box( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor_ignored, ++ size_t src_len, ++ uint32_t h1v2_bias_ignored, ++ bool first_column_ignored, ++ bool last_column_ignored) { ++ uint8_t* dp = dst_ptr; ++ const uint8_t* sp = src_ptr_major; ++ while (src_len--) { ++ uint8_t sv = *sp++; ++ *dp++ = sv; ++ *dp++ = sv; ++ *dp++ = sv; ++ } ++ return dst_ptr; ++} ++ ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h4vn_box( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor_ignored, ++ size_t src_len, ++ uint32_t h1v2_bias_ignored, ++ bool first_column_ignored, ++ bool last_column_ignored) { ++ uint8_t* dp = dst_ptr; ++ const uint8_t* sp = src_ptr_major; ++ while (src_len--) { ++ uint8_t sv = *sp++; ++ *dp++ = sv; ++ *dp++ = sv; ++ *dp++ = sv; ++ *dp++ = sv; ++ } ++ return dst_ptr; ++} ++ ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h1v2_triangle( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor, ++ size_t src_len, ++ uint32_t h1v2_bias, ++ bool first_column, ++ bool last_column) { ++ uint8_t* dp = dst_ptr; ++ const uint8_t* sp_major = src_ptr_major; ++ const uint8_t* sp_minor = src_ptr_minor; ++ while (src_len--) { ++ *dp++ = (uint8_t)(((3u * ((uint32_t)(*sp_major++))) + // ++ (1u * ((uint32_t)(*sp_minor++))) + // ++ h1v2_bias) >> ++ 2u); ++ } ++ return dst_ptr; ++} ++ ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h2v1_triangle( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor, ++ size_t src_len, ++ uint32_t h1v2_bias_ignored, ++ bool first_column, ++ bool last_column) { ++ uint8_t* dp = dst_ptr; ++ const uint8_t* sp = src_ptr_major; ++ ++ if (first_column) { ++ src_len--; ++ if ((src_len <= 0u) && last_column) { ++ uint8_t sv = *sp++; ++ *dp++ = sv; ++ *dp++ = sv; ++ return dst_ptr; + } +- iop_a_src += self->private_data.s_do_decode_image_config[0].scratch; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; +- if (num_bits_1 == 24) { +- t_1 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)) << 56; +- } +- } +- self->private_impl.f_padding = t_1; ++ uint32_t svp1 = sp[+1]; ++ uint8_t sv = *sp++; ++ *dp++ = sv; ++ *dp++ = (uint8_t)(((3u * (uint32_t)sv) + svp1 + 2u) >> 2u); ++ if (src_len <= 0u) { ++ return dst_ptr; + } +- if (self->private_impl.f_padding < 14u) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; ++ } ++ ++ if (last_column) { ++ src_len--; ++ } ++ ++ for (; src_len > 0u; src_len--) { ++ uint32_t svm1 = sp[-1]; ++ uint32_t svp1 = sp[+1]; ++ uint32_t sv3 = 3u * (uint32_t)(*sp++); ++ *dp++ = (uint8_t)((sv3 + svm1 + 1u) >> 2u); ++ *dp++ = (uint8_t)((sv3 + svp1 + 2u) >> 2u); ++ } ++ ++ if (last_column) { ++ uint32_t svm1 = sp[-1]; ++ uint8_t sv = *sp++; ++ *dp++ = (uint8_t)(((3u * (uint32_t)sv) + svm1 + 1u) >> 2u); ++ *dp++ = sv; ++ } ++ ++ return dst_ptr; ++} ++ ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h2v2_triangle( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor, ++ size_t src_len, ++ uint32_t h1v2_bias_ignored, ++ bool first_column, ++ bool last_column) { ++ uint8_t* dp = dst_ptr; ++ const uint8_t* sp_major = src_ptr_major; ++ const uint8_t* sp_minor = src_ptr_minor; ++ ++ if (first_column) { ++ src_len--; ++ if ((src_len <= 0u) && last_column) { ++ uint32_t sv = (12u * ((uint32_t)(*sp_major++))) + // ++ (4u * ((uint32_t)(*sp_minor++))); ++ *dp++ = (uint8_t)((sv + 8u) >> 4u); ++ *dp++ = (uint8_t)((sv + 7u) >> 4u); ++ return dst_ptr; + } +- self->private_impl.f_padding -= 14u; +- self->private_impl.f_io_redirect_pos = wuffs_base__u64__sat_add(((uint64_t)(self->private_impl.f_padding)), wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- uint32_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; +- if (num_bits_2 == 24) { +- t_2 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)) << 56; +- } +- } +- self->private_impl.f_bitmap_info_len = t_2; ++ ++ uint32_t sv_major_m1 = sp_major[-0]; // Clamp offset to zero. ++ uint32_t sv_minor_m1 = sp_minor[-0]; // Clamp offset to zero. ++ uint32_t sv_major_p1 = sp_major[+1]; ++ uint32_t sv_minor_p1 = sp_minor[+1]; ++ ++ uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // ++ (3u * ((uint32_t)(*sp_minor++))); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); ++ if (src_len <= 0u) { ++ return dst_ptr; + } +- if (self->private_impl.f_padding < self->private_impl.f_bitmap_info_len) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; ++ } ++ ++ if (last_column) { ++ src_len--; ++ } ++ ++ for (; src_len > 0u; src_len--) { ++ uint32_t sv_major_m1 = sp_major[-1]; ++ uint32_t sv_minor_m1 = sp_minor[-1]; ++ uint32_t sv_major_p1 = sp_major[+1]; ++ uint32_t sv_minor_p1 = sp_minor[+1]; ++ ++ uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // ++ (3u * ((uint32_t)(*sp_minor++))); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); ++ } ++ ++ if (last_column) { ++ uint32_t sv_major_m1 = sp_major[-1]; ++ uint32_t sv_minor_m1 = sp_minor[-1]; ++ uint32_t sv_major_p1 = sp_major[+0]; // Clamp offset to zero. ++ uint32_t sv_minor_p1 = sp_minor[+0]; // Clamp offset to zero. ++ ++ uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // ++ (3u * ((uint32_t)(*sp_minor++))); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); ++ } ++ ++ return dst_ptr; ++} ++ ++// wuffs_private_impl__swizzle_ycc__upsample_funcs is indexed by inv_h and then ++// inv_v. ++static const wuffs_private_impl__swizzle_ycc__upsample_func ++ wuffs_private_impl__swizzle_ycc__upsample_funcs[4][4] = { ++ { ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h1vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h1vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h1vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h1vn_box, ++ }, ++ { ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h2vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h2vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h2vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h2vn_box, ++ }, ++ { ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h3vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h3vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h3vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h3vn_box, ++ }, ++ { ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h4vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h4vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h4vn_box, ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h4vn_box, ++ }, ++}; ++ ++static inline uint32_t // ++wuffs_private_impl__swizzle_has_triangle_upsampler(uint32_t inv_h, ++ uint32_t inv_v) { ++ if (inv_h == 1u) { ++ return inv_v == 2u; ++ } else if (inv_h == 2u) { ++ return (inv_v == 1u) || (inv_v == 2u); ++ } ++ return false; ++} ++ ++// -------- ++ ++// All of the wuffs_private_impl__swizzle_ycc__etc functions have ++// preconditions. See all of the checks made in ++// wuffs_base__pixel_swizzler__swizzle_ycck before calling these functions. For ++// example, (width > 0) is a precondition, but there are many more. ++ ++static void // ++wuffs_private_impl__swizzle_ycck__general__triangle_filter_edge_row( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t width, ++ uint32_t y, ++ const uint8_t* src_ptr0, ++ const uint8_t* src_ptr1, ++ const uint8_t* src_ptr2, ++ const uint8_t* src_ptr3, ++ uint32_t stride0, ++ uint32_t stride1, ++ uint32_t stride2, ++ uint32_t stride3, ++ uint32_t inv_h0, ++ uint32_t inv_h1, ++ uint32_t inv_h2, ++ uint32_t inv_h3, ++ uint32_t inv_v0, ++ uint32_t inv_v1, ++ uint32_t inv_v2, ++ uint32_t inv_v3, ++ uint32_t half_width_for_2to1, ++ uint32_t h1v2_bias, ++ uint8_t* scratch_buffer_2k_ptr, ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc0, ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc1, ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc2, ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc3, ++ wuffs_private_impl__swizzle_ycc__convert_4_func conv4func) { ++ const uint8_t* src0 = src_ptr0 + ((y / inv_v0) * (size_t)stride0); ++ const uint8_t* src1 = src_ptr1 + ((y / inv_v1) * (size_t)stride1); ++ const uint8_t* src2 = src_ptr2 + ((y / inv_v2) * (size_t)stride2); ++ const uint8_t* src3 = src_ptr3 + ((y / inv_v3) * (size_t)stride3); ++ uint32_t total_src_len0 = 0u; ++ uint32_t total_src_len1 = 0u; ++ uint32_t total_src_len2 = 0u; ++ uint32_t total_src_len3 = 0u; ++ ++ uint32_t x = 0u; ++ while (x < width) { ++ bool first_column = x == 0u; ++ uint32_t end = x + 480u; ++ if (end > width) { ++ end = width; + } +- self->private_impl.f_padding -= self->private_impl.f_bitmap_info_len; +- if (self->private_impl.f_bitmap_info_len == 12u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- uint32_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_3 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; +- if (num_bits_3 == 8) { +- t_3 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)) << 56; +- } +- } +- self->private_impl.f_width = t_3; ++ ++ uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; ++ uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; ++ uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; ++ uint32_t src_len3 = ((end - x) + inv_h3 - 1u) / inv_h3; ++ total_src_len0 += src_len0; ++ total_src_len1 += src_len1; ++ total_src_len2 += src_len2; ++ total_src_len3 += src_len3; ++ ++ const uint8_t* src_ptr_x0 = src0 + (x / inv_h0); ++ const uint8_t* up0 = (*upfunc0)( // ++ scratch_buffer_2k_ptr + (0u * 480u), // ++ src_ptr_x0, // ++ src_ptr_x0, // ++ src_len0, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len0 >= half_width_for_2to1)); ++ ++ const uint8_t* src_ptr_x1 = src1 + (x / inv_h1); ++ const uint8_t* up1 = (*upfunc1)( // ++ scratch_buffer_2k_ptr + (1u * 480u), // ++ src_ptr_x1, // ++ src_ptr_x1, // ++ src_len1, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len1 >= half_width_for_2to1)); ++ ++ const uint8_t* src_ptr_x2 = src2 + (x / inv_h2); ++ const uint8_t* up2 = (*upfunc2)( // ++ scratch_buffer_2k_ptr + (2u * 480u), // ++ src_ptr_x2, // ++ src_ptr_x2, // ++ src_len2, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len2 >= half_width_for_2to1)); ++ ++ const uint8_t* src_ptr_x3 = src3 + (x / inv_h3); ++ const uint8_t* up3 = (*upfunc3)( // ++ scratch_buffer_2k_ptr + (3u * 480u), // ++ src_ptr_x3, // ++ src_ptr_x3, // ++ src_len3, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len3 >= half_width_for_2to1)); ++ ++ (*conv4func)(dst, x, end, y, up0, up1, up2, up3); ++ x = end; ++ } ++} ++ ++static void // ++wuffs_private_impl__swizzle_ycck__general__triangle_filter( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x_min_incl, ++ uint32_t x_max_excl, ++ uint32_t y_min_incl, ++ uint32_t y_max_excl, ++ const uint8_t* src_ptr0, ++ const uint8_t* src_ptr1, ++ const uint8_t* src_ptr2, ++ const uint8_t* src_ptr3, ++ uint32_t stride0, ++ uint32_t stride1, ++ uint32_t stride2, ++ uint32_t stride3, ++ uint32_t inv_h0, ++ uint32_t inv_h1, ++ uint32_t inv_h2, ++ uint32_t inv_h3, ++ uint32_t inv_v0, ++ uint32_t inv_v1, ++ uint32_t inv_v2, ++ uint32_t inv_v3, ++ uint32_t half_width_for_2to1, ++ uint32_t half_height_for_2to1, ++ uint8_t* scratch_buffer_2k_ptr, ++ wuffs_private_impl__swizzle_ycc__upsample_func (*upfuncs)[4][4], ++ wuffs_private_impl__swizzle_ycc__convert_4_func conv4func) { ++ if ((x_min_incl != 0) || (y_min_incl != 0)) { ++ return; ++ } ++ ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc0 = ++ (*upfuncs)[(inv_h0 - 1u) & 3u][(inv_v0 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc1 = ++ (*upfuncs)[(inv_h1 - 1u) & 3u][(inv_v1 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc2 = ++ (*upfuncs)[(inv_h2 - 1u) & 3u][(inv_v2 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc3 = ++ (*upfuncs)[(inv_h3 - 1u) & 3u][(inv_v3 - 1u) & 3u]; ++ ++ // First row. ++ uint32_t h1v2_bias = 1u; ++ wuffs_private_impl__swizzle_ycck__general__triangle_filter_edge_row( ++ dst, x_max_excl, 0u, // ++ src_ptr0, src_ptr1, src_ptr2, src_ptr3, // ++ stride0, stride1, stride2, stride3, // ++ inv_h0, inv_h1, inv_h2, inv_h3, // ++ inv_v0, inv_v1, inv_v2, inv_v3, // ++ half_width_for_2to1, // ++ h1v2_bias, // ++ scratch_buffer_2k_ptr, // ++ upfunc0, upfunc1, upfunc2, upfunc3, conv4func); ++ h1v2_bias = 2u; ++ ++ // Middle rows. ++ bool last_row = y_max_excl == 2u * half_height_for_2to1; ++ uint32_t middle_y_max_excl = last_row ? (y_max_excl - 1u) : y_max_excl; ++ uint32_t y; ++ for (y = 1u; y < middle_y_max_excl; y++) { ++ const uint8_t* src0_major = src_ptr0 + ((y / inv_v0) * (size_t)stride0); ++ const uint8_t* src0_minor = ++ (inv_v0 != 2u) ++ ? src0_major ++ : ((y & 1u) ? (src0_major + stride0) : (src0_major - stride0)); ++ const uint8_t* src1_major = src_ptr1 + ((y / inv_v1) * (size_t)stride1); ++ const uint8_t* src1_minor = ++ (inv_v1 != 2u) ++ ? src1_major ++ : ((y & 1u) ? (src1_major + stride1) : (src1_major - stride1)); ++ const uint8_t* src2_major = src_ptr2 + ((y / inv_v2) * (size_t)stride2); ++ const uint8_t* src2_minor = ++ (inv_v2 != 2u) ++ ? src2_major ++ : ((y & 1u) ? (src2_major + stride2) : (src2_major - stride2)); ++ const uint8_t* src3_major = src_ptr3 + ((y / inv_v3) * (size_t)stride3); ++ const uint8_t* src3_minor = ++ (inv_v3 != 2u) ++ ? src3_major ++ : ((y & 1u) ? (src3_major + stride3) : (src3_major - stride3)); ++ uint32_t total_src_len0 = 0u; ++ uint32_t total_src_len1 = 0u; ++ uint32_t total_src_len2 = 0u; ++ uint32_t total_src_len3 = 0u; ++ ++ uint32_t x = 0u; ++ while (x < x_max_excl) { ++ bool first_column = x == 0u; ++ uint32_t end = x + 480u; ++ if (end > x_max_excl) { ++ end = x_max_excl; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- uint32_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_4 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; +- if (num_bits_4 == 8) { +- t_4 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)) << 56; +- } +- } +- self->private_impl.f_height = t_4; ++ ++ uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; ++ uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; ++ uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; ++ uint32_t src_len3 = ((end - x) + inv_h3 - 1u) / inv_h3; ++ total_src_len0 += src_len0; ++ total_src_len1 += src_len1; ++ total_src_len2 += src_len2; ++ total_src_len3 += src_len3; ++ ++ const uint8_t* up0 = (*upfunc0)( // ++ scratch_buffer_2k_ptr + (0u * 480u), // ++ src0_major + (x / inv_h0), // ++ src0_minor + (x / inv_h0), // ++ src_len0, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len0 >= half_width_for_2to1)); ++ ++ const uint8_t* up1 = (*upfunc1)( // ++ scratch_buffer_2k_ptr + (1u * 480u), // ++ src1_major + (x / inv_h1), // ++ src1_minor + (x / inv_h1), // ++ src_len1, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len1 >= half_width_for_2to1)); ++ ++ const uint8_t* up2 = (*upfunc2)( // ++ scratch_buffer_2k_ptr + (2u * 480u), // ++ src2_major + (x / inv_h2), // ++ src2_minor + (x / inv_h2), // ++ src_len2, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len2 >= half_width_for_2to1)); ++ ++ const uint8_t* up3 = (*upfunc3)( // ++ scratch_buffer_2k_ptr + (3u * 480u), // ++ src3_major + (x / inv_h3), // ++ src3_minor + (x / inv_h3), // ++ src_len3, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len3 >= half_width_for_2to1)); ++ ++ (*conv4func)(dst, x, end, y, up0, up1, up2, up3); ++ x = end; ++ } ++ ++ h1v2_bias ^= 3u; ++ } ++ ++ // Last row. ++ if (middle_y_max_excl != y_max_excl) { ++ wuffs_private_impl__swizzle_ycck__general__triangle_filter_edge_row( ++ dst, x_max_excl, middle_y_max_excl, // ++ src_ptr0, src_ptr1, src_ptr2, src_ptr3, // ++ stride0, stride1, stride2, stride3, // ++ inv_h0, inv_h1, inv_h2, inv_h3, // ++ inv_v0, inv_v1, inv_v2, inv_v3, // ++ half_width_for_2to1, // ++ h1v2_bias, // ++ scratch_buffer_2k_ptr, // ++ upfunc0, upfunc1, upfunc2, upfunc3, conv4func); ++ } ++} ++ ++static void // ++wuffs_private_impl__swizzle_ycc__general__triangle_filter_edge_row( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t width, ++ uint32_t y, ++ const uint8_t* src_ptr0, ++ const uint8_t* src_ptr1, ++ const uint8_t* src_ptr2, ++ uint32_t stride0, ++ uint32_t stride1, ++ uint32_t stride2, ++ uint32_t inv_h0, ++ uint32_t inv_h1, ++ uint32_t inv_h2, ++ uint32_t inv_v0, ++ uint32_t inv_v1, ++ uint32_t inv_v2, ++ uint32_t half_width_for_2to1, ++ uint32_t h1v2_bias, ++ uint8_t* scratch_buffer_2k_ptr, ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc0, ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc1, ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc2, ++ wuffs_private_impl__swizzle_ycc__convert_3_func conv3func) { ++ const uint8_t* src0 = src_ptr0 + ((y / inv_v0) * (size_t)stride0); ++ const uint8_t* src1 = src_ptr1 + ((y / inv_v1) * (size_t)stride1); ++ const uint8_t* src2 = src_ptr2 + ((y / inv_v2) * (size_t)stride2); ++ uint32_t total_src_len0 = 0u; ++ uint32_t total_src_len1 = 0u; ++ uint32_t total_src_len2 = 0u; ++ ++ uint32_t x = 0u; ++ while (x < width) { ++ bool first_column = x == 0u; ++ uint32_t end = x + 672u; ++ if (end > width) { ++ end = width; ++ } ++ ++ uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; ++ uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; ++ uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; ++ total_src_len0 += src_len0; ++ total_src_len1 += src_len1; ++ total_src_len2 += src_len2; ++ ++ const uint8_t* src_ptr_x0 = src0 + (x / inv_h0); ++ const uint8_t* up0 = (*upfunc0)( // ++ scratch_buffer_2k_ptr + (0u * 672u), // ++ src_ptr_x0, // ++ src_ptr_x0, // ++ src_len0, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len0 >= half_width_for_2to1)); ++ ++ const uint8_t* src_ptr_x1 = src1 + (x / inv_h1); ++ const uint8_t* up1 = (*upfunc1)( // ++ scratch_buffer_2k_ptr + (1u * 672u), // ++ src_ptr_x1, // ++ src_ptr_x1, // ++ src_len1, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len1 >= half_width_for_2to1)); ++ ++ const uint8_t* src_ptr_x2 = src2 + (x / inv_h2); ++ const uint8_t* up2 = (*upfunc2)( // ++ scratch_buffer_2k_ptr + (2u * 672u), // ++ src_ptr_x2, // ++ src_ptr_x2, // ++ src_len2, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len2 >= half_width_for_2to1)); ++ ++ (*conv3func)(dst, x, end, y, up0, up1, up2); ++ x = end; ++ } ++} ++ ++static void // ++wuffs_private_impl__swizzle_ycc__general__triangle_filter( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x_min_incl, ++ uint32_t x_max_excl, ++ uint32_t y_min_incl, ++ uint32_t y_max_excl, ++ const uint8_t* src_ptr0, ++ const uint8_t* src_ptr1, ++ const uint8_t* src_ptr2, ++ uint32_t stride0, ++ uint32_t stride1, ++ uint32_t stride2, ++ uint32_t inv_h0, ++ uint32_t inv_h1, ++ uint32_t inv_h2, ++ uint32_t inv_v0, ++ uint32_t inv_v1, ++ uint32_t inv_v2, ++ uint32_t half_width_for_2to1, ++ uint32_t half_height_for_2to1, ++ uint8_t* scratch_buffer_2k_ptr, ++ wuffs_private_impl__swizzle_ycc__upsample_func (*upfuncs)[4][4], ++ wuffs_private_impl__swizzle_ycc__convert_3_func conv3func) { ++ if ((x_min_incl != 0) || (y_min_incl != 0)) { ++ return; ++ } ++ ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc0 = ++ (*upfuncs)[(inv_h0 - 1u) & 3u][(inv_v0 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc1 = ++ (*upfuncs)[(inv_h1 - 1u) & 3u][(inv_v1 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc2 = ++ (*upfuncs)[(inv_h2 - 1u) & 3u][(inv_v2 - 1u) & 3u]; ++ ++ // First row. ++ uint32_t h1v2_bias = 1u; ++ wuffs_private_impl__swizzle_ycc__general__triangle_filter_edge_row( ++ dst, x_max_excl, 0u, // ++ src_ptr0, src_ptr1, src_ptr2, // ++ stride0, stride1, stride2, // ++ inv_h0, inv_h1, inv_h2, // ++ inv_v0, inv_v1, inv_v2, // ++ half_width_for_2to1, // ++ h1v2_bias, // ++ scratch_buffer_2k_ptr, // ++ upfunc0, upfunc1, upfunc2, conv3func); ++ h1v2_bias = 2u; ++ ++ // Middle rows. ++ bool last_row = y_max_excl == 2u * half_height_for_2to1; ++ uint32_t middle_y_max_excl = last_row ? (y_max_excl - 1u) : y_max_excl; ++ uint32_t y; ++ for (y = 1u; y < middle_y_max_excl; y++) { ++ const uint8_t* src0_major = src_ptr0 + ((y / inv_v0) * (size_t)stride0); ++ const uint8_t* src0_minor = ++ (inv_v0 != 2u) ++ ? src0_major ++ : ((y & 1u) ? (src0_major + stride0) : (src0_major - stride0)); ++ const uint8_t* src1_major = src_ptr1 + ((y / inv_v1) * (size_t)stride1); ++ const uint8_t* src1_minor = ++ (inv_v1 != 2u) ++ ? src1_major ++ : ((y & 1u) ? (src1_major + stride1) : (src1_major - stride1)); ++ const uint8_t* src2_major = src_ptr2 + ((y / inv_v2) * (size_t)stride2); ++ const uint8_t* src2_minor = ++ (inv_v2 != 2u) ++ ? src2_major ++ : ((y & 1u) ? (src2_major + stride2) : (src2_major - stride2)); ++ uint32_t total_src_len0 = 0u; ++ uint32_t total_src_len1 = 0u; ++ uint32_t total_src_len2 = 0u; ++ ++ uint32_t x = 0u; ++ while (x < x_max_excl) { ++ bool first_column = x == 0u; ++ uint32_t end = x + 672u; ++ if (end > x_max_excl) { ++ end = x_max_excl; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); +- uint32_t t_5; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_5 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_5 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_5; +- if (num_bits_5 == 8) { +- t_5 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_5 += 8u; +- *scratch |= ((uint64_t)(num_bits_5)) << 56; +- } +- } +- v_planes = t_5; ++ ++ uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; ++ uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; ++ uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; ++ total_src_len0 += src_len0; ++ total_src_len1 += src_len1; ++ total_src_len2 += src_len2; ++ ++ const uint8_t* up0 = (*upfunc0)( // ++ scratch_buffer_2k_ptr + (0u * 672u), // ++ src0_major + (x / inv_h0), // ++ src0_minor + (x / inv_h0), // ++ src_len0, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len0 >= half_width_for_2to1)); ++ ++ const uint8_t* up1 = (*upfunc1)( // ++ scratch_buffer_2k_ptr + (1u * 672u), // ++ src1_major + (x / inv_h1), // ++ src1_minor + (x / inv_h1), // ++ src_len1, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len1 >= half_width_for_2to1)); ++ ++ const uint8_t* up2 = (*upfunc2)( // ++ scratch_buffer_2k_ptr + (2u * 672u), // ++ src2_major + (x / inv_h2), // ++ src2_minor + (x / inv_h2), // ++ src_len2, // ++ h1v2_bias, // ++ first_column, // ++ (total_src_len2 >= half_width_for_2to1)); ++ ++ (*conv3func)(dst, x, end, y, up0, up1, up2); ++ x = end; ++ } ++ ++ h1v2_bias ^= 3u; ++ } ++ ++ // Last row. ++ if (middle_y_max_excl != y_max_excl) { ++ wuffs_private_impl__swizzle_ycc__general__triangle_filter_edge_row( ++ dst, x_max_excl, middle_y_max_excl, // ++ src_ptr0, src_ptr1, src_ptr2, // ++ stride0, stride1, stride2, // ++ inv_h0, inv_h1, inv_h2, // ++ inv_v0, inv_v1, inv_v2, // ++ half_width_for_2to1, // ++ h1v2_bias, // ++ scratch_buffer_2k_ptr, // ++ upfunc0, upfunc1, upfunc2, conv3func); ++ } ++} ++ ++static void // ++wuffs_private_impl__swizzle_ycc__general__box_filter( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x_min_incl, ++ uint32_t x_max_excl, ++ uint32_t y_min_incl, ++ uint32_t y_max_excl, ++ const uint8_t* src_ptr0, ++ const uint8_t* src_ptr1, ++ const uint8_t* src_ptr2, ++ uint32_t stride0, ++ uint32_t stride1, ++ uint32_t stride2, ++ uint32_t inv_h0, ++ uint32_t inv_h1, ++ uint32_t inv_h2, ++ uint32_t inv_v0, ++ uint32_t inv_v1, ++ uint32_t inv_v2, ++ uint32_t half_width_for_2to1, ++ uint32_t half_height_for_2to1, ++ uint8_t* scratch_buffer_2k_ptr, ++ wuffs_private_impl__swizzle_ycc__upsample_func (*upfuncs)[4][4], ++ wuffs_private_impl__swizzle_ycc__convert_3_func conv3func) { ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc0 = ++ (*upfuncs)[(inv_h0 - 1u) & 3u][(inv_v0 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc1 = ++ (*upfuncs)[(inv_h1 - 1u) & 3u][(inv_v1 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc2 = ++ (*upfuncs)[(inv_h2 - 1u) & 3u][(inv_v2 - 1u) & 3u]; ++ ++ uint32_t y; ++ for (y = y_min_incl; y < y_max_excl; y++) { ++ const uint8_t* src0_major = ++ src_ptr0 + (((y - y_min_incl) / inv_v0) * (size_t)stride0); ++ const uint8_t* src1_major = ++ src_ptr1 + (((y - y_min_incl) / inv_v1) * (size_t)stride1); ++ const uint8_t* src2_major = ++ src_ptr2 + (((y - y_min_incl) / inv_v2) * (size_t)stride2); ++ ++ uint32_t x = x_min_incl; ++ while (x < x_max_excl) { ++ uint32_t end = x + 672u; ++ if (end > x_max_excl) { ++ end = x_max_excl; + } +- if (v_planes != 1u) { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; ++ ++ uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; ++ uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; ++ uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; ++ ++ const uint8_t* up0 = (*upfunc0)( // ++ scratch_buffer_2k_ptr + (0u * 672u), // ++ src0_major + ((x - x_min_incl) / inv_h0), // ++ src0_major + ((x - x_min_incl) / inv_h0), // ++ src_len0, // ++ 0u, false, false); ++ ++ const uint8_t* up1 = (*upfunc1)( // ++ scratch_buffer_2k_ptr + (1u * 672u), // ++ src1_major + ((x - x_min_incl) / inv_h1), // ++ src1_major + ((x - x_min_incl) / inv_h1), // ++ src_len1, // ++ 0u, false, false); ++ ++ const uint8_t* up2 = (*upfunc2)( // ++ scratch_buffer_2k_ptr + (2u * 672u), // ++ src2_major + ((x - x_min_incl) / inv_h2), // ++ src2_major + ((x - x_min_incl) / inv_h2), // ++ src_len2, // ++ 0u, false, false); ++ ++ (*conv3func)(dst, x, end, y, up0, up1, up2); ++ x = end; ++ } ++ } ++} ++ ++static void // ++wuffs_private_impl__swizzle_ycck__general__box_filter( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x_min_incl, ++ uint32_t x_max_excl, ++ uint32_t y_min_incl, ++ uint32_t y_max_excl, ++ const uint8_t* src_ptr0, ++ const uint8_t* src_ptr1, ++ const uint8_t* src_ptr2, ++ const uint8_t* src_ptr3, ++ uint32_t stride0, ++ uint32_t stride1, ++ uint32_t stride2, ++ uint32_t stride3, ++ uint32_t inv_h0, ++ uint32_t inv_h1, ++ uint32_t inv_h2, ++ uint32_t inv_h3, ++ uint32_t inv_v0, ++ uint32_t inv_v1, ++ uint32_t inv_v2, ++ uint32_t inv_v3, ++ uint32_t half_width_for_2to1, ++ uint32_t half_height_for_2to1, ++ uint8_t* scratch_buffer_2k_ptr, ++ wuffs_private_impl__swizzle_ycc__upsample_func (*upfuncs)[4][4], ++ wuffs_private_impl__swizzle_ycc__convert_4_func conv4func) { ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc0 = ++ (*upfuncs)[(inv_h0 - 1u) & 3u][(inv_v0 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc1 = ++ (*upfuncs)[(inv_h1 - 1u) & 3u][(inv_v1 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc2 = ++ (*upfuncs)[(inv_h2 - 1u) & 3u][(inv_v2 - 1u) & 3u]; ++ wuffs_private_impl__swizzle_ycc__upsample_func upfunc3 = ++ (*upfuncs)[(inv_h3 - 1u) & 3u][(inv_v3 - 1u) & 3u]; ++ ++ uint32_t y; ++ for (y = y_min_incl; y < y_max_excl; y++) { ++ const uint8_t* src0_major = ++ src_ptr0 + (((y - y_min_incl) / inv_v0) * (size_t)stride0); ++ const uint8_t* src1_major = ++ src_ptr1 + (((y - y_min_incl) / inv_v1) * (size_t)stride1); ++ const uint8_t* src2_major = ++ src_ptr2 + (((y - y_min_incl) / inv_v2) * (size_t)stride2); ++ const uint8_t* src3_major = ++ src_ptr3 + (((y - y_min_incl) / inv_v3) * (size_t)stride3); ++ ++ uint32_t x = x_min_incl; ++ while (x < x_max_excl) { ++ uint32_t end = x + 480u; ++ if (end > x_max_excl) { ++ end = x_max_excl; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); +- uint32_t t_6; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_6 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6; +- if (num_bits_6 == 8) { +- t_6 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_6 += 8u; +- *scratch |= ((uint64_t)(num_bits_6)) << 56; +- } +- } +- self->private_impl.f_bits_per_pixel = t_6; +- } +- } else if (self->private_impl.f_bitmap_info_len == 16u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); +- uint32_t t_7; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_7 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7; +- if (num_bits_7 == 24) { +- t_7 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_7 += 8u; +- *scratch |= ((uint64_t)(num_bits_7)) << 56; +- } +- } +- v_width = t_7; +- } +- if (v_width > 2147483647u) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; +- } else if (v_width > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } +- self->private_impl.f_width = v_width; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18); +- uint32_t t_8; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8; +- if (num_bits_8 == 24) { +- t_8 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_8 += 8u; +- *scratch |= ((uint64_t)(num_bits_8)) << 56; +- } +- } +- v_height = t_8; +- } +- if (v_height > 2147483647u) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; +- } else if (v_height > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } +- self->private_impl.f_height = v_height; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20); +- uint32_t t_9; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_9 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9; +- if (num_bits_9 == 8) { +- t_9 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_9 += 8u; +- *scratch |= ((uint64_t)(num_bits_9)) << 56; +- } +- } +- v_planes = t_9; +- } +- if (v_planes != 1u) { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22); +- uint32_t t_10; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_10 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10; +- if (num_bits_10 == 8) { +- t_10 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_10 += 8u; +- *scratch |= ((uint64_t)(num_bits_10)) << 56; +- } +- } +- self->private_impl.f_bits_per_pixel = t_10; +- } +- } else { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24); +- uint32_t t_11; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_11 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(25); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11; +- if (num_bits_11 == 24) { +- t_11 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_11 += 8u; +- *scratch |= ((uint64_t)(num_bits_11)) << 56; +- } +- } +- v_width = t_11; +- } +- if (v_width > 2147483647u) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; +- } else if (v_width > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } +- self->private_impl.f_width = v_width; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(26); +- uint32_t t_12; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_12 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(27); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_12 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_12; +- if (num_bits_12 == 24) { +- t_12 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_12 += 8u; +- *scratch |= ((uint64_t)(num_bits_12)) << 56; +- } +- } +- v_height = t_12; +- } +- if (v_height == 2147483648u) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; +- } else if (v_height > 2147483648u) { +- v_height = ((uint32_t)(0u - v_height)); +- if (v_height > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } +- self->private_impl.f_height = v_height; +- self->private_impl.f_top_down = true; +- } else if (v_height > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } else { +- self->private_impl.f_height = v_height; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(28); +- uint32_t t_13; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_13 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(29); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_13 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_13; +- if (num_bits_13 == 8) { +- t_13 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_13 += 8u; +- *scratch |= ((uint64_t)(num_bits_13)) << 56; +- } ++ ++ uint32_t src_len0 = ((end - x) + inv_h0 - 1u) / inv_h0; ++ uint32_t src_len1 = ((end - x) + inv_h1 - 1u) / inv_h1; ++ uint32_t src_len2 = ((end - x) + inv_h2 - 1u) / inv_h2; ++ uint32_t src_len3 = ((end - x) + inv_h3 - 1u) / inv_h3; ++ ++ const uint8_t* up0 = (*upfunc0)( // ++ scratch_buffer_2k_ptr + (0u * 480u), // ++ src0_major + ((x - x_min_incl) / inv_h0), // ++ src0_major + ((x - x_min_incl) / inv_h0), // ++ src_len0, // ++ 0u, false, false); ++ ++ const uint8_t* up1 = (*upfunc1)( // ++ scratch_buffer_2k_ptr + (1u * 480u), // ++ src1_major + ((x - x_min_incl) / inv_h1), // ++ src1_major + ((x - x_min_incl) / inv_h1), // ++ src_len1, // ++ 0u, false, false); ++ ++ const uint8_t* up2 = (*upfunc2)( // ++ scratch_buffer_2k_ptr + (2u * 480u), // ++ src2_major + ((x - x_min_incl) / inv_h2), // ++ src2_major + ((x - x_min_incl) / inv_h2), // ++ src_len2, // ++ 0u, false, false); ++ ++ const uint8_t* up3 = (*upfunc3)( // ++ scratch_buffer_2k_ptr + (3u * 480u), // ++ src3_major + ((x - x_min_incl) / inv_h3), // ++ src3_major + ((x - x_min_incl) / inv_h3), // ++ src_len3, // ++ 0u, false, false); ++ ++ (*conv4func)(dst, x, end, y, up0, up1, up2, up3); ++ x = end; ++ } ++ } ++} ++ ++// -------- ++ ++// wuffs_private_impl__swizzle_flattened_length is like ++// wuffs_base__table__flattened_length but returns uint64_t (not size_t) and ++// also accounts for subsampling. ++static uint64_t // ++wuffs_private_impl__swizzle_flattened_length(uint32_t width, ++ uint32_t height, ++ uint32_t stride, ++ uint32_t inv_h, ++ uint32_t inv_v) { ++ uint64_t scaled_width = (((uint64_t)width) + (inv_h - 1u)) / inv_h; ++ uint64_t scaled_height = (((uint64_t)height) + (inv_v - 1u)) / inv_v; ++ if (scaled_height <= 0u) { ++ return 0u; ++ } ++ return ((scaled_height - 1u) * stride) + scaled_width; ++} ++ ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status // ++wuffs_base__pixel_swizzler__swizzle_ycck( ++ const wuffs_base__pixel_swizzler* p, ++ wuffs_base__pixel_buffer* dst, ++ wuffs_base__slice_u8 dst_palette, ++ uint32_t x_min_incl, ++ uint32_t x_max_excl, ++ uint32_t y_min_incl, ++ uint32_t y_max_excl, ++ wuffs_base__slice_u8 src0, ++ wuffs_base__slice_u8 src1, ++ wuffs_base__slice_u8 src2, ++ wuffs_base__slice_u8 src3, ++ uint32_t width0, ++ uint32_t width1, ++ uint32_t width2, ++ uint32_t width3, ++ uint32_t height0, ++ uint32_t height1, ++ uint32_t height2, ++ uint32_t height3, ++ uint32_t stride0, ++ uint32_t stride1, ++ uint32_t stride2, ++ uint32_t stride3, ++ uint8_t h0, ++ uint8_t h1, ++ uint8_t h2, ++ uint8_t h3, ++ uint8_t v0, ++ uint8_t v1, ++ uint8_t v2, ++ uint8_t v3, ++ bool is_rgb_or_cmyk, ++ bool triangle_filter_for_2to1, ++ wuffs_base__slice_u8 scratch_buffer_2k) { ++ if (!p) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } else if (!dst || // ++ (x_min_incl > x_max_excl) || // ++ (x_max_excl > 0xFFFFu) || // ++ (y_min_incl > y_max_excl) || // ++ (y_max_excl > 0xFFFFu) || // ++ (4u <= ((unsigned int)h0 - 1u)) || // ++ (4u <= ((unsigned int)h1 - 1u)) || // ++ (4u <= ((unsigned int)h2 - 1u)) || // ++ (4u <= ((unsigned int)v0 - 1u)) || // ++ (4u <= ((unsigned int)v1 - 1u)) || // ++ (4u <= ((unsigned int)v2 - 1u)) || // ++ (triangle_filter_for_2to1 && ((x_min_incl | y_min_incl) > 0u)) || ++ (scratch_buffer_2k.len < 2048u)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((h3 != 0u) || (v3 != 0u)) { ++ if ((4u <= ((unsigned int)h3 - 1u)) || // ++ (4u <= ((unsigned int)v3 - 1u))) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ } ++ ++ uint32_t max_incl_h = wuffs_private_impl__u32__max_of_4(h0, h1, h2, h3); ++ uint32_t max_incl_v = wuffs_private_impl__u32__max_of_4(v0, v1, v2, v3); ++ ++ // Calculate the inverse h and v ratios. ++ // ++ // It also canonicalizes (h=2 and max_incl_h=4) as equivalent to (h=1 and ++ // max_incl_h=2). In both cases, the inv_h value is 2. ++ uint32_t inv_h0 = max_incl_h / h0; ++ uint32_t inv_h1 = max_incl_h / h1; ++ uint32_t inv_h2 = max_incl_h / h2; ++ uint32_t inv_h3 = h3 ? (max_incl_h / h3) : 0u; ++ uint32_t inv_v0 = max_incl_v / v0; ++ uint32_t inv_v1 = max_incl_v / v1; ++ uint32_t inv_v2 = max_incl_v / v2; ++ uint32_t inv_v3 = v3 ? (max_incl_v / v3) : 0u; ++ ++ if (x_min_incl != 0) { ++ if ((x_min_incl % inv_h0) || (x_min_incl % inv_h1) || ++ (x_min_incl % inv_h2) || (inv_h3 && (x_min_incl % inv_h3))) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ } ++ if (y_min_incl != 0) { ++ if ((y_min_incl % inv_v0) || (y_min_incl % inv_v1) || ++ (y_min_incl % inv_v2) || (inv_v3 && (y_min_incl % inv_v3))) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ } ++ ++ uint32_t half_width_for_2to1 = ((x_max_excl - x_min_incl) + 1u) / 2u; ++ if (inv_h0 == 2) { ++ half_width_for_2to1 = wuffs_base__u32__min(half_width_for_2to1, width0); ++ } ++ if (inv_h1 == 2) { ++ half_width_for_2to1 = wuffs_base__u32__min(half_width_for_2to1, width1); ++ } ++ if (inv_h2 == 2) { ++ half_width_for_2to1 = wuffs_base__u32__min(half_width_for_2to1, width2); ++ } ++ if (inv_h3 == 2) { ++ half_width_for_2to1 = wuffs_base__u32__min(half_width_for_2to1, width3); ++ } ++ ++ uint32_t half_height_for_2to1 = ((y_max_excl - y_min_incl) + 1u) / 2u; ++ if (inv_v0 == 2) { ++ half_height_for_2to1 = wuffs_base__u32__min(half_height_for_2to1, height0); ++ } ++ if (inv_v1 == 2) { ++ half_height_for_2to1 = wuffs_base__u32__min(half_height_for_2to1, height1); ++ } ++ if (inv_v2 == 2) { ++ half_height_for_2to1 = wuffs_base__u32__min(half_height_for_2to1, height2); ++ } ++ if (inv_v3 == 2) { ++ half_height_for_2to1 = wuffs_base__u32__min(half_height_for_2to1, height3); ++ } ++ ++ x_max_excl = wuffs_base__u32__min( // ++ wuffs_base__pixel_config__width(&dst->pixcfg), // ++ x_min_incl + wuffs_private_impl__u32__min_of_5( // ++ x_max_excl - x_min_incl, // ++ width0 * inv_h0, // ++ width1 * inv_h1, // ++ width2 * inv_h2, // ++ inv_h3 ? (width3 * inv_h3) : 0xFFFFFFFF)); ++ y_max_excl = wuffs_base__u32__min( // ++ wuffs_base__pixel_config__height(&dst->pixcfg), // ++ y_min_incl + wuffs_private_impl__u32__min_of_5( // ++ y_max_excl - y_min_incl, // ++ height0 * inv_v0, // ++ height1 * inv_v1, // ++ height2 * inv_v2, // ++ inv_v3 ? (height3 * inv_v3) : 0xFFFFFFFF)); ++ ++ if ((x_min_incl >= x_max_excl) || (y_min_incl >= y_max_excl)) { ++ return wuffs_base__make_status(NULL); ++ } ++ uint32_t width = x_max_excl - x_min_incl; ++ uint32_t height = y_max_excl - y_min_incl; ++ ++ if (((h0 * inv_h0) != max_incl_h) || // ++ ((h1 * inv_h1) != max_incl_h) || // ++ ((h2 * inv_h2) != max_incl_h) || // ++ ((v0 * inv_v0) != max_incl_v) || // ++ ((v1 * inv_v1) != max_incl_v) || // ++ ((v2 * inv_v2) != max_incl_v) || // ++ (src0.len < wuffs_private_impl__swizzle_flattened_length( ++ width, height, stride0, inv_h0, inv_v0)) || ++ (src1.len < wuffs_private_impl__swizzle_flattened_length( ++ width, height, stride1, inv_h1, inv_v1)) || ++ (src2.len < wuffs_private_impl__swizzle_flattened_length( ++ width, height, stride2, inv_h2, inv_v2))) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((h3 != 0u) || (v3 != 0u)) { ++ if (((h3 * inv_h3) != max_incl_h) || // ++ ((v3 * inv_v3) != max_incl_v) || // ++ (src3.len < wuffs_private_impl__swizzle_flattened_length( ++ width, height, stride3, inv_h3, inv_v3))) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ } ++ ++ if (wuffs_base__pixel_format__is_planar(&dst->pixcfg.private_impl.pixfmt)) { ++ // TODO: see wuffs_base__pixel_buffer__set_color_u32_at's TODO. ++ return wuffs_base__make_status( ++ wuffs_base__error__unsupported_pixel_swizzler_option); ++ } ++ ++ // ---- ++ ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ENABLE_ALLOWLIST) ++ switch (dst->pixcfg.private_impl.pixfmt.repr) { ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGR_565) ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGR) ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGRA_NONPREMUL) ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGRA_NONPREMUL_4X16LE) ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_BGRA_PREMUL) ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_RGB) ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_RGBA_NONPREMUL) ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ break; ++#endif ++#if defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ALLOW_RGBA_PREMUL) ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ break; ++#endif ++ default: ++ return wuffs_base__make_status( ++ wuffs_base__error__disabled_by_wuffs_config_dst_pixel_format_enable_allowlist); ++ } ++#else // defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ENABLE_ALLOWLIST) ++ switch (dst->pixcfg.private_impl.pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__Y: ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__Y_16BE: ++ case WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: ++ case WUFFS_BASE__PIXEL_FORMAT__BGR_565: ++ case WUFFS_BASE__PIXEL_FORMAT__BGR: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++ case WUFFS_BASE__PIXEL_FORMAT__RGB: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++ break; ++ ++ default: ++ // TODO: see wuffs_base__pixel_buffer__set_color_u32_at's TODO. ++ return wuffs_base__make_status( ++ wuffs_base__error__unsupported_pixel_swizzler_option); ++ } ++#endif // defined(WUFFS_CONFIG__DST_PIXEL_FORMAT__ENABLE_ALLOWLIST) ++ ++ // ---- ++ ++ wuffs_private_impl__swizzle_ycc__convert_3_func conv3func = NULL; ++ ++ if (is_rgb_or_cmyk) { ++ conv3func = &wuffs_private_impl__swizzle_rgb__convert_3_general; ++ } else { ++ switch (dst->pixcfg.private_impl.pixfmt.repr) { ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__BGRX: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++ if (wuffs_base__cpu_arch__have_x86_avx2()) { ++ conv3func = &wuffs_private_impl__swizzle_ycc__convert_3_bgrx_x86_avx2; ++ break; + } +- v_planes = t_13; +- } +- if (v_planes != 1u) { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(30); +- uint32_t t_14; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_14 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(31); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_14 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_14; +- if (num_bits_14 == 8) { +- t_14 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_14 += 8u; +- *scratch |= ((uint64_t)(num_bits_14)) << 56; +- } ++#endif ++ conv3func = &wuffs_private_impl__swizzle_ycc__convert_3_bgrx; ++ break; ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL: ++ case WUFFS_BASE__PIXEL_FORMAT__RGBX: ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++ if (wuffs_base__cpu_arch__have_x86_avx2()) { ++ conv3func = &wuffs_private_impl__swizzle_ycc__convert_3_rgbx_x86_avx2; ++ break; + } +- self->private_impl.f_bits_per_pixel = t_14; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(32); +- uint32_t t_15; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_15 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(33); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_15 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_15; +- if (num_bits_15 == 24) { +- t_15 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_15 += 8u; +- *scratch |= ((uint64_t)(num_bits_15)) << 56; +- } +- } +- self->private_impl.f_compression = t_15; +- } +- if (self->private_impl.f_bits_per_pixel == 0u) { +- if (self->private_impl.f_compression == 4u) { +- self->private_impl.f_io_redirect_fourcc = 1246774599u; +- status = wuffs_base__make_status(wuffs_base__note__i_o_redirect); +- goto ok; +- } else if (self->private_impl.f_compression == 5u) { +- self->private_impl.f_io_redirect_fourcc = 1347307296u; +- status = wuffs_base__make_status(wuffs_base__note__i_o_redirect); +- goto ok; +- } +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- self->private_data.s_do_decode_image_config[0].scratch = 20u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(34); +- if (self->private_data.s_do_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_image_config[0].scratch; +- if (self->private_impl.f_bitmap_info_len == 40u) { +- if (self->private_impl.f_bits_per_pixel >= 16u) { +- if (self->private_impl.f_padding >= 16u) { +- self->private_impl.f_bitmap_info_len = 56u; +- self->private_impl.f_padding -= 16u; +- } else if (self->private_impl.f_padding >= 12u) { +- self->private_impl.f_bitmap_info_len = 52u; +- self->private_impl.f_padding -= 12u; +- } +- } +- } else if ((self->private_impl.f_bitmap_info_len != 52u) && +- (self->private_impl.f_bitmap_info_len != 56u) && +- (self->private_impl.f_bitmap_info_len != 64u) && +- (self->private_impl.f_bitmap_info_len != 108u) && +- (self->private_impl.f_bitmap_info_len != 124u)) { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- if (self->private_impl.f_compression == 6u) { +- self->private_impl.f_compression = 3u; +- } +- if (self->private_impl.f_compression == 3u) { +- if (self->private_impl.f_bitmap_info_len >= 52u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(35); +- uint32_t t_16; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_16 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(36); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_16 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_16; +- if (num_bits_16 == 24) { +- t_16 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_16 += 8u; +- *scratch |= ((uint64_t)(num_bits_16)) << 56; +- } +- } +- self->private_impl.f_channel_masks[2u] = t_16; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(37); +- uint32_t t_17; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_17 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(38); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_17 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_17; +- if (num_bits_17 == 24) { +- t_17 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_17 += 8u; +- *scratch |= ((uint64_t)(num_bits_17)) << 56; +- } +- } +- self->private_impl.f_channel_masks[1u] = t_17; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(39); +- uint32_t t_18; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_18 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(40); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_18 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_18; +- if (num_bits_18 == 24) { +- t_18 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_18 += 8u; +- *scratch |= ((uint64_t)(num_bits_18)) << 56; +- } +- } +- self->private_impl.f_channel_masks[0u] = t_18; +- } +- if (self->private_impl.f_bitmap_info_len >= 56u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(41); +- uint32_t t_19; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_19 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(42); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_19 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_19; +- if (num_bits_19 == 24) { +- t_19 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_19 += 8u; +- *scratch |= ((uint64_t)(num_bits_19)) << 56; +- } +- } +- self->private_impl.f_channel_masks[3u] = t_19; +- } +- self->private_data.s_do_decode_image_config[0].scratch = ((uint32_t)(self->private_impl.f_bitmap_info_len - 56u)); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(43); +- if (self->private_data.s_do_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_image_config[0].scratch; +- } +- if ((self->private_impl.f_channel_masks[0u] == 255u) && (self->private_impl.f_channel_masks[1u] == 65280u) && (self->private_impl.f_channel_masks[2u] == 16711680u)) { +- if (self->private_impl.f_bits_per_pixel == 24u) { +- self->private_impl.f_compression = 0u; +- } else if (self->private_impl.f_bits_per_pixel == 32u) { +- if ((self->private_impl.f_channel_masks[3u] == 0u) || (self->private_impl.f_channel_masks[3u] == 4278190080u)) { +- self->private_impl.f_compression = 0u; +- } +- } +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(44); +- status = wuffs_bmp__decoder__process_masks(self); +- if (status.repr) { +- goto suspend; +- } +- } +- } else if (self->private_impl.f_bitmap_info_len >= 40u) { +- self->private_data.s_do_decode_image_config[0].scratch = (self->private_impl.f_bitmap_info_len - 40u); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(45); +- if (self->private_data.s_do_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_image_config[0].scratch; +- } else { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- } +- if (self->private_impl.f_compression != 3u) { +- if (self->private_impl.f_bits_per_pixel < 16u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(46); +- status = wuffs_bmp__decoder__read_palette(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } +- } +- if (self->private_impl.f_compression == 0u) { +- if ((self->private_impl.f_bits_per_pixel == 1u) || (self->private_impl.f_bits_per_pixel == 2u) || (self->private_impl.f_bits_per_pixel == 4u)) { +- self->private_impl.f_src_pixfmt = 2198077448u; +- self->private_impl.f_compression = 256u; +- } else if (self->private_impl.f_bits_per_pixel == 8u) { +- self->private_impl.f_src_pixfmt = 2198077448u; +- } else if (self->private_impl.f_bits_per_pixel == 16u) { +- self->private_impl.f_compression = 3u; +- self->private_impl.f_channel_masks[0u] = 31u; +- self->private_impl.f_channel_masks[1u] = 992u; +- self->private_impl.f_channel_masks[2u] = 31744u; +- self->private_impl.f_channel_masks[3u] = 0u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(47); +- status = wuffs_bmp__decoder__process_masks(self); +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_src_pixfmt = 2164308923u; +- } else if (self->private_impl.f_bits_per_pixel == 24u) { +- self->private_impl.f_src_pixfmt = 2147485832u; +- } else if (self->private_impl.f_bits_per_pixel == 32u) { +- if (self->private_impl.f_channel_masks[3u] == 0u) { +- self->private_impl.f_src_pixfmt = 2415954056u; +- } else { +- self->private_impl.f_src_pixfmt = 2164295816u; +- } +- } else { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- } else if (self->private_impl.f_compression == 1u) { +- if (self->private_impl.f_bits_per_pixel == 8u) { +- self->private_impl.f_src_pixfmt = 2198077448u; +- } else { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- } else if (self->private_impl.f_compression == 2u) { +- if (self->private_impl.f_bits_per_pixel == 4u) { +- self->private_impl.f_src_pixfmt = 2198077448u; +- } else { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- } else if (self->private_impl.f_compression == 3u) { +- if ((self->private_impl.f_bits_per_pixel == 16u) || (self->private_impl.f_bits_per_pixel == 32u)) { +- self->private_impl.f_src_pixfmt = 2164308923u; +- } else { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- } else { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- if (((self->private_impl.f_bitmap_info_len < 40u) || (self->private_impl.f_bitmap_info_len == 64u)) && +- (self->private_impl.f_bits_per_pixel != 1u) && +- (self->private_impl.f_bits_per_pixel != 4u) && +- (self->private_impl.f_bits_per_pixel != 8u) && +- (self->private_impl.f_bits_per_pixel != 24u)) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; +- } +- if (self->private_impl.f_bits_per_pixel == 1u) { +- v_byte_width = ((self->private_impl.f_width >> 3u) + (((self->private_impl.f_width & 7u) + 7u) >> 3u)); +- self->private_impl.f_pad_per_row = ((4u - (v_byte_width & 3u)) & 3u); +- } else if (self->private_impl.f_bits_per_pixel == 2u) { +- v_byte_width = ((self->private_impl.f_width >> 2u) + (((self->private_impl.f_width & 3u) + 3u) >> 2u)); +- self->private_impl.f_pad_per_row = ((4u - (v_byte_width & 3u)) & 3u); +- } else if (self->private_impl.f_bits_per_pixel == 4u) { +- v_byte_width = ((self->private_impl.f_width >> 1u) + (self->private_impl.f_width & 1u)); +- self->private_impl.f_pad_per_row = ((4u - (v_byte_width & 3u)) & 3u); +- } else if (self->private_impl.f_bits_per_pixel == 8u) { +- self->private_impl.f_pad_per_row = ((4u - (self->private_impl.f_width & 3u)) & 3u); +- } else if (self->private_impl.f_bits_per_pixel == 16u) { +- self->private_impl.f_pad_per_row = ((self->private_impl.f_width & 1u) * 2u); +- } else if (self->private_impl.f_bits_per_pixel == 24u) { +- self->private_impl.f_pad_per_row = (self->private_impl.f_width & 3u); +- } else if (self->private_impl.f_bits_per_pixel == 32u) { +- self->private_impl.f_pad_per_row = 0u; +- } +- self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- if (a_dst != NULL) { +- v_dst_pixfmt = 2164295816u; +- if ((self->private_impl.f_channel_num_bits[0u] > 8u) || +- (self->private_impl.f_channel_num_bits[1u] > 8u) || +- (self->private_impl.f_channel_num_bits[2u] > 8u) || +- (self->private_impl.f_channel_num_bits[3u] > 8u)) { +- v_dst_pixfmt = 2164308923u; +- } +- wuffs_base__image_config__set( +- a_dst, +- v_dst_pixfmt, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height, +- self->private_impl.f_frame_config_io_position, +- (self->private_impl.f_channel_masks[3u] == 0u)); ++#endif ++ conv3func = &wuffs_private_impl__swizzle_ycc__convert_3_rgbx; ++ break; ++ default: ++ conv3func = &wuffs_private_impl__swizzle_ycc__convert_3_general; ++ break; + } +- self->private_impl.f_call_sequence = 32u; +- +- ok: +- self->private_impl.p_do_decode_image_config[0] = 0; +- goto exit; + } + +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ void (*func3)(wuffs_base__pixel_buffer * dst, // ++ uint32_t x_min_incl, // ++ uint32_t x_max_excl, // ++ uint32_t y_min_incl, // ++ uint32_t y_max_excl, // ++ const uint8_t* src_ptr0, // ++ const uint8_t* src_ptr1, // ++ const uint8_t* src_ptr2, // ++ uint32_t stride0, // ++ uint32_t stride1, // ++ uint32_t stride2, // ++ uint32_t inv_h0, // ++ uint32_t inv_h1, // ++ uint32_t inv_h2, // ++ uint32_t inv_v0, // ++ uint32_t inv_v1, // ++ uint32_t inv_v2, // ++ uint32_t half_width_for_2to1, // ++ uint32_t half_height_for_2to1, // ++ uint8_t* scratch_buffer_2k_ptr, // ++ wuffs_private_impl__swizzle_ycc__upsample_func(*upfuncs)[4][4], ++ wuffs_private_impl__swizzle_ycc__convert_3_func conv3func) = ++ &wuffs_private_impl__swizzle_ycc__general__box_filter; ++ ++ void (*func4)(wuffs_base__pixel_buffer * dst, // ++ uint32_t x_min_incl, // ++ uint32_t x_max_excl, // ++ uint32_t y_min_incl, // ++ uint32_t y_max_excl, // ++ const uint8_t* src_ptr0, // ++ const uint8_t* src_ptr1, // ++ const uint8_t* src_ptr2, // ++ const uint8_t* src_ptr3, // ++ uint32_t stride0, // ++ uint32_t stride1, // ++ uint32_t stride2, // ++ uint32_t stride3, // ++ uint32_t inv_h0, // ++ uint32_t inv_h1, // ++ uint32_t inv_h2, // ++ uint32_t inv_h3, // ++ uint32_t inv_v0, // ++ uint32_t inv_v1, // ++ uint32_t inv_v2, // ++ uint32_t inv_v3, // ++ uint32_t half_width_for_2to1, // ++ uint32_t half_height_for_2to1, // ++ uint8_t* scratch_buffer_2k_ptr, // ++ wuffs_private_impl__swizzle_ycc__upsample_func(*upfuncs)[4][4], ++ wuffs_private_impl__swizzle_ycc__convert_4_func conv4func) = ++ &wuffs_private_impl__swizzle_ycck__general__box_filter; ++ ++ wuffs_private_impl__swizzle_ycc__upsample_func upfuncs[4][4]; ++ memcpy(&upfuncs, &wuffs_private_impl__swizzle_ycc__upsample_funcs, ++ sizeof upfuncs); + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ if (triangle_filter_for_2to1 && ++ (wuffs_private_impl__swizzle_has_triangle_upsampler(inv_h0, inv_v0) || ++ wuffs_private_impl__swizzle_has_triangle_upsampler(inv_h1, inv_v1) || ++ wuffs_private_impl__swizzle_has_triangle_upsampler(inv_h2, inv_v2) || ++ wuffs_private_impl__swizzle_has_triangle_upsampler(inv_h3, inv_v3))) { ++ func3 = &wuffs_private_impl__swizzle_ycc__general__triangle_filter; ++ func4 = &wuffs_private_impl__swizzle_ycck__general__triangle_filter; ++ ++ upfuncs[0][1] = wuffs_private_impl__swizzle_ycc__upsample_inv_h1v2_triangle; ++ upfuncs[1][0] = wuffs_private_impl__swizzle_ycc__upsample_inv_h2v1_triangle; ++ upfuncs[1][1] = wuffs_private_impl__swizzle_ycc__upsample_inv_h2v2_triangle; ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++#if defined(__GNUC__) && !defined(__clang__) ++ // Don't use our AVX2 implementation for GCC (but do use it for clang). For ++ // some unknown reason, GCC performs noticably better on the non-SIMD ++ // version. Possibly because GCC's auto-vectorizer is smarter (just with ++ // SSE2, not AVX2) than our hand-written code, but that's just a guess. ++ // ++ // See commits 51bc60ef9298cb2efc1b29a9681191f66d49820d and ++ // cd769a0cdf1b5affee13f6089b995f3d39569cb4 for benchmark numbers. ++ // ++ // See also https://godbolt.org/z/MbhbPGEz4 for Debian Bullseye's clang 11 ++ // versus gcc 10, where only gcc auto-vectorizes, although later clang ++ // versions will also auto-vectorize. ++#else ++ if (wuffs_base__cpu_arch__have_x86_avx2()) { ++ upfuncs[1][1] = ++ wuffs_private_impl__swizzle_ycc__upsample_inv_h2v2_triangle_x86_avx2; ++ } ++#endif ++#endif + } + +- return status; +-} +- +-// -------- func bmp.decoder.decode_frame_config ++ if ((h3 != 0u) || (v3 != 0u)) { ++ wuffs_private_impl__swizzle_ycc__convert_4_func conv4func = ++ is_rgb_or_cmyk ? &wuffs_private_impl__swizzle_cmyk__convert_4_general ++ : &wuffs_private_impl__swizzle_ycck__convert_4_general; ++ (*func4)( // ++ dst, x_min_incl, x_max_excl, y_min_incl, y_max_excl, // ++ src0.ptr, src1.ptr, src2.ptr, src3.ptr, // ++ stride0, stride1, stride2, stride3, // ++ inv_h0, inv_h1, inv_h2, inv_h3, // ++ inv_v0, inv_v1, inv_v2, inv_v3, // ++ half_width_for_2to1, half_height_for_2to1, // ++ scratch_buffer_2k.ptr, &upfuncs, conv4func); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_bmp__decoder__decode_frame_config( +- wuffs_bmp__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 2)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } else { ++ (*func3)( // ++ dst, x_min_incl, x_max_excl, y_min_incl, y_max_excl, // ++ src0.ptr, src1.ptr, src2.ptr, // ++ stride0, stride1, stride2, // ++ inv_h0, inv_h1, inv_h2, // ++ inv_v0, inv_v1, inv_v2, // ++ half_width_for_2to1, half_height_for_2to1, // ++ scratch_buffer_2k.ptr, &upfuncs, conv3func); + } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ return wuffs_base__make_status(NULL); ++} + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_bmp__decoder__do_decode_frame_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_bmp__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++// -------- + +- ok: +- self->private_impl.p_decode_frame_config[0] = 0; +- goto exit; ++// ‼ WUFFS MULTI-FILE SECTION +x86_avx2 ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") ++static void // ++wuffs_private_impl__swizzle_ycc__convert_3_bgrx_x86_avx2( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2) { ++ if ((x + 32u) > x_end) { ++ wuffs_private_impl__swizzle_ycc__convert_3_bgrx( // ++ dst, x, x_end, y, up0, up1, up2); ++ return; + } + +- goto suspend; +- suspend: +- self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ size_t dst_stride = dst->private_impl.planes[0].stride; ++ uint8_t* dst_iter = dst->private_impl.planes[0].ptr + ++ (dst_stride * ((size_t)y)) + (4u * ((size_t)x)); + +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} ++ // u0001 = u16x16 [0x0001 .. 0x0001] ++ // u00FF = u16x16 [0x00FF .. 0x00FF] ++ // uFF80 = u16x16 [0xFF80 .. 0xFF80] ++ // uFFFF = u16x16 [0xFFFF .. 0xFFFF] ++ const __m256i u0001 = _mm256_set1_epi16(+0x0001); ++ const __m256i u00FF = _mm256_set1_epi16(+0x00FF); ++ const __m256i uFF80 = _mm256_set1_epi16(-0x0080); ++ const __m256i uFFFF = _mm256_set1_epi16(-0x0001); + +-// -------- func bmp.decoder.do_decode_frame_config ++ // p8000_p0000 = u16x16 [0x8000 0x0000 .. 0x8000 0x0000] ++ const __m256i p8000_p0000 = _mm256_set_epi16( // ++ +0x0000, -0x8000, +0x0000, -0x8000, // ++ +0x0000, -0x8000, +0x0000, -0x8000, // ++ +0x0000, -0x8000, +0x0000, -0x8000, // ++ +0x0000, -0x8000, +0x0000, -0x8000); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__do_decode_frame_config( +- wuffs_bmp__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ // Per wuffs_base__color_ycc__as__color_u32, the formulae: ++ // ++ // R = Y + 1.40200 * Cr ++ // G = Y - 0.34414 * Cb - 0.71414 * Cr ++ // B = Y + 1.77200 * Cb ++ // ++ // When scaled by 1<<16: ++ // ++ // 0.34414 becomes 0x0581A = 22554. ++ // 0.71414 becomes 0x0B6D2 = 46802. ++ // 1.40200 becomes 0x166E9 = 91881. ++ // 1.77200 becomes 0x1C5A2 = 116130. ++ // ++ // Separate the integer and fractional parts, since we work with signed ++ // 16-bit SIMD lanes. The fractional parts range from -0.5 .. +0.5 (as ++ // floating-point) which is from -0x8000 .. +0x8000 (as fixed-point). ++ // ++ // -0x3A5E = -0x20000 + 0x1C5A2 The B:Cb factor. ++ // +0x66E9 = -0x10000 + 0x166E9 The R:Cr factor. ++ // -0x581A = +0x00000 - 0x0581A The G:Cb factor. ++ // +0x492E = +0x10000 - 0x0B6D2 The G:Cr factor. ++ const __m256i m3A5E = _mm256_set1_epi16(-0x3A5E); ++ const __m256i p66E9 = _mm256_set1_epi16(+0x66E9); ++ const __m256i m581A_p492E = _mm256_set_epi16( // ++ +0x492E, -0x581A, +0x492E, -0x581A, // ++ +0x492E, -0x581A, +0x492E, -0x581A, // ++ +0x492E, -0x581A, +0x492E, -0x581A, // ++ +0x492E, -0x581A, +0x492E, -0x581A); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ while (x < x_end) { ++ // Load chroma values in even and odd columns (the high 8 bits of each ++ // u16x16 element are zero) and then subtract 0x0080. ++ // ++ // cb_all = u8x32 [cb.00 cb.01 cb.02 cb.03 .. cb.1C cb.1D cb.1E cb.1F] ++ // cb_eve = i16x16 [cb.00-0x80 cb.02-0x80 .. cb.1C-0x80 cb.1E-0x80 ] ++ // cb_odd = i16x16 [cb.01-0x80 cb.03-0x80 .. cb.1D-0x80 cb.1F-0x80 ] ++ // ++ // Ditto for the cr_xxx Chroma-Red values. ++ __m256i cb_all = _mm256_lddqu_si256((const __m256i*)(const void*)up1); ++ __m256i cr_all = _mm256_lddqu_si256((const __m256i*)(const void*)up2); ++ __m256i cb_eve = _mm256_add_epi16(uFF80, _mm256_and_si256(cb_all, u00FF)); ++ __m256i cr_eve = _mm256_add_epi16(uFF80, _mm256_and_si256(cr_all, u00FF)); ++ __m256i cb_odd = _mm256_add_epi16(uFF80, _mm256_srli_epi16(cb_all, 8)); ++ __m256i cr_odd = _mm256_add_epi16(uFF80, _mm256_srli_epi16(cr_all, 8)); + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ // ---- + +- if (self->private_impl.f_call_sequence == 32u) { +- } else if (self->private_impl.f_call_sequence < 32u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_bmp__decoder__do_decode_image_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } else if (self->private_impl.f_call_sequence == 40u) { +- if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_restart); +- goto exit; +- } +- } else if (self->private_impl.f_call_sequence == 64u) { +- self->private_impl.f_call_sequence = 96u; +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- if (a_dst != NULL) { +- wuffs_base__frame_config__set( +- a_dst, +- wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height), +- ((wuffs_base__flicks)(0u)), +- 0u, +- self->private_impl.f_frame_config_io_position, +- 0u, +- true, +- false, +- 4278190080u); +- } +- self->private_impl.f_call_sequence = 64u; ++ // Calculate: ++ // ++ // B-Y = (+1.77200 * Cb) as floating-point ++ // R-Y = (+1.40200 * Cr) as floating-point ++ // ++ // B-Y = ((0x2_0000 - 0x3A5E) * Cb) as fixed-point ++ // R-Y = ((0x1_0000 + 0x66E9) * Cr) as fixed-point ++ // ++ // B-Y = ((-0x3A5E * Cb) + ("2.0" * Cb)) ++ // R-Y = ((+0x66E9 * Cr) + ("1.0" * Cr)) + +- ok: +- self->private_impl.p_do_decode_frame_config[0] = 0; +- goto exit; +- } ++ // Multiply by m3A5E or p66E9, taking the high 16 bits. There's also a ++ // doubling (add x to itself), adding-of-1 and halving (shift right by 1). ++ // That makes multiply-and-take-high round to nearest (instead of down). ++ __m256i tmp_by_eve = _mm256_srai_epi16( ++ _mm256_add_epi16( ++ _mm256_mulhi_epi16(_mm256_add_epi16(cb_eve, cb_eve), m3A5E), u0001), ++ 1); ++ __m256i tmp_by_odd = _mm256_srai_epi16( ++ _mm256_add_epi16( ++ _mm256_mulhi_epi16(_mm256_add_epi16(cb_odd, cb_odd), m3A5E), u0001), ++ 1); ++ __m256i tmp_ry_eve = _mm256_srai_epi16( ++ _mm256_add_epi16( ++ _mm256_mulhi_epi16(_mm256_add_epi16(cr_eve, cr_eve), p66E9), u0001), ++ 1); ++ __m256i tmp_ry_odd = _mm256_srai_epi16( ++ _mm256_add_epi16( ++ _mm256_mulhi_epi16(_mm256_add_epi16(cr_odd, cr_odd), p66E9), u0001), ++ 1); + +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ // Add (2 * Cb) and (1 * Cr). ++ __m256i by_eve = ++ _mm256_add_epi16(tmp_by_eve, _mm256_add_epi16(cb_eve, cb_eve)); ++ __m256i by_odd = ++ _mm256_add_epi16(tmp_by_odd, _mm256_add_epi16(cb_odd, cb_odd)); ++ __m256i ry_eve = _mm256_add_epi16(tmp_ry_eve, cr_eve); ++ __m256i ry_odd = _mm256_add_epi16(tmp_ry_odd, cr_odd); + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++ // ---- + +- return status; +-} ++ // Calculate: ++ // ++ // G-Y = (-0.34414 * Cb) + ++ // (-0.71414 * Cr) as floating-point ++ // ++ // G-Y = ((+0x0_0000 - 0x581A) * Cb) + ++ // ((-0x1_0000 + 0x492E) * Cr) as fixed-point ++ // ++ // G-Y = (-0x581A * Cb) + ++ // (+0x492E * Cr) - ("1.0" * Cr) + +-// -------- func bmp.decoder.decode_frame ++ // Multiply-add to get ((-0x581A * Cb) + (+0x492E * Cr)). ++ __m256i tmp0_gy_eve_lo = _mm256_madd_epi16( // ++ _mm256_unpacklo_epi16(cb_eve, cr_eve), m581A_p492E); ++ __m256i tmp0_gy_eve_hi = _mm256_madd_epi16( // ++ _mm256_unpackhi_epi16(cb_eve, cr_eve), m581A_p492E); ++ __m256i tmp0_gy_odd_lo = _mm256_madd_epi16( // ++ _mm256_unpacklo_epi16(cb_odd, cr_odd), m581A_p492E); ++ __m256i tmp0_gy_odd_hi = _mm256_madd_epi16( // ++ _mm256_unpackhi_epi16(cb_odd, cr_odd), m581A_p492E); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_bmp__decoder__decode_frame( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 3)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ // Divide the i32x8 vectors by (1 << 16), rounding to nearest. ++ __m256i tmp1_gy_eve_lo = ++ _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_eve_lo, p8000_p0000), 16); ++ __m256i tmp1_gy_eve_hi = ++ _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_eve_hi, p8000_p0000), 16); ++ __m256i tmp1_gy_odd_lo = ++ _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_odd_lo, p8000_p0000), 16); ++ __m256i tmp1_gy_odd_hi = ++ _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_odd_hi, p8000_p0000), 16); + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ // Pack the ((-0x581A * Cb) + (+0x492E * Cr)) as i16x16 and subtract Cr. ++ __m256i gy_eve = _mm256_sub_epi16( ++ _mm256_packs_epi32(tmp1_gy_eve_lo, tmp1_gy_eve_hi), cr_eve); ++ __m256i gy_odd = _mm256_sub_epi16( ++ _mm256_packs_epi32(tmp1_gy_odd_lo, tmp1_gy_odd_hi), cr_odd); + +- uint32_t coro_susp_point = self->private_impl.p_decode_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ // ---- + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_bmp__decoder__do_decode_frame(self, +- a_dst, +- a_src, +- a_blend, +- a_workbuf, +- a_opts); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_bmp__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++ // Add Y to (B-Y), (G-Y) and (R-Y) to produce B, G and R. ++ // ++ // For the resultant packed_x_xxx vectors, only elements 0 ..= 7 and 16 ..= ++ // 23 of the 32-element vectors matter (since we'll unpacklo but not ++ // unpackhi them). Let … denote 8 ignored consecutive u8 values and let % ++ // denote 0xFF. We'll end this section with: ++ // ++ // packed_b_eve = u8x32 [b00 b02 .. b0C b0E … b10 b12 .. b1C b1E …] ++ // packed_b_odd = u8x32 [b01 b03 .. b0D b0F … b11 b13 .. b1D b1F …] ++ // packed_g_eve = u8x32 [g00 g02 .. g0C g0E … g10 g12 .. g1C g1E …] ++ // packed_g_odd = u8x32 [g01 g03 .. g0D g0F … g11 g13 .. g1D g1F …] ++ // packed_r_eve = u8x32 [r00 r02 .. r0C r0E … r10 r12 .. r1C r1E …] ++ // packed_r_odd = u8x32 [r01 r03 .. r0D r0F … r11 r13 .. r1D r1F …] ++ // uFFFF = u8x32 [ % % .. % % … % % .. % % …] + +- ok: +- self->private_impl.p_decode_frame[0] = 0; +- goto exit; +- } ++ __m256i yy_all = _mm256_lddqu_si256((const __m256i*)(const void*)up0); ++ __m256i yy_eve = _mm256_and_si256(yy_all, u00FF); ++ __m256i yy_odd = _mm256_srli_epi16(yy_all, 8); + +- goto suspend; +- suspend: +- self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ __m256i loose_b_eve = _mm256_add_epi16(by_eve, yy_eve); ++ __m256i loose_b_odd = _mm256_add_epi16(by_odd, yy_odd); ++ __m256i packed_b_eve = _mm256_packus_epi16(loose_b_eve, loose_b_eve); ++ __m256i packed_b_odd = _mm256_packus_epi16(loose_b_odd, loose_b_odd); + +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} ++ __m256i loose_g_eve = _mm256_add_epi16(gy_eve, yy_eve); ++ __m256i loose_g_odd = _mm256_add_epi16(gy_odd, yy_odd); ++ __m256i packed_g_eve = _mm256_packus_epi16(loose_g_eve, loose_g_eve); ++ __m256i packed_g_odd = _mm256_packus_epi16(loose_g_odd, loose_g_odd); + +-// -------- func bmp.decoder.do_decode_frame ++ __m256i loose_r_eve = _mm256_add_epi16(ry_eve, yy_eve); ++ __m256i loose_r_odd = _mm256_add_epi16(ry_odd, yy_odd); ++ __m256i packed_r_eve = _mm256_packus_epi16(loose_r_eve, loose_r_eve); ++ __m256i packed_r_odd = _mm256_packus_epi16(loose_r_odd, loose_r_odd); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__do_decode_frame( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ // ---- + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ // Mix those values (unpacking in 8, 16 and then 32 bit units) to get the ++ // desired BGRX/RGBX order. ++ // ++ // From here onwards, all of our __m256i registers are u8x32. + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ // mix00 = [b00 g00 b02 g02 .. b0E g0E b10 g10 .. b1C g1C b1E g1E] ++ // mix01 = [b01 g01 b03 g03 .. b0F g0F b11 g11 .. b1D g1D b1F g1F] ++ // mix02 = [r00 % r02 % .. r0E % r10 % .. r1C % r1E %] ++ // mix03 = [r01 % r03 % .. r0F % r11 % .. r1D % r1F %] ++ // ++ // See also § below. ++ __m256i mix00 = _mm256_unpacklo_epi8(packed_b_eve, packed_g_eve); ++ __m256i mix01 = _mm256_unpacklo_epi8(packed_b_odd, packed_g_odd); ++ __m256i mix02 = _mm256_unpacklo_epi8(packed_r_eve, uFFFF); ++ __m256i mix03 = _mm256_unpacklo_epi8(packed_r_odd, uFFFF); + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ // mix10 = [b00 g00 r00 % b02 g02 r02 % b04 g04 r04 % b06 g06 r06 % ++ // b10 g10 r10 % b12 g12 r12 % b14 g14 r14 % b16 g16 r16 %] ++ // mix11 = [b01 g01 r01 % b03 g03 r03 % b05 g05 r05 % b07 g07 r07 % ++ // b11 g11 r11 % b13 g13 r13 % b15 g15 r15 % b17 g17 r17 %] ++ // mix12 = [b08 g08 r08 % b0A g0A r0A % b0C g0C r0C % b0E g0E r0E % ++ // b18 g18 r18 % b1A g1A r1A % b1C g1C r1C % b1E g1E r1E %] ++ // mix13 = [b09 g09 r09 % b0B g0B r0B % b0D g0D r0D % b0F g0F r0F % ++ // b19 g19 r19 % b1B g1B r1B % b1D g1D r1D % b1F g1F r1F %] ++ __m256i mix10 = _mm256_unpacklo_epi16(mix00, mix02); ++ __m256i mix11 = _mm256_unpacklo_epi16(mix01, mix03); ++ __m256i mix12 = _mm256_unpackhi_epi16(mix00, mix02); ++ __m256i mix13 = _mm256_unpackhi_epi16(mix01, mix03); + +- if (self->private_impl.f_call_sequence == 64u) { +- } else if (self->private_impl.f_call_sequence < 64u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_bmp__decoder__do_decode_frame_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- self->private_data.s_do_decode_frame[0].scratch = self->private_impl.f_padding; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (self->private_data.s_do_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_frame[0].scratch; +- if ((self->private_impl.f_width > 0u) && (self->private_impl.f_height > 0u)) { +- self->private_impl.f_dst_x = 0u; +- if (self->private_impl.f_top_down) { +- self->private_impl.f_dst_y = 0u; +- self->private_impl.f_dst_y_inc = 1u; +- } else { +- self->private_impl.f_dst_y = ((uint32_t)(self->private_impl.f_height - 1u)); +- self->private_impl.f_dst_y_inc = 4294967295u; +- } +- v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, +- wuffs_base__pixel_buffer__pixel_format(a_dst), +- wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)), +- wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt), +- wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024), +- a_blend); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } +- while (true) { +- if (self->private_impl.f_compression == 0u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_status = wuffs_bmp__decoder__swizzle_none(self, a_dst, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } else if (self->private_impl.f_compression < 3u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_status = wuffs_bmp__decoder__swizzle_rle(self, a_dst, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } else if (self->private_impl.f_compression == 3u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_status = wuffs_bmp__decoder__swizzle_bitfields(self, a_dst, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } else { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_status = wuffs_bmp__decoder__swizzle_low_bit_depth(self, a_dst, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } +- if (wuffs_base__status__is_ok(&v_status)) { +- break; +- } else if (v_status.repr != wuffs_bmp__note__internal_note_short_read) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- } +- self->private_data.s_do_decode_frame[0].scratch = self->private_impl.f_pending_pad; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (self->private_data.s_do_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_frame[0].scratch; +- self->private_impl.f_pending_pad = 0u; +- } +- self->private_impl.f_call_sequence = 96u; ++ // mix20 = [b00 g00 r00 % b01 g01 r01 % b02 g02 r02 % b03 g03 r03 % ++ // b10 g10 r10 % b11 g11 r11 % b12 g12 r12 % b13 g13 r13 %] ++ // mix21 = [b04 g04 r04 % b05 g05 r05 % b06 g06 r06 % b07 g07 r07 % ++ // b14 g14 r14 % b15 g15 r15 % b16 g16 r16 % b17 g17 r17 %] ++ // mix22 = [b08 g08 r08 % b09 g09 r09 % b0A g0A r0A % b0B g0B r0B % ++ // b18 g18 r18 % b19 g19 r19 % b1A g1A r1A % b1B g1B r1B %] ++ // mix23 = [b0C g0C r0C % b0D g0D r0D % b0E g0E r0E % b0F g0F r0F % ++ // b1C g1C r1C % b1D g1D r1D % b1E g1E r1E % b1F g1F r1F %] ++ __m256i mix20 = _mm256_unpacklo_epi32(mix10, mix11); ++ __m256i mix21 = _mm256_unpackhi_epi32(mix10, mix11); ++ __m256i mix22 = _mm256_unpacklo_epi32(mix12, mix13); ++ __m256i mix23 = _mm256_unpackhi_epi32(mix12, mix13); + +- ok: +- self->private_impl.p_do_decode_frame[0] = 0; +- goto exit; +- } ++ // mix30 = [b00 g00 r00 % b01 g01 r01 % b02 g02 r02 % b03 g03 r03 % ++ // b04 g04 r04 % b05 g05 r05 % b06 g06 r06 % b07 g07 r07 %] ++ // mix31 = [b08 g08 r08 % b09 g09 r09 % b0A g0A r0A % b0B g0B r0B % ++ // b0C g0C r0C % b0D g0D r0D % b0E g0E r0E % b0F g0F r0F %] ++ // mix32 = [b10 g10 r10 % b11 g11 r11 % b12 g12 r12 % b13 g13 r13 % ++ // b14 g14 r14 % b15 g15 r15 % b16 g16 r16 % b17 g17 r17 %] ++ // mix33 = [b18 g18 r18 % b19 g19 r19 % b1A g1A r1A % b1B g1B r1B % ++ // b1C g1C r1C % b1D g1D r1D % b1E g1E r1E % b1F g1F r1F %] ++ __m256i mix30 = _mm256_permute2x128_si256(mix20, mix21, 0x20); ++ __m256i mix31 = _mm256_permute2x128_si256(mix22, mix23, 0x20); ++ __m256i mix32 = _mm256_permute2x128_si256(mix20, mix21, 0x31); ++ __m256i mix33 = _mm256_permute2x128_si256(mix22, mix23, 0x31); + +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ // Write out four u8x32 SIMD registers (128 bytes, 32 BGRX/RGBX pixels). ++ _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x00), mix30); ++ _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x20), mix31); ++ _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x40), mix32); ++ _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x60), mix33); + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ // Advance by up to 32 pixels. The first iteration might be smaller than 32 ++ // so that all of the remaining steps are exactly 32. ++ uint32_t n = 32u - (31u & (x - x_end)); ++ dst_iter += 4u * n; ++ up0 += n; ++ up1 += n; ++ up2 += n; ++ x += n; + } +- +- return status; + } + +-// -------- func bmp.decoder.swizzle_none ++// The rgbx flavor (below) is exactly the same as the bgrx flavor (above) ++// except for the lines marked with a § and that comments were stripped. ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") ++static void // ++wuffs_private_impl__swizzle_ycc__convert_3_rgbx_x86_avx2( ++ wuffs_base__pixel_buffer* dst, ++ uint32_t x, ++ uint32_t x_end, ++ uint32_t y, ++ const uint8_t* up0, ++ const uint8_t* up1, ++ const uint8_t* up2) { ++ if ((x + 32u) > x_end) { ++ wuffs_private_impl__swizzle_ycc__convert_3_bgrx( // ++ dst, x, x_end, y, up0, up1, up2); ++ return; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__swizzle_none( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ size_t dst_stride = dst->private_impl.planes[0].stride; ++ uint8_t* dst_iter = dst->private_impl.planes[0].ptr + ++ (dst_stride * ((size_t)y)) + (4u * ((size_t)x)); + +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint32_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_bytes_per_row = 0; +- uint32_t v_src_bytes_per_pixel = 0; +- wuffs_base__slice_u8 v_dst_palette = {0}; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint64_t v_i = 0; +- uint64_t v_j = 0; +- uint64_t v_n = 0; ++ const __m256i u0001 = _mm256_set1_epi16(+0x0001); ++ const __m256i u00FF = _mm256_set1_epi16(+0x00FF); ++ const __m256i uFF80 = _mm256_set1_epi16(-0x0080); ++ const __m256i uFFFF = _mm256_set1_epi16(-0x0001); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ const __m256i p8000_p0000 = _mm256_set_epi16( // ++ +0x0000, -0x8000, +0x0000, -0x8000, // ++ +0x0000, -0x8000, +0x0000, -0x8000, // ++ +0x0000, -0x8000, +0x0000, -0x8000, // ++ +0x0000, -0x8000, +0x0000, -0x8000); + +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_option); +- goto exit; +- } +- v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); +- v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); +- v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- label__outer__continue:; +- while (true) { +- while (self->private_impl.f_pending_pad > 0u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); +- goto ok; +- } +- self->private_impl.f_pending_pad -= 1u; +- iop_a_src += 1u; +- } +- while (true) { +- if (self->private_impl.f_dst_x == self->private_impl.f_width) { +- self->private_impl.f_dst_x = 0u; +- self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; +- if (self->private_impl.f_dst_y >= self->private_impl.f_height) { +- if (self->private_impl.f_height > 0u) { +- self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row; +- } +- goto label__outer__break; +- } else if (self->private_impl.f_pad_per_row != 0u) { +- self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row; +- goto label__outer__continue; +- } +- } +- v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); +- } +- v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); +- if (v_i >= ((uint64_t)(v_dst.len))) { +- if (self->private_impl.f_bits_per_pixel > 32u) { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- v_src_bytes_per_pixel = (self->private_impl.f_bits_per_pixel / 8u); +- if (v_src_bytes_per_pixel == 0u) { +- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); +- goto exit; +- } +- v_n = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(v_src_bytes_per_pixel))); +- v_n = wuffs_base__u64__min(v_n, ((uint64_t)(((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x))))); +- v_j = v_n; +- while (v_j >= 8u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 8u)))) { +- iop_a_src += (v_src_bytes_per_pixel * 8u); +- } +- v_j -= 8u; +- } +- while (v_j > 0u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 1u)))) { +- iop_a_src += (v_src_bytes_per_pixel * 1u); +- } +- v_j -= 1u; +- } +- } else { +- v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( +- &self->private_impl.f_swizzler, +- wuffs_base__slice_u8__subslice_i(v_dst, v_i), +- v_dst_palette, +- &iop_a_src, +- io2_a_src); +- } +- if (v_n == 0u) { +- status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); +- goto ok; +- } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); +- } +- } +- label__outer__break:; +- status = wuffs_base__make_status(NULL); +- goto ok; ++ const __m256i m3A5E = _mm256_set1_epi16(-0x3A5E); ++ const __m256i p66E9 = _mm256_set1_epi16(+0x66E9); ++ const __m256i m581A_p492E = _mm256_set_epi16( // ++ +0x492E, -0x581A, +0x492E, -0x581A, // ++ +0x492E, -0x581A, +0x492E, -0x581A, // ++ +0x492E, -0x581A, +0x492E, -0x581A, // ++ +0x492E, -0x581A, +0x492E, -0x581A); + +- ok: +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++ while (x < x_end) { ++ __m256i cb_all = _mm256_lddqu_si256((const __m256i*)(const void*)up1); ++ __m256i cr_all = _mm256_lddqu_si256((const __m256i*)(const void*)up2); ++ __m256i cb_eve = _mm256_add_epi16(uFF80, _mm256_and_si256(cb_all, u00FF)); ++ __m256i cr_eve = _mm256_add_epi16(uFF80, _mm256_and_si256(cr_all, u00FF)); ++ __m256i cb_odd = _mm256_add_epi16(uFF80, _mm256_srli_epi16(cb_all, 8)); ++ __m256i cr_odd = _mm256_add_epi16(uFF80, _mm256_srli_epi16(cr_all, 8)); + +- return status; +-} ++ __m256i tmp_by_eve = _mm256_srai_epi16( ++ _mm256_add_epi16( ++ _mm256_mulhi_epi16(_mm256_add_epi16(cb_eve, cb_eve), m3A5E), u0001), ++ 1); ++ __m256i tmp_by_odd = _mm256_srai_epi16( ++ _mm256_add_epi16( ++ _mm256_mulhi_epi16(_mm256_add_epi16(cb_odd, cb_odd), m3A5E), u0001), ++ 1); ++ __m256i tmp_ry_eve = _mm256_srai_epi16( ++ _mm256_add_epi16( ++ _mm256_mulhi_epi16(_mm256_add_epi16(cr_eve, cr_eve), p66E9), u0001), ++ 1); ++ __m256i tmp_ry_odd = _mm256_srai_epi16( ++ _mm256_add_epi16( ++ _mm256_mulhi_epi16(_mm256_add_epi16(cr_odd, cr_odd), p66E9), u0001), ++ 1); + +-// -------- func bmp.decoder.swizzle_rle ++ __m256i by_eve = ++ _mm256_add_epi16(tmp_by_eve, _mm256_add_epi16(cb_eve, cb_eve)); ++ __m256i by_odd = ++ _mm256_add_epi16(tmp_by_odd, _mm256_add_epi16(cb_odd, cb_odd)); ++ __m256i ry_eve = _mm256_add_epi16(tmp_ry_eve, cr_eve); ++ __m256i ry_odd = _mm256_add_epi16(tmp_ry_odd, cr_odd); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__swizzle_rle( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ __m256i tmp0_gy_eve_lo = _mm256_madd_epi16( // ++ _mm256_unpacklo_epi16(cb_eve, cr_eve), m581A_p492E); ++ __m256i tmp0_gy_eve_hi = _mm256_madd_epi16( // ++ _mm256_unpackhi_epi16(cb_eve, cr_eve), m581A_p492E); ++ __m256i tmp0_gy_odd_lo = _mm256_madd_epi16( // ++ _mm256_unpacklo_epi16(cb_odd, cr_odd), m581A_p492E); ++ __m256i tmp0_gy_odd_hi = _mm256_madd_epi16( // ++ _mm256_unpackhi_epi16(cb_odd, cr_odd), m581A_p492E); + +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint32_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_bytes_per_row = 0; +- wuffs_base__slice_u8 v_dst_palette = {0}; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_row = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint64_t v_i = 0; +- uint64_t v_n = 0; +- uint32_t v_p0 = 0; +- uint8_t v_code = 0; +- uint8_t v_indexes[2] = {0}; +- uint32_t v_rle_state = 0; +- uint32_t v_chunk_bits = 0; +- uint32_t v_chunk_count = 0; ++ __m256i tmp1_gy_eve_lo = ++ _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_eve_lo, p8000_p0000), 16); ++ __m256i tmp1_gy_eve_hi = ++ _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_eve_hi, p8000_p0000), 16); ++ __m256i tmp1_gy_odd_lo = ++ _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_odd_lo, p8000_p0000), 16); ++ __m256i tmp1_gy_odd_hi = ++ _mm256_srai_epi32(_mm256_add_epi32(tmp0_gy_odd_hi, p8000_p0000), 16); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ __m256i gy_eve = _mm256_sub_epi16( ++ _mm256_packs_epi32(tmp1_gy_eve_lo, tmp1_gy_eve_hi), cr_eve); ++ __m256i gy_odd = _mm256_sub_epi16( ++ _mm256_packs_epi32(tmp1_gy_odd_lo, tmp1_gy_odd_hi), cr_odd); + +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_option); +- goto exit; +- } +- v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); +- v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); +- v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- v_rle_state = self->private_impl.f_rle_state; +- label__outer__continue:; +- while (true) { +- v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) { +- v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row); +- } +- label__middle__continue:; +- while (true) { +- v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); +- if (v_i <= ((uint64_t)(v_row.len))) { +- v_dst = wuffs_base__slice_u8__subslice_i(v_row, v_i); +- } else { +- v_dst = wuffs_base__utility__empty_slice_u8(); +- } +- while (true) { +- while (true) { +- if (v_rle_state == 0u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { +- goto label__goto_suspend__break; +- } +- v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- if (v_code == 0u) { +- v_rle_state = 2u; +- continue; +- } +- self->private_impl.f_rle_length = ((uint32_t)(v_code)); +- v_rle_state = 1u; +- continue; +- } else if (v_rle_state == 1u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { +- goto label__goto_suspend__break; +- } +- v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- if (self->private_impl.f_bits_per_pixel == 8u) { +- v_p0 = 0u; +- while (v_p0 < self->private_impl.f_rle_length) { +- self->private_data.f_scratch[v_p0] = v_code; +- v_p0 += 1u; +- } +- } else { +- v_indexes[0u] = ((uint8_t)((v_code >> 4u))); +- v_indexes[1u] = (v_code & 15u); +- v_p0 = 0u; +- while (v_p0 < self->private_impl.f_rle_length) { +- self->private_data.f_scratch[(v_p0 + 0u)] = v_indexes[0u]; +- self->private_data.f_scratch[(v_p0 + 1u)] = v_indexes[1u]; +- v_p0 += 2u; +- } +- } +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_rle_length)); +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, self->private_impl.f_rle_length); +- v_rle_state = 0u; +- goto label__middle__continue; +- } else if (v_rle_state == 2u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { +- goto label__goto_suspend__break; +- } +- v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- if (v_code < 2u) { +- if ((self->private_impl.f_dst_y >= self->private_impl.f_height) && (v_code == 0u)) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression); +- goto exit; +- } +- wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_dst, v_dst_palette, 18446744073709551615u); +- self->private_impl.f_dst_x = 0u; +- self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; +- if (v_code > 0u) { +- goto label__outer__break; +- } +- v_rle_state = 0u; +- goto label__outer__continue; +- } else if (v_code == 2u) { +- v_rle_state = 4u; +- continue; +- } +- self->private_impl.f_rle_length = ((uint32_t)(v_code)); +- self->private_impl.f_rle_padded = ((self->private_impl.f_bits_per_pixel == 8u) && ((v_code & 1u) != 0u)); +- v_rle_state = 3u; +- continue; +- } else if (v_rle_state == 3u) { +- if (self->private_impl.f_bits_per_pixel == 8u) { +- v_n = wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader( +- &self->private_impl.f_swizzler, +- self->private_impl.f_rle_length, +- v_dst, +- v_dst_palette, +- &iop_a_src, +- io2_a_src); +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); +- wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_rle_length, ((uint32_t)(v_n))); +- } else { +- v_chunk_count = ((self->private_impl.f_rle_length + 3u) / 4u); +- v_p0 = 0u; +- while ((v_chunk_count > 0u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 2u)) { +- v_chunk_bits = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); +- iop_a_src += 2u; +- self->private_data.f_scratch[(v_p0 + 0u)] = ((uint8_t)((15u & (v_chunk_bits >> 12u)))); +- self->private_data.f_scratch[(v_p0 + 1u)] = ((uint8_t)((15u & (v_chunk_bits >> 8u)))); +- self->private_data.f_scratch[(v_p0 + 2u)] = ((uint8_t)((15u & (v_chunk_bits >> 4u)))); +- self->private_data.f_scratch[(v_p0 + 3u)] = ((uint8_t)((15u & (v_chunk_bits >> 0u)))); +- v_p0 = ((v_p0 & 255u) + 4u); +- v_chunk_count -= 1u; +- } +- v_p0 = wuffs_base__u32__min(v_p0, self->private_impl.f_rle_length); +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, v_p0)); +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, v_p0); +- wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_rle_length, v_p0); +- } +- if (self->private_impl.f_rle_length > 0u) { +- goto label__goto_suspend__break; +- } +- if (self->private_impl.f_rle_padded) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { +- goto label__goto_suspend__break; +- } +- iop_a_src += 1u; +- self->private_impl.f_rle_padded = false; +- } +- v_rle_state = 0u; +- goto label__middle__continue; +- } else if (v_rle_state == 4u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { +- goto label__goto_suspend__break; +- } +- self->private_impl.f_rle_delta_x = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- v_rle_state = 5u; +- continue; +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { +- goto label__goto_suspend__break; +- } +- v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- if (self->private_impl.f_rle_delta_x > 0u) { +- wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_dst, v_dst_palette, ((uint64_t)(self->private_impl.f_rle_delta_x))); +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(self->private_impl.f_rle_delta_x))); +- self->private_impl.f_rle_delta_x = 0u; +- if (self->private_impl.f_dst_x > self->private_impl.f_width) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression); +- goto exit; +- } +- } +- if (v_code > 0u) { +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_code -= 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- while (true) { +- self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; +- if (self->private_impl.f_dst_y >= self->private_impl.f_height) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression); +- goto exit; +- } +- v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) { +- v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row); +- } +- if (v_code <= 0u) { +- wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, ((uint64_t)(self->private_impl.f_dst_x))); +- break; +- } +- wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, 18446744073709551615u); +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_code -= 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } +- } +- v_rle_state = 0u; +- goto label__middle__continue; +- } +- } +- label__goto_suspend__break:; +- self->private_impl.f_rle_state = v_rle_state; +- status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); +- goto ok; +- } +- } +- label__outer__break:; +- while (self->private_impl.f_dst_y < self->private_impl.f_height) { +- v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) { +- v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row); +- } +- wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, 18446744073709551615u); +- self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; +- } +- status = wuffs_base__make_status(NULL); +- goto ok; ++ __m256i yy_all = _mm256_lddqu_si256((const __m256i*)(const void*)up0); ++ __m256i yy_eve = _mm256_and_si256(yy_all, u00FF); ++ __m256i yy_odd = _mm256_srli_epi16(yy_all, 8); + +- ok: +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++ __m256i loose_b_eve = _mm256_add_epi16(by_eve, yy_eve); ++ __m256i loose_b_odd = _mm256_add_epi16(by_odd, yy_odd); ++ __m256i packed_b_eve = _mm256_packus_epi16(loose_b_eve, loose_b_eve); ++ __m256i packed_b_odd = _mm256_packus_epi16(loose_b_odd, loose_b_odd); + +- return status; +-} ++ __m256i loose_g_eve = _mm256_add_epi16(gy_eve, yy_eve); ++ __m256i loose_g_odd = _mm256_add_epi16(gy_odd, yy_odd); ++ __m256i packed_g_eve = _mm256_packus_epi16(loose_g_eve, loose_g_eve); ++ __m256i packed_g_odd = _mm256_packus_epi16(loose_g_odd, loose_g_odd); + +-// -------- func bmp.decoder.swizzle_bitfields ++ __m256i loose_r_eve = _mm256_add_epi16(ry_eve, yy_eve); ++ __m256i loose_r_odd = _mm256_add_epi16(ry_odd, yy_odd); ++ __m256i packed_r_eve = _mm256_packus_epi16(loose_r_eve, loose_r_eve); ++ __m256i packed_r_odd = _mm256_packus_epi16(loose_r_odd, loose_r_odd); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__swizzle_bitfields( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ // § Note the swapped B and R channels. ++ __m256i mix00 = _mm256_unpacklo_epi8(packed_r_eve, packed_g_eve); ++ __m256i mix01 = _mm256_unpacklo_epi8(packed_r_odd, packed_g_odd); ++ __m256i mix02 = _mm256_unpacklo_epi8(packed_b_eve, uFFFF); ++ __m256i mix03 = _mm256_unpacklo_epi8(packed_b_odd, uFFFF); + +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint32_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_bytes_per_row = 0; +- wuffs_base__slice_u8 v_dst_palette = {0}; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint64_t v_i = 0; +- uint64_t v_n = 0; +- uint32_t v_p0 = 0; +- uint32_t v_p1 = 0; +- uint32_t v_p1_temp = 0; +- uint32_t v_num_bits = 0; +- uint32_t v_c = 0; +- uint32_t v_c32 = 0; +- uint32_t v_channel = 0; ++ __m256i mix10 = _mm256_unpacklo_epi16(mix00, mix02); ++ __m256i mix11 = _mm256_unpacklo_epi16(mix01, mix03); ++ __m256i mix12 = _mm256_unpackhi_epi16(mix00, mix02); ++ __m256i mix13 = _mm256_unpackhi_epi16(mix01, mix03); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ __m256i mix20 = _mm256_unpacklo_epi32(mix10, mix11); ++ __m256i mix21 = _mm256_unpackhi_epi32(mix10, mix11); ++ __m256i mix22 = _mm256_unpacklo_epi32(mix12, mix13); ++ __m256i mix23 = _mm256_unpackhi_epi32(mix12, mix13); + +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_option); +- goto exit; +- } +- v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); +- v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); +- v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- label__outer__continue:; +- while (true) { +- while (self->private_impl.f_pending_pad > 0u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); +- goto ok; +- } +- self->private_impl.f_pending_pad -= 1u; +- iop_a_src += 1u; +- } +- while (true) { +- if (self->private_impl.f_dst_x == self->private_impl.f_width) { +- self->private_impl.f_dst_x = 0u; +- self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; +- if (self->private_impl.f_dst_y >= self->private_impl.f_height) { +- if (self->private_impl.f_height > 0u) { +- self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row; +- } +- goto label__outer__break; +- } else if (self->private_impl.f_pad_per_row != 0u) { +- self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row; +- goto label__outer__continue; +- } +- } +- v_p1_temp = ((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x)); +- v_p1 = wuffs_base__u32__min(v_p1_temp, 256u); +- v_p0 = 0u; +- while (v_p0 < v_p1) { +- if (self->private_impl.f_bits_per_pixel == 16u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { +- break; +- } +- v_c32 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2u; +- } else { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { +- break; +- } +- v_c32 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4u; +- } +- v_channel = 0u; +- while (v_channel < 4u) { +- if (self->private_impl.f_channel_num_bits[v_channel] == 0u) { +- self->private_data.f_scratch[((8u * v_p0) + (2u * v_channel) + 0u)] = 255u; +- self->private_data.f_scratch[((8u * v_p0) + (2u * v_channel) + 1u)] = 255u; +- } else { +- v_c = ((v_c32 & self->private_impl.f_channel_masks[v_channel]) >> self->private_impl.f_channel_shifts[v_channel]); +- v_num_bits = ((uint32_t)(self->private_impl.f_channel_num_bits[v_channel])); +- while (v_num_bits < 16u) { +- v_c |= ((uint32_t)(v_c << v_num_bits)); +- v_num_bits *= 2u; +- } +- v_c >>= (v_num_bits - 16u); +- self->private_data.f_scratch[((8u * v_p0) + (2u * v_channel) + 0u)] = ((uint8_t)((v_c >> 0u))); +- self->private_data.f_scratch[((8u * v_p0) + (2u * v_channel) + 1u)] = ((uint8_t)((v_c >> 8u))); +- } +- v_channel += 1u; +- } +- v_p0 += 1u; +- } +- v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); +- } +- v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); +- if (v_i >= ((uint64_t)(v_dst.len))) { +- v_n = ((uint64_t)(v_p0)); +- } else { +- v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, (8u * v_p0))); +- } +- if (v_n == 0u) { +- status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); +- goto ok; +- } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); +- } +- } +- label__outer__break:; +- status = wuffs_base__make_status(NULL); +- goto ok; ++ __m256i mix30 = _mm256_permute2x128_si256(mix20, mix21, 0x20); ++ __m256i mix31 = _mm256_permute2x128_si256(mix22, mix23, 0x20); ++ __m256i mix32 = _mm256_permute2x128_si256(mix20, mix21, 0x31); ++ __m256i mix33 = _mm256_permute2x128_si256(mix22, mix23, 0x31); + +- ok: +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++ _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x00), mix30); ++ _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x20), mix31); ++ _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x40), mix32); ++ _mm256_storeu_si256((__m256i*)(void*)(dst_iter + 0x60), mix33); + +- return status; ++ uint32_t n = 32u - (31u & (x - x_end)); ++ dst_iter += 4u * n; ++ up0 += n; ++ up1 += n; ++ up2 += n; ++ x += n; ++ } + } + +-// -------- func bmp.decoder.swizzle_low_bit_depth ++#if defined(__GNUC__) && !defined(__clang__) ++// No-op. ++#else ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") ++static const uint8_t* // ++wuffs_private_impl__swizzle_ycc__upsample_inv_h2v2_triangle_x86_avx2( ++ uint8_t* dst_ptr, ++ const uint8_t* src_ptr_major, ++ const uint8_t* src_ptr_minor, ++ size_t src_len, ++ uint32_t h1v2_bias_ignored, ++ bool first_column, ++ bool last_column) { ++ uint8_t* dp = dst_ptr; ++ const uint8_t* sp_major = src_ptr_major; ++ const uint8_t* sp_minor = src_ptr_minor; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__swizzle_low_bit_depth( +- wuffs_bmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ if (first_column) { ++ src_len--; ++ if ((src_len <= 0u) && last_column) { ++ uint32_t sv = (12u * ((uint32_t)(*sp_major++))) + // ++ (4u * ((uint32_t)(*sp_minor++))); ++ *dp++ = (uint8_t)((sv + 8u) >> 4u); ++ *dp++ = (uint8_t)((sv + 7u) >> 4u); ++ return dst_ptr; ++ } + +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint32_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_bytes_per_row = 0; +- wuffs_base__slice_u8 v_dst_palette = {0}; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint64_t v_i = 0; +- uint64_t v_n = 0; +- uint32_t v_p0 = 0; +- uint32_t v_chunk_bits = 0; +- uint32_t v_chunk_count = 0; +- uint32_t v_pixels_per_chunk = 0; ++ uint32_t sv_major_m1 = sp_major[-0]; // Clamp offset to zero. ++ uint32_t sv_minor_m1 = sp_minor[-0]; // Clamp offset to zero. ++ uint32_t sv_major_p1 = sp_major[+1]; ++ uint32_t sv_minor_p1 = sp_minor[+1]; + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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 sv = (9u * ((uint32_t)(*sp_major++))) + // ++ (3u * ((uint32_t)(*sp_minor++))); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); ++ if (src_len <= 0u) { ++ return dst_ptr; ++ } + } + +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_option); +- goto exit; +- } +- v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); +- v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); +- v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- while (true) { +- if (self->private_impl.f_dst_x == self->private_impl.f_width) { +- self->private_impl.f_dst_x = 0u; +- self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; +- if (self->private_impl.f_dst_y >= self->private_impl.f_height) { +- break; +- } +- } +- v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); +- } +- v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); +- if (v_i >= ((uint64_t)(v_dst.len))) { +- if (self->private_impl.f_bits_per_pixel == 1u) { +- v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 31u) / 32u); +- v_pixels_per_chunk = 32u; +- } else if (self->private_impl.f_bits_per_pixel == 2u) { +- v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 15u) / 16u); +- v_pixels_per_chunk = 16u; +- } else { +- v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 7u) / 8u); +- v_pixels_per_chunk = 8u; +- } +- while ((v_chunk_count >= 64u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 256u)) { +- iop_a_src += 256u; +- self->private_impl.f_dst_x = wuffs_base__u32__min(self->private_impl.f_width, ((uint32_t)(self->private_impl.f_dst_x + (v_pixels_per_chunk * 64u)))); +- v_chunk_count -= 64u; +- } +- while ((v_chunk_count >= 8u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 32u)) { +- iop_a_src += 32u; +- self->private_impl.f_dst_x = wuffs_base__u32__min(self->private_impl.f_width, ((uint32_t)(self->private_impl.f_dst_x + (v_pixels_per_chunk * 8u)))); +- v_chunk_count -= 8u; +- } +- while (v_chunk_count > 0u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { +- status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); +- goto ok; +- } +- iop_a_src += 4u; +- self->private_impl.f_dst_x = wuffs_base__u32__min(self->private_impl.f_width, ((uint32_t)(self->private_impl.f_dst_x + (v_pixels_per_chunk * 1u)))); +- v_chunk_count -= 1u; +- } +- continue; +- } +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i); +- v_p0 = 0u; +- if (self->private_impl.f_bits_per_pixel == 1u) { +- v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 31u) / 32u); +- v_chunk_count = wuffs_base__u32__min(v_chunk_count, 16u); +- while ((v_chunk_count > 0u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4u)) { +- v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4u; +- self->private_data.f_scratch[(v_p0 + 0u)] = ((uint8_t)((1u & (v_chunk_bits >> 31u)))); +- self->private_data.f_scratch[(v_p0 + 1u)] = ((uint8_t)((1u & (v_chunk_bits >> 30u)))); +- self->private_data.f_scratch[(v_p0 + 2u)] = ((uint8_t)((1u & (v_chunk_bits >> 29u)))); +- self->private_data.f_scratch[(v_p0 + 3u)] = ((uint8_t)((1u & (v_chunk_bits >> 28u)))); +- self->private_data.f_scratch[(v_p0 + 4u)] = ((uint8_t)((1u & (v_chunk_bits >> 27u)))); +- self->private_data.f_scratch[(v_p0 + 5u)] = ((uint8_t)((1u & (v_chunk_bits >> 26u)))); +- self->private_data.f_scratch[(v_p0 + 6u)] = ((uint8_t)((1u & (v_chunk_bits >> 25u)))); +- self->private_data.f_scratch[(v_p0 + 7u)] = ((uint8_t)((1u & (v_chunk_bits >> 24u)))); +- self->private_data.f_scratch[(v_p0 + 8u)] = ((uint8_t)((1u & (v_chunk_bits >> 23u)))); +- self->private_data.f_scratch[(v_p0 + 9u)] = ((uint8_t)((1u & (v_chunk_bits >> 22u)))); +- self->private_data.f_scratch[(v_p0 + 10u)] = ((uint8_t)((1u & (v_chunk_bits >> 21u)))); +- self->private_data.f_scratch[(v_p0 + 11u)] = ((uint8_t)((1u & (v_chunk_bits >> 20u)))); +- self->private_data.f_scratch[(v_p0 + 12u)] = ((uint8_t)((1u & (v_chunk_bits >> 19u)))); +- self->private_data.f_scratch[(v_p0 + 13u)] = ((uint8_t)((1u & (v_chunk_bits >> 18u)))); +- self->private_data.f_scratch[(v_p0 + 14u)] = ((uint8_t)((1u & (v_chunk_bits >> 17u)))); +- self->private_data.f_scratch[(v_p0 + 15u)] = ((uint8_t)((1u & (v_chunk_bits >> 16u)))); +- self->private_data.f_scratch[(v_p0 + 16u)] = ((uint8_t)((1u & (v_chunk_bits >> 15u)))); +- self->private_data.f_scratch[(v_p0 + 17u)] = ((uint8_t)((1u & (v_chunk_bits >> 14u)))); +- self->private_data.f_scratch[(v_p0 + 18u)] = ((uint8_t)((1u & (v_chunk_bits >> 13u)))); +- self->private_data.f_scratch[(v_p0 + 19u)] = ((uint8_t)((1u & (v_chunk_bits >> 12u)))); +- self->private_data.f_scratch[(v_p0 + 20u)] = ((uint8_t)((1u & (v_chunk_bits >> 11u)))); +- self->private_data.f_scratch[(v_p0 + 21u)] = ((uint8_t)((1u & (v_chunk_bits >> 10u)))); +- self->private_data.f_scratch[(v_p0 + 22u)] = ((uint8_t)((1u & (v_chunk_bits >> 9u)))); +- self->private_data.f_scratch[(v_p0 + 23u)] = ((uint8_t)((1u & (v_chunk_bits >> 8u)))); +- self->private_data.f_scratch[(v_p0 + 24u)] = ((uint8_t)((1u & (v_chunk_bits >> 7u)))); +- self->private_data.f_scratch[(v_p0 + 25u)] = ((uint8_t)((1u & (v_chunk_bits >> 6u)))); +- self->private_data.f_scratch[(v_p0 + 26u)] = ((uint8_t)((1u & (v_chunk_bits >> 5u)))); +- self->private_data.f_scratch[(v_p0 + 27u)] = ((uint8_t)((1u & (v_chunk_bits >> 4u)))); +- self->private_data.f_scratch[(v_p0 + 28u)] = ((uint8_t)((1u & (v_chunk_bits >> 3u)))); +- self->private_data.f_scratch[(v_p0 + 29u)] = ((uint8_t)((1u & (v_chunk_bits >> 2u)))); +- self->private_data.f_scratch[(v_p0 + 30u)] = ((uint8_t)((1u & (v_chunk_bits >> 1u)))); +- self->private_data.f_scratch[(v_p0 + 31u)] = ((uint8_t)((1u & (v_chunk_bits >> 0u)))); +- v_p0 = ((v_p0 & 511u) + 32u); +- v_chunk_count -= 1u; +- } +- } else if (self->private_impl.f_bits_per_pixel == 2u) { +- v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 15u) / 16u); +- v_chunk_count = wuffs_base__u32__min(v_chunk_count, 32u); +- while ((v_chunk_count > 0u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4u)) { +- v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4u; +- self->private_data.f_scratch[(v_p0 + 0u)] = ((uint8_t)((3u & (v_chunk_bits >> 30u)))); +- self->private_data.f_scratch[(v_p0 + 1u)] = ((uint8_t)((3u & (v_chunk_bits >> 28u)))); +- self->private_data.f_scratch[(v_p0 + 2u)] = ((uint8_t)((3u & (v_chunk_bits >> 26u)))); +- self->private_data.f_scratch[(v_p0 + 3u)] = ((uint8_t)((3u & (v_chunk_bits >> 24u)))); +- self->private_data.f_scratch[(v_p0 + 4u)] = ((uint8_t)((3u & (v_chunk_bits >> 22u)))); +- self->private_data.f_scratch[(v_p0 + 5u)] = ((uint8_t)((3u & (v_chunk_bits >> 20u)))); +- self->private_data.f_scratch[(v_p0 + 6u)] = ((uint8_t)((3u & (v_chunk_bits >> 18u)))); +- self->private_data.f_scratch[(v_p0 + 7u)] = ((uint8_t)((3u & (v_chunk_bits >> 16u)))); +- self->private_data.f_scratch[(v_p0 + 8u)] = ((uint8_t)((3u & (v_chunk_bits >> 14u)))); +- self->private_data.f_scratch[(v_p0 + 9u)] = ((uint8_t)((3u & (v_chunk_bits >> 12u)))); +- self->private_data.f_scratch[(v_p0 + 10u)] = ((uint8_t)((3u & (v_chunk_bits >> 10u)))); +- self->private_data.f_scratch[(v_p0 + 11u)] = ((uint8_t)((3u & (v_chunk_bits >> 8u)))); +- self->private_data.f_scratch[(v_p0 + 12u)] = ((uint8_t)((3u & (v_chunk_bits >> 6u)))); +- self->private_data.f_scratch[(v_p0 + 13u)] = ((uint8_t)((3u & (v_chunk_bits >> 4u)))); +- self->private_data.f_scratch[(v_p0 + 14u)] = ((uint8_t)((3u & (v_chunk_bits >> 2u)))); +- self->private_data.f_scratch[(v_p0 + 15u)] = ((uint8_t)((3u & (v_chunk_bits >> 0u)))); +- v_p0 = ((v_p0 & 511u) + 16u); +- v_chunk_count -= 1u; +- } +- } else { +- v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 7u) / 8u); +- v_chunk_count = wuffs_base__u32__min(v_chunk_count, 64u); +- while ((v_chunk_count > 0u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4u)) { +- v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4u; +- self->private_data.f_scratch[(v_p0 + 0u)] = ((uint8_t)((15u & (v_chunk_bits >> 28u)))); +- self->private_data.f_scratch[(v_p0 + 1u)] = ((uint8_t)((15u & (v_chunk_bits >> 24u)))); +- self->private_data.f_scratch[(v_p0 + 2u)] = ((uint8_t)((15u & (v_chunk_bits >> 20u)))); +- self->private_data.f_scratch[(v_p0 + 3u)] = ((uint8_t)((15u & (v_chunk_bits >> 16u)))); +- self->private_data.f_scratch[(v_p0 + 4u)] = ((uint8_t)((15u & (v_chunk_bits >> 12u)))); +- self->private_data.f_scratch[(v_p0 + 5u)] = ((uint8_t)((15u & (v_chunk_bits >> 8u)))); +- self->private_data.f_scratch[(v_p0 + 6u)] = ((uint8_t)((15u & (v_chunk_bits >> 4u)))); +- self->private_data.f_scratch[(v_p0 + 7u)] = ((uint8_t)((15u & (v_chunk_bits >> 0u)))); +- v_p0 = ((v_p0 & 511u) + 8u); +- v_chunk_count -= 1u; +- } +- } +- v_p0 = wuffs_base__u32__min(v_p0, wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x)); +- v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, v_p0)); +- if (v_n == 0u) { +- status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); +- goto ok; +- } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); +- } +- status = wuffs_base__make_status(NULL); +- goto ok; +- +- ok: +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func bmp.decoder.frame_dirty_rect +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_bmp__decoder__frame_dirty_rect( +- const wuffs_bmp__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_rect_ie_u32(); ++ if (last_column) { ++ src_len--; + } + +- return wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height); +-} ++ if (src_len < 32) { ++ // This fallback is the same as the non-SIMD-capable code path. ++ for (; src_len > 0u; src_len--) { ++ uint32_t sv_major_m1 = sp_major[-1]; ++ uint32_t sv_minor_m1 = sp_minor[-1]; ++ uint32_t sv_major_p1 = sp_major[+1]; ++ uint32_t sv_minor_p1 = sp_minor[+1]; + +-// -------- func bmp.decoder.num_animation_loops ++ uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // ++ (3u * ((uint32_t)(*sp_minor++))); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_bmp__decoder__num_animation_loops( +- const wuffs_bmp__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ } else { ++ while (src_len > 0u) { ++ // Load 1+32+1 samples (six u8x32 vectors) from the major (jxx) and minor ++ // (nxx) rows. ++ // ++ // major_p0 = [j00 j01 j02 j03 .. j28 j29 j30 j31] // p0 = "plus 0" ++ // minor_p0 = [n00 n01 n02 n03 .. n28 n29 n30 n31] // p0 = "plus 0" ++ // major_m1 = [jm1 j00 j01 j02 .. j27 j28 j29 j30] // m1 = "minus 1" ++ // minor_m1 = [nm1 n00 n01 n02 .. n27 n28 n29 n30] // m1 = "minus 1" ++ // major_p1 = [j01 j02 j03 j04 .. j29 j30 j31 j32] // p1 = "plus 1" ++ // minor_p1 = [n01 n02 n03 n04 .. n29 n30 n31 n32] // p1 = "plus 1" ++ __m256i major_p0 = ++ _mm256_lddqu_si256((const __m256i*)(const void*)(sp_major + 0)); ++ __m256i minor_p0 = ++ _mm256_lddqu_si256((const __m256i*)(const void*)(sp_minor + 0)); ++ __m256i major_m1 = ++ _mm256_lddqu_si256((const __m256i*)(const void*)(sp_major - 1)); ++ __m256i minor_m1 = ++ _mm256_lddqu_si256((const __m256i*)(const void*)(sp_minor - 1)); ++ __m256i major_p1 = ++ _mm256_lddqu_si256((const __m256i*)(const void*)(sp_major + 1)); ++ __m256i minor_p1 = ++ _mm256_lddqu_si256((const __m256i*)(const void*)(sp_minor + 1)); + +- return 0u; +-} ++ // Unpack, staying with u8x32 vectors. ++ // ++ // step1_p0_lo = [j00 n00 j01 n01 .. j07 n07 j16 n16 j17 n17 .. j23 n23] ++ // step1_p0_hi = [j08 n08 j09 n09 .. j15 n15 j24 n24 j25 n25 .. j31 n31] ++ // step1_m1_lo = [jm1 nm1 j00 n00 .. j06 n06 j15 n15 j16 n16 .. j22 n22] ++ // step1_m1_hi = [j07 n07 j08 n08 .. j14 n14 j23 n23 j24 n24 .. j30 n30] ++ // step1_p1_lo = [j01 n01 j02 n02 .. j08 n08 j17 n17 j18 n18 .. j24 n24] ++ // step1_p1_hi = [j09 n09 j10 n10 .. j16 n16 j25 n25 j26 n26 .. j32 n32] ++ __m256i step1_p0_lo = _mm256_unpacklo_epi8(major_p0, minor_p0); ++ __m256i step1_p0_hi = _mm256_unpackhi_epi8(major_p0, minor_p0); ++ __m256i step1_m1_lo = _mm256_unpacklo_epi8(major_m1, minor_m1); ++ __m256i step1_m1_hi = _mm256_unpackhi_epi8(major_m1, minor_m1); ++ __m256i step1_p1_lo = _mm256_unpacklo_epi8(major_p1, minor_p1); ++ __m256i step1_p1_hi = _mm256_unpackhi_epi8(major_p1, minor_p1); + +-// -------- func bmp.decoder.num_decoded_frame_configs ++ // Multiply-add to get u16x16 vectors. ++ // ++ // step2_p0_lo = [9*j00+3*n00 9*j01+3*n01 .. 9*j23+3*n23] ++ // step2_p0_hi = [9*j08+3*n08 9*j09+3*n09 .. 9*j31+3*n31] ++ // step2_m1_lo = [3*jm1+1*nm1 3*j00+1*n00 .. 3*j22+1*n22] ++ // step2_m1_hi = [3*j07+1*n07 3*j08+1*n08 .. 3*j30+1*n30] ++ // step2_p1_lo = [3*j01+1*n01 3*j02+1*n02 .. 3*j24+1*n24] ++ // step2_p1_hi = [3*j09+1*n09 3*j10+1*n10 .. 3*j32+1*n32] ++ const __m256i k0309 = _mm256_set1_epi16(0x0309); ++ const __m256i k0103 = _mm256_set1_epi16(0x0103); ++ __m256i step2_p0_lo = _mm256_maddubs_epi16(step1_p0_lo, k0309); ++ __m256i step2_p0_hi = _mm256_maddubs_epi16(step1_p0_hi, k0309); ++ __m256i step2_m1_lo = _mm256_maddubs_epi16(step1_m1_lo, k0103); ++ __m256i step2_m1_hi = _mm256_maddubs_epi16(step1_m1_hi, k0103); ++ __m256i step2_p1_lo = _mm256_maddubs_epi16(step1_p1_lo, k0103); ++ __m256i step2_p1_hi = _mm256_maddubs_epi16(step1_p1_hi, k0103); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_bmp__decoder__num_decoded_frame_configs( +- const wuffs_bmp__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ // Compute the weighted sums of (p0, m1) and (p0, p1). For example: ++ // ++ // step3_m1_lo[00] = ((9*j00) + (3*n00) + (3*jm1) + (1*nm1)) as u16 ++ // step3_p1_hi[15] = ((9*j31) + (3*n31) + (3*j32) + (1*n32)) as u16 ++ __m256i step3_m1_lo = _mm256_add_epi16(step2_p0_lo, step2_m1_lo); ++ __m256i step3_m1_hi = _mm256_add_epi16(step2_p0_hi, step2_m1_hi); ++ __m256i step3_p1_lo = _mm256_add_epi16(step2_p0_lo, step2_p1_lo); ++ __m256i step3_p1_hi = _mm256_add_epi16(step2_p0_hi, step2_p1_hi); + +- if (self->private_impl.f_call_sequence > 32u) { +- return 1u; +- } +- return 0u; +-} ++ // Bias by 8 (on the left) or 7 (on the right) and then divide by 16 ++ // (which is 9+3+3+1) to get a weighted average. On the left (m1), shift ++ // the u16 right value by 4. On the right (p1), shift right by 4 and then ++ // shift left by 8 so that, when still in the u16x16 little-endian ++ // interpretation, we have: ++ // - m1_element = (etcetera + 8) >> 4 ++ // - p1_element = ((etcetera + 7) >> 4) << 8 ++ // ++ // step4_m1_lo = [0x00?? 0x00?? ... 0x00?? 0x00??] ++ // step4_p1_lo = [0x??00 0x??00 ... 0x??00 0x??00] ++ // step4_m1_hi = [0x00?? 0x00?? ... 0x00?? 0x00??] ++ // step4_p1_hi = [0x??00 0x??00 ... 0x??00 0x??00] ++ __m256i step4_m1_lo = _mm256_srli_epi16( ++ _mm256_add_epi16(step3_m1_lo, _mm256_set1_epi16(8)), 4); ++ __m256i step4_p1_lo = _mm256_slli_epi16( ++ _mm256_srli_epi16(_mm256_add_epi16(step3_p1_lo, _mm256_set1_epi16(7)), ++ 4), ++ 8); ++ __m256i step4_m1_hi = _mm256_srli_epi16( ++ _mm256_add_epi16(step3_m1_hi, _mm256_set1_epi16(8)), 4); ++ __m256i step4_p1_hi = _mm256_slli_epi16( ++ _mm256_srli_epi16(_mm256_add_epi16(step3_p1_hi, _mm256_set1_epi16(7)), ++ 4), ++ 8); + +-// -------- func bmp.decoder.num_decoded_frames ++ // Bitwise-or two "0x00"-rich u16x16 vectors to get a u8x32 vector. Do ++ // that twice. Once for the low columns and once for the high columns. ++ // ++ // In terms of jxx (major row) or nxx (minor row) source samples: ++ // - low columns means ( 0 .. 8; 16 .. 24). ++ // - high columns means ( 8 .. 16; 24 .. 32). ++ // ++ // In terms of dxx destination samples (there are twice as many): ++ // - low columns means ( 0 .. 16; 32 .. 48). ++ // - high columns means (16 .. 32; 48 .. 64). ++ // ++ // step5_lo = [d00 d01 .. d14 d15 d32 d33 .. d46 d47] ++ // step5_hi = [d16 d17 .. d30 d31 d48 d49 .. d62 d63] ++ // ++ // The d00, d02 ... d62 even elements come from (p0, m1) weighted sums. ++ // The d01, d03 ... d63 odd elements come from (p0, p1) weighted sums. ++ __m256i step5_lo = _mm256_or_si256(step4_m1_lo, step4_p1_lo); ++ __m256i step5_hi = _mm256_or_si256(step4_m1_hi, step4_p1_hi); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_bmp__decoder__num_decoded_frames( +- const wuffs_bmp__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ // Permute and store. ++ // ++ // step6_00_31 = [d00 d01 .. d14 d15 d16 d17 .. d30 d31] ++ // step6_32_63 = [d32 d33 .. d46 d47 d48 d49 .. d62 d63] ++ __m256i step6_00_31 = _mm256_permute2x128_si256(step5_lo, step5_hi, 0x20); ++ __m256i step6_32_63 = _mm256_permute2x128_si256(step5_lo, step5_hi, 0x31); ++ _mm256_storeu_si256((__m256i*)(void*)(dp + 0x00), step6_00_31); ++ _mm256_storeu_si256((__m256i*)(void*)(dp + 0x20), step6_32_63); + +- if (self->private_impl.f_call_sequence > 64u) { +- return 1u; ++ // Advance by up to 32 source samples (64 destination samples). The first ++ // iteration might be smaller than 32 so that all of the remaining steps ++ // are exactly 32. ++ size_t n = 32u - (31u & (0u - src_len)); ++ dp += 2u * n; ++ sp_major += n; ++ sp_minor += n; ++ src_len -= n; ++ } + } +- return 0u; +-} + +-// -------- func bmp.decoder.restart_frame ++ if (last_column) { ++ uint32_t sv_major_m1 = sp_major[-1]; ++ uint32_t sv_minor_m1 = sp_minor[-1]; ++ uint32_t sv_major_p1 = sp_major[+0]; // Clamp offset to zero. ++ uint32_t sv_minor_p1 = sp_minor[+0]; // Clamp offset to zero. + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_bmp__decoder__restart_frame( +- wuffs_bmp__decoder* self, +- uint64_t a_index, +- uint64_t a_io_position) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ uint32_t sv = (9u * ((uint32_t)(*sp_major++))) + // ++ (3u * ((uint32_t)(*sp_minor++))); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_m1) + (sv_minor_m1) + 8u) >> 4u); ++ *dp++ = (uint8_t)((sv + (3u * sv_major_p1) + (sv_minor_p1) + 7u) >> 4u); + } + +- if (self->private_impl.f_call_sequence < 32u) { +- return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- } +- if (a_index != 0u) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- self->private_impl.f_call_sequence = 40u; +- self->private_impl.f_frame_config_io_position = a_io_position; +- return wuffs_base__make_status(NULL); ++ return dst_ptr; + } ++#endif ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++// ‼ WUFFS MULTI-FILE SECTION -x86_avx2 + +-// -------- func bmp.decoder.set_report_metadata +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_bmp__decoder__set_report_metadata( +- wuffs_bmp__decoder* self, +- uint32_t a_fourcc, +- bool a_report) { +- return wuffs_base__make_empty_struct(); +-} ++#endif // !defined(WUFFS_CONFIG__MODULES) || ++ // defined(WUFFS_CONFIG__MODULE__BASE) || ++ // defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV) + +-// -------- func bmp.decoder.tell_me_more ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \ ++ defined(WUFFS_CONFIG__MODULE__BASE__UTF8) + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_bmp__decoder__tell_me_more( +- wuffs_bmp__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 4)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); ++// ---------------- Unicode and UTF-8 + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++WUFFS_BASE__MAYBE_STATIC size_t // ++wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point) { ++ if (code_point <= 0x7F) { ++ if (dst.len >= 1) { ++ dst.ptr[0] = (uint8_t)(code_point); ++ return 1; ++ } + +- uint32_t coro_susp_point = self->private_impl.p_tell_me_more[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ } else if (code_point <= 0x07FF) { ++ if (dst.len >= 2) { ++ dst.ptr[0] = (uint8_t)(0xC0 | ((code_point >> 6))); ++ dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); ++ return 2; ++ } + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_bmp__decoder__do_tell_me_more(self, a_dst, a_minfo, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_bmp__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } else if (code_point <= 0xFFFF) { ++ if ((dst.len >= 3) && ((code_point < 0xD800) || (0xDFFF < code_point))) { ++ dst.ptr[0] = (uint8_t)(0xE0 | ((code_point >> 12))); ++ dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F)); ++ dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); ++ return 3; + } + +- ok: +- self->private_impl.p_tell_me_more[0] = 0; +- goto exit; ++ } else if (code_point <= 0x10FFFF) { ++ if (dst.len >= 4) { ++ dst.ptr[0] = (uint8_t)(0xF0 | ((code_point >> 18))); ++ dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 12) & 0x3F)); ++ dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F)); ++ dst.ptr[3] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); ++ return 4; ++ } + } + +- goto suspend; +- suspend: +- self->private_impl.p_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0; +- +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; ++ return 0; + } + +-// -------- func bmp.decoder.do_tell_me_more +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__do_tell_me_more( +- wuffs_bmp__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++// wuffs_base__utf_8__byte_length_minus_1 is the byte length (minus 1) of a ++// UTF-8 encoded code point, based on the encoding's initial byte. ++// - 0x00 is 1-byte UTF-8 (ASCII). ++// - 0x01 is the start of 2-byte UTF-8. ++// - 0x02 is the start of 3-byte UTF-8. ++// - 0x03 is the start of 4-byte UTF-8. ++// - 0x40 is a UTF-8 tail byte. ++// - 0x80 is invalid UTF-8. ++// ++// RFC 3629 (UTF-8) gives this grammar for valid UTF-8: ++// UTF8-1 = %x00-7F ++// UTF8-2 = %xC2-DF UTF8-tail ++// UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) / ++// %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail ) ++// UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) / ++// %xF4 %x80-8F 2( UTF8-tail ) ++// UTF8-tail = %x80-BF ++static const uint8_t wuffs_base__utf_8__byte_length_minus_1[256] = { ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 ..= 0x37. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. + +- if (self->private_impl.f_io_redirect_fourcc <= 1u) { +- status = wuffs_base__make_status(wuffs_base__error__no_more_information); +- goto exit; +- } +- if (a_minfo != NULL) { +- wuffs_base__more_information__set(a_minfo, +- 1u, +- self->private_impl.f_io_redirect_fourcc, +- 0u, +- self->private_impl.f_io_redirect_pos, +- 18446744073709551615u); +- } +- self->private_impl.f_io_redirect_fourcc = 1u; ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 ..= 0x47. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 ..= 0x67. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77. ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F. + +- goto ok; +- ok: +- goto exit; +- exit: +- return status; +-} ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x80 ..= 0x87. ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x88 ..= 0x8F. ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x90 ..= 0x97. ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x98 ..= 0x9F. ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xA0 ..= 0xA7. ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xA8 ..= 0xAF. ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xB0 ..= 0xB7. ++ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xB8 ..= 0xBF. + +-// -------- func bmp.decoder.history_retain_length ++ 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xC0 ..= 0xC7. ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xC8 ..= 0xCF. ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xD0 ..= 0xD7. ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xD8 ..= 0xDF. ++ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xE0 ..= 0xE7. ++ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xE8 ..= 0xEF. ++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7. ++ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF. ++ // 0 1 2 3 4 5 6 7 ++ // 8 9 A B C D E F ++}; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_bmp__decoder__history_retain_length( +- const wuffs_bmp__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output // ++wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len) { ++ if (s_len == 0) { ++ return wuffs_base__make_utf_8__next__output(0, 0); + } ++ uint32_t c = s_ptr[0]; ++ switch (wuffs_base__utf_8__byte_length_minus_1[c & 0xFF]) { ++ case 0: ++ return wuffs_base__make_utf_8__next__output(c, 1); + +- return 0u; +-} ++ case 1: ++ if (s_len < 2) { ++ break; ++ } ++ c = wuffs_base__peek_u16le__no_bounds_check(s_ptr); ++ if ((c & 0xC000) != 0x8000) { ++ break; ++ } ++ c = (0x0007C0 & (c << 6)) | (0x00003F & (c >> 8)); ++ return wuffs_base__make_utf_8__next__output(c, 2); + +-// -------- func bmp.decoder.workbuf_len ++ case 2: ++ if (s_len < 3) { ++ break; ++ } ++ c = wuffs_base__peek_u24le__no_bounds_check(s_ptr); ++ if ((c & 0xC0C000) != 0x808000) { ++ break; ++ } ++ c = (0x00F000 & (c << 12)) | (0x000FC0 & (c >> 2)) | ++ (0x00003F & (c >> 16)); ++ if ((c <= 0x07FF) || ((0xD800 <= c) && (c <= 0xDFFF))) { ++ break; ++ } ++ return wuffs_base__make_utf_8__next__output(c, 3); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_bmp__decoder__workbuf_len( +- const wuffs_bmp__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ case 3: ++ if (s_len < 4) { ++ break; ++ } ++ c = wuffs_base__peek_u32le__no_bounds_check(s_ptr); ++ if ((c & 0xC0C0C000) != 0x80808000) { ++ break; ++ } ++ c = (0x1C0000 & (c << 18)) | (0x03F000 & (c << 4)) | ++ (0x000FC0 & (c >> 10)) | (0x00003F & (c >> 24)); ++ if ((c <= 0xFFFF) || (0x110000 <= c)) { ++ break; ++ } ++ return wuffs_base__make_utf_8__next__output(c, 4); + } + +- return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++ return wuffs_base__make_utf_8__next__output( ++ WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1); + } + +-// -------- func bmp.decoder.read_palette +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__read_palette( +- wuffs_bmp__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_i = 0; +- uint32_t v_argb = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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_read_palette[0]; +- if (coro_susp_point) { +- v_i = self->private_data.s_read_palette[0].v_i; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output // ++wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len) { ++ if (s_len == 0) { ++ return wuffs_base__make_utf_8__next__output(0, 0); + } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ const uint8_t* ptr = &s_ptr[s_len - 1]; ++ if (*ptr < 0x80) { ++ return wuffs_base__make_utf_8__next__output(*ptr, 1); + +- if (self->private_impl.f_bitmap_info_len == 12u) { +- while ((v_i < 256u) && (self->private_impl.f_padding >= 3u)) { +- self->private_impl.f_padding -= 3u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { +- t_0 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); +- iop_a_src += 3; +- } else { +- self->private_data.s_read_palette[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_read_palette[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; +- if (num_bits_0 == 16) { +- t_0 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)) << 56; +- } +- } +- v_argb = t_0; +- } +- v_argb |= 4278190080u; +- self->private_data.f_src_palette[((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); +- self->private_data.f_src_palette[((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); +- self->private_data.f_src_palette[((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); +- self->private_data.f_src_palette[((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); +- v_i += 1u; ++ } else if (*ptr < 0xC0) { ++ const uint8_t* too_far = &s_ptr[(s_len > 4) ? (s_len - 4) : 0]; ++ uint32_t n = 1; ++ while (ptr != too_far) { ++ ptr--; ++ n++; ++ if (*ptr < 0x80) { ++ break; ++ } else if (*ptr < 0xC0) { ++ continue; + } +- } else { +- while ((v_i < 256u) && (self->private_impl.f_padding >= 4u)) { +- self->private_impl.f_padding -= 4u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_read_palette[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_read_palette[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; +- if (num_bits_1 == 24) { +- t_1 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)) << 56; +- } +- } +- v_argb = t_1; +- } +- v_argb |= 4278190080u; +- self->private_data.f_src_palette[((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); +- self->private_data.f_src_palette[((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); +- self->private_data.f_src_palette[((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); +- self->private_data.f_src_palette[((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); +- v_i += 1u; ++ wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(ptr, n); ++ if (o.byte_length != n) { ++ break; + } ++ return o; + } +- while (v_i < 256u) { +- self->private_data.f_src_palette[((4u * v_i) + 0u)] = 0u; +- self->private_data.f_src_palette[((4u * v_i) + 1u)] = 0u; +- self->private_data.f_src_palette[((4u * v_i) + 2u)] = 0u; +- self->private_data.f_src_palette[((4u * v_i) + 3u)] = 255u; +- v_i += 1u; +- } +- +- goto ok; +- ok: +- self->private_impl.p_read_palette[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_read_palette[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_read_palette[0].v_i = v_i; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- return status; ++ return wuffs_base__make_utf_8__next__output( ++ WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1); + } + +-// -------- func bmp.decoder.process_masks +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bmp__decoder__process_masks( +- wuffs_bmp__decoder* self) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_i = 0; +- uint32_t v_mask = 0; +- uint32_t v_n = 0; +- +- while (v_i < 4u) { +- v_mask = self->private_impl.f_channel_masks[v_i]; +- if (v_mask != 0u) { +- v_n = 0u; +- while ((v_mask & 1u) == 0u) { +- v_n += 1u; +- v_mask >>= 1u; +- } +- self->private_impl.f_channel_shifts[v_i] = ((uint8_t)((v_n & 31u))); +- v_n = 0u; +- while ((v_mask & 1u) == 1u) { +- v_n += 1u; +- v_mask >>= 1u; +- } +- if ((v_mask != 0u) || (v_n > 32u)) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; +- } +- self->private_impl.f_channel_num_bits[v_i] = ((uint8_t)(v_n)); +- } else if (v_i != 3u) { +- status = wuffs_base__make_status(wuffs_bmp__error__bad_header); +- goto exit; ++WUFFS_BASE__MAYBE_STATIC size_t // ++wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) { ++ // TODO: possibly optimize the all-ASCII case (4 or 8 bytes at a time). ++ // ++ // TODO: possibly optimize this by manually inlining the ++ // wuffs_base__utf_8__next calls. ++ size_t original_len = s_len; ++ while (s_len > 0) { ++ wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(s_ptr, s_len); ++ if ((o.code_point > 0x7F) && (o.byte_length == 1)) { ++ break; + } +- v_i += 1u; ++ s_ptr += o.byte_length; ++ s_len -= o.byte_length; + } ++ return original_len - s_len; ++} + +- goto ok; +- ok: +- goto exit; +- exit: +- return status; ++WUFFS_BASE__MAYBE_STATIC size_t // ++wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) { ++ // TODO: possibly optimize this by checking 4 or 8 bytes at a time. ++ const uint8_t* original_ptr = s_ptr; ++ const uint8_t* p = s_ptr; ++ const uint8_t* q = s_ptr + s_len; ++ for (; (p != q) && ((*p & 0x80) == 0); p++) { ++ } ++ return (size_t)(p - original_ptr); + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP) ++#endif // !defined(WUFFS_CONFIG__MODULES) || ++ // defined(WUFFS_CONFIG__MODULE__BASE) || ++ // defined(WUFFS_CONFIG__MODULE__BASE__UTF8) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BZIP2) ++#ifdef __cplusplus ++} // extern "C" ++#endif + +-// ---------------- Status Codes Implementations ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32) + +-const char wuffs_bzip2__error__bad_huffman_code_over_subscribed[] = "#bzip2: bad Huffman code (over-subscribed)"; +-const char wuffs_bzip2__error__bad_huffman_code_under_subscribed[] = "#bzip2: bad Huffman code (under-subscribed)"; +-const char wuffs_bzip2__error__bad_block_header[] = "#bzip2: bad block header"; +-const char wuffs_bzip2__error__bad_block_length[] = "#bzip2: bad block length"; +-const char wuffs_bzip2__error__bad_checksum[] = "#bzip2: bad checksum"; +-const char wuffs_bzip2__error__bad_header[] = "#bzip2: bad header"; +-const char wuffs_bzip2__error__bad_number_of_sections[] = "#bzip2: bad number of sections"; +-const char wuffs_bzip2__error__truncated_input[] = "#bzip2: truncated input"; +-const char wuffs_bzip2__error__unsupported_block_randomization[] = "#bzip2: unsupported block randomization"; +-const char wuffs_bzip2__error__internal_error_inconsistent_huffman_decoder_state[] = "#bzip2: internal error: inconsistent Huffman decoder state"; ++// ---------------- Status Codes Implementations + + // ---------------- Private Consts + +-static const uint8_t +-WUFFS_BZIP2__CLAMP_TO_5[8] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 1, 2, 3, 4, 5, 5, 5, +-}; +- +-static const uint32_t +-WUFFS_BZIP2__REV_CRC32_TABLE[256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 79764919, 159529838, 222504665, 319059676, 398814059, 445009330, 507990021, +- 638119352, 583659535, 797628118, 726387553, 890018660, 835552979, 1015980042, 944750013, +- 1276238704, 1221641927, 1167319070, 1095957929, 1595256236, 1540665371, 1452775106, 1381403509, +- 1780037320, 1859660671, 1671105958, 1733955601, 2031960084, 2111593891, 1889500026, 1952343757, +- 2552477408, 2632100695, 2443283854, 2506133561, 2334638140, 2414271883, 2191915858, 2254759653, +- 3190512472, 3135915759, 3081330742, 3009969537, 2905550212, 2850959411, 2762807018, 2691435357, +- 3560074640, 3505614887, 3719321342, 3648080713, 3342211916, 3287746299, 3467911202, 3396681109, +- 4063920168, 4143685023, 4223187782, 4286162673, 3779000052, 3858754371, 3904687514, 3967668269, +- 881225847, 809987520, 1023691545, 969234094, 662832811, 591600412, 771767749, 717299826, +- 311336399, 374308984, 453813921, 533576470, 25881363, 88864420, 134795389, 214552010, +- 2023205639, 2086057648, 1897238633, 1976864222, 1804852699, 1867694188, 1645340341, 1724971778, +- 1587496639, 1516133128, 1461550545, 1406951526, 1302016099, 1230646740, 1142491917, 1087903418, +- 2896545431, 2825181984, 2770861561, 2716262478, 3215044683, 3143675388, 3055782693, 3001194130, +- 2326604591, 2389456536, 2200899649, 2280525302, 2578013683, 2640855108, 2418763421, 2498394922, +- 3769900519, 3832873040, 3912640137, 3992402750, 4088425275, 4151408268, 4197601365, 4277358050, +- 3334271071, 3263032808, 3476998961, 3422541446, 3585640067, 3514407732, 3694837229, 3640369242, +- 1762451694, 1842216281, 1619975040, 1682949687, 2047383090, 2127137669, 1938468188, 2001449195, +- 1325665622, 1271206113, 1183200824, 1111960463, 1543535498, 1489069629, 1434599652, 1363369299, +- 622672798, 568075817, 748617968, 677256519, 907627842, 853037301, 1067152940, 995781531, +- 51762726, 131386257, 177728840, 240578815, 269590778, 349224269, 429104020, 491947555, +- 4046411278, 4126034873, 4172115296, 4234965207, 3794477266, 3874110821, 3953728444, 4016571915, +- 3609705398, 3555108353, 3735388376, 3664026991, 3290680682, 3236090077, 3449943556, 3378572211, +- 3174993278, 3120533705, 3032266256, 2961025959, 2923101090, 2868635157, 2813903052, 2742672763, +- 2604032198, 2683796849, 2461293480, 2524268063, 2284983834, 2364738477, 2175806836, 2238787779, +- 1569362073, 1498123566, 1409854455, 1355396672, 1317987909, 1246755826, 1192025387, 1137557660, +- 2072149281, 2135122070, 1912620623, 1992383480, 1753615357, 1816598090, 1627664531, 1707420964, +- 295390185, 358241886, 404320391, 483945776, 43990325, 106832002, 186451547, 266083308, +- 932423249, 861060070, 1041341759, 986742920, 613929101, 542559546, 756411363, 701822548, +- 3316196985, 3244833742, 3425377559, 3370778784, 3601682597, 3530312978, 3744426955, 3689838204, +- 3819031489, 3881883254, 3928223919, 4007849240, 4037393693, 4100235434, 4180117107, 4259748804, +- 2310601993, 2373574846, 2151335527, 2231098320, 2596047829, 2659030626, 2470359227, 2550115596, +- 2947551409, 2876312838, 2788305887, 2733848168, 3165939309, 3094707162, 3040238851, 2985771188, +-}; +- + // ---------------- Private Initializer Prototypes + + // ---------------- Private Function Prototypes + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__do_transform_io( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__prepare_block( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__read_code_lengths( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__build_huffman_tree( +- wuffs_bzip2__decoder* self, +- uint32_t a_which); +- + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_bzip2__decoder__build_huffman_table( +- wuffs_bzip2__decoder* self, +- uint32_t a_which); ++wuffs_adler32__hasher__up( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_bzip2__decoder__invert_bwt( +- wuffs_bzip2__decoder* self); ++wuffs_adler32__hasher__up__choosy_default( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x); + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_bzip2__decoder__flush_fast( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_dst); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__flush_slow( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_dst); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__decode_huffman_fast( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_src); ++wuffs_adler32__hasher__up_arm_neon( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__decode_huffman_slow( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_src); ++static wuffs_base__empty_struct ++wuffs_adler32__hasher__up_x86_sse42( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) + + // ---------------- VTables + +-const wuffs_base__io_transformer__func_ptrs +-wuffs_bzip2__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++const wuffs_base__hasher_u32__func_ptrs ++wuffs_adler32__hasher__func_ptrs_for__wuffs_base__hasher_u32 = { ++ (uint32_t(*)(const void*))(&wuffs_adler32__hasher__checksum_u32), + (uint64_t(*)(const void*, +- uint32_t))(&wuffs_bzip2__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_bzip2__decoder__history_retain_length), ++ uint32_t))(&wuffs_adler32__hasher__get_quirk), + (wuffs_base__status(*)(void*, + uint32_t, +- uint64_t))(&wuffs_bzip2__decoder__set_quirk), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__slice_u8))(&wuffs_bzip2__decoder__transform_io), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_bzip2__decoder__workbuf_len), ++ uint64_t))(&wuffs_adler32__hasher__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_adler32__hasher__update), ++ (uint32_t(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_adler32__hasher__update_u32), + }; + + // ---------------- Initializer Implementations + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_bzip2__decoder__initialize( +- wuffs_bzip2__decoder* self, ++wuffs_adler32__hasher__initialize( ++ wuffs_adler32__hasher* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options){ +@@ -30559,23 +30841,25 @@ wuffs_bzip2__decoder__initialize( + } + } + ++ self->private_impl.choosy_up = &wuffs_adler32__hasher__up__choosy_default; ++ + self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = +- wuffs_base__io_transformer__vtable_name; +- self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = +- (const void*)(&wuffs_bzip2__decoder__func_ptrs_for__wuffs_base__io_transformer); ++ self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name = ++ wuffs_base__hasher_u32__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers = ++ (const void*)(&wuffs_adler32__hasher__func_ptrs_for__wuffs_base__hasher_u32); + return wuffs_base__make_status(NULL); + } + +-wuffs_bzip2__decoder* +-wuffs_bzip2__decoder__alloc(void) { +- wuffs_bzip2__decoder* x = +- (wuffs_bzip2__decoder*)(calloc(sizeof(wuffs_bzip2__decoder), 1)); ++wuffs_adler32__hasher* ++wuffs_adler32__hasher__alloc(void) { ++ wuffs_adler32__hasher* x = ++ (wuffs_adler32__hasher*)(calloc(1, sizeof(wuffs_adler32__hasher))); + if (!x) { + return NULL; + } +- if (wuffs_bzip2__decoder__initialize( +- x, sizeof(wuffs_bzip2__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ if (wuffs_adler32__hasher__initialize( ++ x, sizeof(wuffs_adler32__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { + free(x); + return NULL; + } +@@ -30583,18 +30867,18 @@ wuffs_bzip2__decoder__alloc(void) { + } + + size_t +-sizeof__wuffs_bzip2__decoder(void) { +- return sizeof(wuffs_bzip2__decoder); ++sizeof__wuffs_adler32__hasher(void) { ++ return sizeof(wuffs_adler32__hasher); + } + + // ---------------- Function Implementations + +-// -------- func bzip2.decoder.get_quirk ++// -------- func adler32.hasher.get_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_bzip2__decoder__get_quirk( +- const wuffs_bzip2__decoder* self, ++wuffs_adler32__hasher__get_quirk( ++ const wuffs_adler32__hasher* self, + uint32_t a_key) { + if (!self) { + return 0; +@@ -30607,12 +30891,12 @@ wuffs_bzip2__decoder__get_quirk( + return 0u; + } + +-// -------- func bzip2.decoder.set_quirk ++// -------- func adler32.hasher.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_bzip2__decoder__set_quirk( +- wuffs_bzip2__decoder* self, ++wuffs_adler32__hasher__set_quirk( ++ wuffs_adler32__hasher* self, + uint32_t a_key, + uint64_t a_value) { + if (!self) { +@@ -30625,369 +30909,699 @@ wuffs_bzip2__decoder__set_quirk( + : wuffs_base__error__initialize_not_called); + } + +- if (a_key == 1u) { +- self->private_impl.f_ignore_checksum = (a_value > 0u); +- return wuffs_base__make_status(NULL); +- } + return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func bzip2.decoder.history_retain_length ++// -------- func adler32.hasher.update + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_bzip2__decoder__history_retain_length( +- const wuffs_bzip2__decoder* self) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_adler32__hasher__update( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x) { + if (!self) { +- return 0; ++ return wuffs_base__make_empty_struct(); + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); + } + +- return 0u; ++ if ( ! self->private_impl.f_started) { ++ self->private_impl.f_started = true; ++ self->private_impl.f_state = 1u; ++ self->private_impl.choosy_up = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_adler32__hasher__up_arm_neon : ++#endif ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_adler32__hasher__up_x86_sse42 : ++#endif ++ self->private_impl.choosy_up); ++ } ++ wuffs_adler32__hasher__up(self, a_x); ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func bzip2.decoder.workbuf_len ++// -------- func adler32.hasher.update_u32 + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_bzip2__decoder__workbuf_len( +- const wuffs_bzip2__decoder* self) { ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_adler32__hasher__update_u32( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x) { + if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ return 0; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return 0; + } + +- return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++ wuffs_adler32__hasher__update(self, a_x); ++ return self->private_impl.f_state; + } + +-// -------- func bzip2.decoder.transform_io ++// -------- func adler32.hasher.up + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_bzip2__decoder__transform_io( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++static wuffs_base__empty_struct ++wuffs_adler32__hasher__up( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ return (*self->private_impl.choosy_up)(self, a_x); ++} + +- uint32_t coro_susp_point = self->private_impl.p_transform_io[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_adler32__hasher__up__choosy_default( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint32_t v_s1 = 0; ++ uint32_t v_s2 = 0; ++ wuffs_base__slice_u8 v_remaining = {0}; ++ wuffs_base__slice_u8 v_p = {0}; + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_bzip2__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); +- v_status = t_0; ++ v_s1 = ((self->private_impl.f_state) & 0xFFFFu); ++ v_s2 = ((self->private_impl.f_state) >> (32u - 16u)); ++ while (((uint64_t)(a_x.len)) > 0u) { ++ v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0u); ++ if (((uint64_t)(a_x.len)) > 5552u) { ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5552u); ++ a_x = wuffs_base__slice_u8__subslice_j(a_x, 5552u); ++ } ++ { ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 1; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8)); ++ while (v_p.ptr < i_end0_p) { ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; + } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_bzip2__error__truncated_input); +- goto exit; ++ v_p.len = 1; ++ const uint8_t* i_end1_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end1_p) { ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; + } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ v_p.len = 0; + } +- +- ok: +- self->private_impl.p_transform_io[0] = 0; +- goto exit; ++ v_s1 %= 65521u; ++ v_s2 %= 65521u; ++ a_x = v_remaining; + } ++ self->private_impl.f_state = (((v_s2 & 65535u) << 16u) | (v_s1 & 65535u)); ++ return wuffs_base__make_empty_struct(); ++} + +- goto suspend; +- suspend: +- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++// -------- func adler32.hasher.checksum_u32 + +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_adler32__hasher__checksum_u32( ++ const wuffs_adler32__hasher* self) { ++ if (!self) { ++ return 0; + } +- return status; ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return self->private_impl.f_state; + } + +-// -------- func bzip2.decoder.do_transform_io ++// ‼ WUFFS MULTI-FILE SECTION +arm_neon ++// -------- func adler32.hasher.up_arm_neon + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__do_transform_io( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint8_t v_c = 0; +- uint32_t v_i = 0; +- uint64_t v_tag = 0; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- uint32_t v_final_checksum_want = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++static wuffs_base__empty_struct ++wuffs_adler32__hasher__up_arm_neon( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint32_t v_s1 = 0; ++ uint32_t v_s2 = 0; ++ wuffs_base__slice_u8 v_remaining = {0}; ++ wuffs_base__slice_u8 v_p = {0}; ++ uint8x16_t v_p__left = {0}; ++ uint8x16_t v_p_right = {0}; ++ uint32x4_t v_v1 = {0}; ++ uint32x4_t v_v2 = {0}; ++ uint16x8_t v_col0 = {0}; ++ uint16x8_t v_col1 = {0}; ++ uint16x8_t v_col2 = {0}; ++ uint16x8_t v_col3 = {0}; ++ uint32x2_t v_sum1 = {0}; ++ uint32x2_t v_sum2 = {0}; ++ uint32x2_t v_sum12 = {0}; ++ uint32_t v_num_iterate_bytes = 0; ++ uint64_t v_tail_index = 0; + +- uint32_t coro_susp_point = self->private_impl.p_do_transform_io[0]; +- if (coro_susp_point) { +- v_i = self->private_data.s_do_transform_io[0].v_i; +- v_tag = self->private_data.s_do_transform_io[0].v_tag; +- v_final_checksum_want = self->private_data.s_do_transform_io[0].v_final_checksum_want; ++ v_s1 = ((self->private_impl.f_state) & 0xFFFFu); ++ v_s2 = ((self->private_impl.f_state) >> (32u - 16u)); ++ while ((((uint64_t)(a_x.len)) > 0u) && ((15u & ((uint32_t)(0xFFFu & (uintptr_t)(a_x.ptr)))) != 0u)) { ++ v_s1 += ((uint32_t)(a_x.ptr[0u])); ++ v_s2 += v_s1; ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); + } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if (v_c != 66u) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_header); +- goto exit; ++ v_s1 %= 65521u; ++ v_s2 %= 65521u; ++ while (((uint64_t)(a_x.len)) > 0u) { ++ v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0u); ++ if (((uint64_t)(a_x.len)) > 5536u) { ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5536u); ++ a_x = wuffs_base__slice_u8__subslice_j(a_x, 5536u); + } ++ v_num_iterate_bytes = ((uint32_t)((((uint64_t)(a_x.len)) & 4294967264u))); ++ v_s2 += ((uint32_t)(v_s1 * v_num_iterate_bytes)); ++ v_v1 = vdupq_n_u32(0u); ++ v_v2 = vdupq_n_u32(0u); ++ v_col0 = vdupq_n_u16(0u); ++ v_col1 = vdupq_n_u16(0u); ++ v_col2 = vdupq_n_u16(0u); ++ v_col3 = vdupq_n_u16(0u); + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 32; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32)); ++ while (v_p.ptr < i_end0_p) { ++ v_p__left = vld1q_u8(v_p.ptr); ++ v_p_right = vld1q_u8(v_p.ptr + 16u); ++ v_v2 = vaddq_u32(v_v2, v_v1); ++ v_v1 = vpadalq_u16(v_v1, vpadalq_u8(vpaddlq_u8(v_p__left), v_p_right)); ++ v_col0 = vaddw_u8(v_col0, vget_low_u8(v_p__left)); ++ v_col1 = vaddw_u8(v_col1, vget_high_u8(v_p__left)); ++ v_col2 = vaddw_u8(v_col2, vget_low_u8(v_p_right)); ++ v_col3 = vaddw_u8(v_col3, vget_high_u8(v_p_right)); ++ v_p.ptr += 32; + } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; +- } +- if (v_c != 90u) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_header); +- goto exit; ++ v_p.len = 0; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ v_v2 = vshlq_n_u32(v_v2, 5u); ++ v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col0), ((uint16x4_t){32u, 31u, 30u, 29u})); ++ v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col0), ((uint16x4_t){28u, 27u, 26u, 25u})); ++ v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col1), ((uint16x4_t){24u, 23u, 22u, 21u})); ++ v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col1), ((uint16x4_t){20u, 19u, 18u, 17u})); ++ v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col2), ((uint16x4_t){16u, 15u, 14u, 13u})); ++ v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col2), ((uint16x4_t){12u, 11u, 10u, 9u})); ++ v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col3), ((uint16x4_t){8u, 7u, 6u, 5u})); ++ v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col3), ((uint16x4_t){4u, 3u, 2u, 1u})); ++ v_sum1 = vpadd_u32(vget_low_u32(v_v1), vget_high_u32(v_v1)); ++ v_sum2 = vpadd_u32(vget_low_u32(v_v2), vget_high_u32(v_v2)); ++ v_sum12 = vpadd_u32(v_sum1, v_sum2); ++ v_s1 += vget_lane_u32(v_sum12, 0u); ++ v_s2 += vget_lane_u32(v_sum12, 1u); ++ v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551584u); ++ if (v_tail_index < ((uint64_t)(a_x.len))) { ++ { ++ wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index); ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 1; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end0_p) { ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; ++ } ++ v_p.len = 0; + } +- uint8_t t_2 = *iop_a_src++; +- v_c = t_2; + } +- if (v_c != 104u) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_header); +- goto exit; ++ v_s1 %= 65521u; ++ v_s2 %= 65521u; ++ a_x = v_remaining; ++ } ++ self->private_impl.f_state = (((v_s2 & 65535u) << 16u) | (v_s1 & 65535u)); ++ return wuffs_base__make_empty_struct(); ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++// ‼ WUFFS MULTI-FILE SECTION -arm_neon ++ ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++// -------- func adler32.hasher.up_x86_sse42 ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_adler32__hasher__up_x86_sse42( ++ wuffs_adler32__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint32_t v_s1 = 0; ++ uint32_t v_s2 = 0; ++ wuffs_base__slice_u8 v_remaining = {0}; ++ wuffs_base__slice_u8 v_p = {0}; ++ __m128i v_zeroes = {0}; ++ __m128i v_ones = {0}; ++ __m128i v_weights__left = {0}; ++ __m128i v_weights_right = {0}; ++ __m128i v_q__left = {0}; ++ __m128i v_q_right = {0}; ++ __m128i v_v1 = {0}; ++ __m128i v_v2 = {0}; ++ __m128i v_v2j = {0}; ++ __m128i v_v2k = {0}; ++ uint32_t v_num_iterate_bytes = 0; ++ uint64_t v_tail_index = 0; ++ ++ v_zeroes = _mm_set1_epi16((int16_t)(0u)); ++ v_ones = _mm_set1_epi16((int16_t)(1u)); ++ v_weights__left = _mm_set_epi8((int8_t)(17u), (int8_t)(18u), (int8_t)(19u), (int8_t)(20u), (int8_t)(21u), (int8_t)(22u), (int8_t)(23u), (int8_t)(24u), (int8_t)(25u), (int8_t)(26u), (int8_t)(27u), (int8_t)(28u), (int8_t)(29u), (int8_t)(30u), (int8_t)(31u), (int8_t)(32u)); ++ v_weights_right = _mm_set_epi8((int8_t)(1u), (int8_t)(2u), (int8_t)(3u), (int8_t)(4u), (int8_t)(5u), (int8_t)(6u), (int8_t)(7u), (int8_t)(8u), (int8_t)(9u), (int8_t)(10u), (int8_t)(11u), (int8_t)(12u), (int8_t)(13u), (int8_t)(14u), (int8_t)(15u), (int8_t)(16u)); ++ v_s1 = ((self->private_impl.f_state) & 0xFFFFu); ++ v_s2 = ((self->private_impl.f_state) >> (32u - 16u)); ++ while (((uint64_t)(a_x.len)) > 0u) { ++ v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0u); ++ if (((uint64_t)(a_x.len)) > 5536u) { ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5536u); ++ a_x = wuffs_base__slice_u8__subslice_j(a_x, 5536u); + } ++ v_num_iterate_bytes = ((uint32_t)((((uint64_t)(a_x.len)) & 4294967264u))); ++ v_s2 += ((uint32_t)(v_s1 * v_num_iterate_bytes)); ++ v_v1 = _mm_setzero_si128(); ++ v_v2j = _mm_setzero_si128(); ++ v_v2k = _mm_setzero_si128(); + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_3 = *iop_a_src++; +- v_c = t_3; +- } +- if ((v_c < 49u) || (57u < v_c)) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_header); +- goto exit; +- } +- self->private_impl.f_max_incl_block_size = (((uint32_t)((v_c - 48u))) * 100000u); +- while (true) { +- v_tag = 0u; +- v_i = 0u; +- while (v_i < 48u) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_4 = *iop_a_src++; +- v_c = t_4; +- } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; +- } +- v_tag <<= 1u; +- v_tag |= ((uint64_t)((self->private_impl.f_bits >> 31u))); +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 1u; +- } +- if (v_tag == 25779555029136u) { +- break; +- } else if (v_tag != 54156738319193u) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- status = wuffs_bzip2__decoder__prepare_block(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_block_size = 0u; +- self->private_impl.f_decode_huffman_finished = false; +- self->private_impl.f_decode_huffman_which = WUFFS_BZIP2__CLAMP_TO_5[(self->private_data.f_huffman_selectors[0u] & 7u)]; +- self->private_impl.f_decode_huffman_ticks = 50u; +- self->private_impl.f_decode_huffman_section = 0u; +- self->private_impl.f_decode_huffman_run_shift = 0u; +- while ( ! self->private_impl.f_decode_huffman_finished) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_status = wuffs_bzip2__decoder__decode_huffman_fast(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (wuffs_base__status__is_error(&v_status)) { +- status = v_status; +- goto exit; +- } else if (self->private_impl.f_decode_huffman_finished) { +- break; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- status = wuffs_bzip2__decoder__decode_huffman_slow(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } +- wuffs_bzip2__decoder__invert_bwt(self); +- self->private_impl.f_block_checksum_have = 4294967295u; +- if (self->private_impl.f_original_pointer >= self->private_impl.f_block_size) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); +- goto exit; +- } +- self->private_impl.f_flush_pointer = (self->private_data.f_bwt[self->private_impl.f_original_pointer] >> 12u); +- self->private_impl.f_flush_repeat_count = 0u; +- self->private_impl.f_flush_prev = 0u; +- while (self->private_impl.f_block_size > 0u) { +- wuffs_bzip2__decoder__flush_fast(self, a_dst); +- if (self->private_impl.f_block_size <= 0u) { +- break; +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- status = wuffs_bzip2__decoder__flush_slow(self, a_dst); +- if (status.repr) { +- goto suspend; +- } +- } +- self->private_impl.f_block_checksum_have ^= 4294967295u; +- if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_block_checksum_have != self->private_impl.f_block_checksum_want)) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_checksum); +- goto exit; ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 32; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32)); ++ while (v_p.ptr < i_end0_p) { ++ v_q__left = _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr)); ++ v_q_right = _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16u)); ++ v_v2j = _mm_add_epi32(v_v2j, v_v1); ++ v_v1 = _mm_add_epi32(v_v1, _mm_sad_epu8(v_q__left, v_zeroes)); ++ v_v1 = _mm_add_epi32(v_v1, _mm_sad_epu8(v_q_right, v_zeroes)); ++ v_v2k = _mm_add_epi32(v_v2k, _mm_madd_epi16(v_ones, _mm_maddubs_epi16(v_q__left, v_weights__left))); ++ v_v2k = _mm_add_epi32(v_v2k, _mm_madd_epi16(v_ones, _mm_maddubs_epi16(v_q_right, v_weights_right))); ++ v_p.ptr += 32; + } +- self->private_impl.f_final_checksum_have = (self->private_impl.f_block_checksum_have ^ ((self->private_impl.f_final_checksum_have >> 31u) | ((uint32_t)(self->private_impl.f_final_checksum_have << 1u)))); ++ v_p.len = 0; + } +- v_final_checksum_want = 0u; +- v_i = 0u; +- while (v_i < 32u) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_5 = *iop_a_src++; +- v_c = t_5; ++ v_v1 = _mm_add_epi32(v_v1, _mm_shuffle_epi32(v_v1, (int32_t)(177u))); ++ v_v1 = _mm_add_epi32(v_v1, _mm_shuffle_epi32(v_v1, (int32_t)(78u))); ++ v_s1 += ((uint32_t)(_mm_cvtsi128_si32(v_v1))); ++ v_v2 = _mm_add_epi32(v_v2k, _mm_slli_epi32(v_v2j, (int32_t)(5u))); ++ v_v2 = _mm_add_epi32(v_v2, _mm_shuffle_epi32(v_v2, (int32_t)(177u))); ++ v_v2 = _mm_add_epi32(v_v2, _mm_shuffle_epi32(v_v2, (int32_t)(78u))); ++ v_s2 += ((uint32_t)(_mm_cvtsi128_si32(v_v2))); ++ v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551584u); ++ if (v_tail_index < ((uint64_t)(a_x.len))) { ++ { ++ wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index); ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 1; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end0_p) { ++ v_s1 += ((uint32_t)(v_p.ptr[0u])); ++ v_s2 += v_s1; ++ v_p.ptr += 1; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; ++ v_p.len = 0; + } +- v_final_checksum_want <<= 1u; +- v_final_checksum_want |= (self->private_impl.f_bits >> 31u); +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 1u; + } +- if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_final_checksum_have != v_final_checksum_want)) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_checksum); +- goto exit; +- } +- +- goto ok; +- ok: +- self->private_impl.p_do_transform_io[0] = 0; +- goto exit; ++ v_s1 %= 65521u; ++ v_s2 %= 65521u; ++ a_x = v_remaining; + } ++ self->private_impl.f_state = (((v_s2 & 65535u) << 16u) | (v_s1 & 65535u)); ++ return wuffs_base__make_empty_struct(); ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +- goto suspend; +- suspend: +- self->private_impl.p_do_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_transform_io[0].v_i = v_i; +- self->private_data.s_do_transform_io[0].v_tag = v_tag; +- self->private_data.s_do_transform_io[0].v_final_checksum_want = v_final_checksum_want; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32) + +- return status; +-} ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP) + +-// -------- func bzip2.decoder.prepare_block ++// ---------------- Status Codes Implementations + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__prepare_block( +- wuffs_bzip2__decoder* self, ++const char wuffs_bmp__error__bad_header[] = "#bmp: bad header"; ++const char wuffs_bmp__error__bad_rle_compression[] = "#bmp: bad RLE compression"; ++const char wuffs_bmp__error__truncated_input[] = "#bmp: truncated input"; ++const char wuffs_bmp__error__unsupported_bmp_file[] = "#bmp: unsupported BMP file"; ++const char wuffs_bmp__note__internal_note_short_read[] = "@bmp: internal note: short read"; ++ ++// ---------------- Private Consts ++ ++#define WUFFS_BMP__COMPRESSION_NONE 0u ++ ++#define WUFFS_BMP__COMPRESSION_RLE8 1u ++ ++#define WUFFS_BMP__COMPRESSION_RLE4 2u ++ ++#define WUFFS_BMP__COMPRESSION_BITFIELDS 3u ++ ++#define WUFFS_BMP__COMPRESSION_JPEG 4u ++ ++#define WUFFS_BMP__COMPRESSION_PNG 5u ++ ++#define WUFFS_BMP__COMPRESSION_ALPHABITFIELDS 6u ++ ++#define WUFFS_BMP__COMPRESSION_LOW_BIT_DEPTH 256u ++ ++#define WUFFS_BMP__RLE_STATE_NEUTRAL 0u ++ ++#define WUFFS_BMP__RLE_STATE_RUN 1u ++ ++#define WUFFS_BMP__RLE_STATE_ESCAPE 2u ++ ++#define WUFFS_BMP__RLE_STATE_LITERAL 3u ++ ++#define WUFFS_BMP__RLE_STATE_DELTA_X 4u ++ ++#define WUFFS_BMP__RLE_STATE_DELTA_Y 5u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__do_decode_image_config( ++ wuffs_bmp__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__do_decode_frame_config( ++ wuffs_bmp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__do_decode_frame( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__swizzle_none( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__swizzle_rle( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__swizzle_bitfields( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__swizzle_low_bit_depth( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__do_tell_me_more( ++ wuffs_bmp__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__read_palette( ++ wuffs_bmp__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__process_masks( ++ wuffs_bmp__decoder* self); ++ ++// ---------------- VTables ++ ++const wuffs_base__image_decoder__func_ptrs ++wuffs_bmp__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_bmp__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_bmp__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_bmp__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_bmp__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_bmp__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_bmp__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_bmp__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_bmp__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_bmp__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_bmp__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_bmp__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_bmp__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_bmp__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_bmp__decoder__initialize( ++ wuffs_bmp__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_bmp__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_bmp__decoder* ++wuffs_bmp__decoder__alloc(void) { ++ wuffs_bmp__decoder* x = ++ (wuffs_bmp__decoder*)(calloc(1, sizeof(wuffs_bmp__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_bmp__decoder__initialize( ++ x, sizeof(wuffs_bmp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_bmp__decoder(void) { ++ return sizeof(wuffs_bmp__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func bmp.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_bmp__decoder__get_quirk( ++ const wuffs_bmp__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func bmp.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_bmp__decoder__set_quirk( ++ wuffs_bmp__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func bmp.decoder.decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_bmp__decoder__decode_image_config( ++ wuffs_bmp__decoder* self, ++ wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint32_t v_i = 0; +- uint32_t v_j = 0; +- uint32_t v_selector = 0; +- uint32_t v_sel_ff = 0; +- uint8_t v_movee = 0; + wuffs_base__status v_status = wuffs_base__make_status(NULL); + ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_bmp__decoder__do_decode_image_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_bmp__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func bmp.decoder.do_decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__do_decode_image_config( ++ wuffs_bmp__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_magic = 0; ++ uint32_t v_width = 0; ++ uint32_t v_height = 0; ++ uint32_t v_planes = 0; ++ uint32_t v_n = 0; ++ uint32_t v_dst_pixfmt = 0; ++ uint32_t v_byte_width = 0; ++ + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -30999,797 +31613,1141 @@ wuffs_bzip2__decoder__prepare_block( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_prepare_block[0]; +- if (coro_susp_point) { +- v_i = self->private_data.s_prepare_block[0].v_i; +- v_selector = self->private_data.s_prepare_block[0].v_selector; +- } ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- self->private_impl.f_block_checksum_want = 0u; +- v_i = 0u; +- while (v_i < 32u) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if ((self->private_impl.f_call_sequence != 0u) || (self->private_impl.f_io_redirect_fourcc == 1u)) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } else if (self->private_impl.f_io_redirect_fourcc != 0u) { ++ status = wuffs_base__make_status(wuffs_base__note__i_o_redirect); ++ goto ok; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; +- } +- self->private_impl.f_block_checksum_want <<= 1u; +- self->private_impl.f_block_checksum_want |= (self->private_impl.f_bits >> 31u); +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 1u; +- } +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 8) { ++ t_0 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; + } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; ++ v_magic = t_0; + } +- if ((self->private_impl.f_bits >> 31u) != 0u) { +- status = wuffs_base__make_status(wuffs_bzip2__error__unsupported_block_randomization); ++ if (v_magic != 19778u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); + goto exit; + } +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- self->private_impl.f_original_pointer = 0u; +- v_i = 0u; +- while (v_i < 24u) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ self->private_data.s_do_decode_image_config.scratch = 8u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (self->private_data.s_do_decode_image_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_image_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_image_config.scratch; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_2 = *iop_a_src++; +- v_c = t_2; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; + } +- self->private_impl.f_original_pointer <<= 1u; +- self->private_impl.f_original_pointer |= (self->private_impl.f_bits >> 31u); +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 1u; ++ self->private_impl.f_padding = t_1; + } +- v_i = 0u; +- while (v_i < 256u) { +- self->private_data.f_presence[v_i] = 0u; +- v_i += 1u; ++ if (self->private_impl.f_padding < 14u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; + } +- v_i = 0u; +- while (v_i < 256u) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ self->private_impl.f_padding -= 14u; ++ self->private_impl.f_io_redirect_pos = wuffs_base__u64__sat_add(((uint64_t)(self->private_impl.f_padding)), wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_3 = *iop_a_src++; +- v_c = t_3; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ if (num_bits_2 == 24) { ++ t_2 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)) << 56; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; +- } +- if ((self->private_impl.f_bits >> 31u) != 0u) { +- self->private_data.f_presence[v_i] = 1u; + } +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 16u; ++ self->private_impl.f_bitmap_info_len = t_2; + } +- self->private_data.f_scratch = 0u; +- v_i = 0u; +- while (v_i < 256u) { +- if (self->private_data.f_presence[v_i] == 0u) { +- v_i += 16u; +- continue; +- } +- while (true) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (self->private_impl.f_padding < self->private_impl.f_bitmap_info_len) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; ++ } ++ self->private_impl.f_padding -= self->private_impl.f_bitmap_info_len; ++ if (self->private_impl.f_bitmap_info_len == 12u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_3 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_4 = *iop_a_src++; +- v_c = t_4; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; ++ if (num_bits_3 == 8) { ++ t_3 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)) << 56; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; +- } +- self->private_data.f_scratch += (self->private_impl.f_bits >> 31u); +- self->private_data.f_presence[(v_i & 255u)] = ((uint8_t)((self->private_impl.f_bits >> 31u))); +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 1u; +- if ((v_i & 15u) == 0u) { +- break; + } ++ self->private_impl.f_width = t_3; + } +- } +- if ((self->private_data.f_scratch < 1u) || (256u < self->private_data.f_scratch)) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); +- goto exit; +- } +- self->private_impl.f_num_symbols = (self->private_data.f_scratch + 2u); +- self->private_data.f_scratch = 0u; +- v_i = 0u; +- while (v_i < 3u) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ uint32_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_4 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; ++ if (num_bits_4 == 8) { ++ t_4 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)) << 56; + } +- uint8_t t_5 = *iop_a_src++; +- v_c = t_5; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; ++ self->private_impl.f_height = t_4; + } +- self->private_data.f_scratch <<= 1u; +- self->private_data.f_scratch |= (self->private_impl.f_bits >> 31u); +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 1u; +- } +- if ((self->private_data.f_scratch < 2u) || (6u < self->private_data.f_scratch)) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); +- goto exit; +- } +- self->private_impl.f_num_huffman_codes = self->private_data.f_scratch; +- self->private_data.f_scratch = 0u; +- v_i = 0u; +- while (v_i < 15u) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ uint32_t t_5; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_5 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_5 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_5; ++ if (num_bits_5 == 8) { ++ t_5 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_5 += 8u; ++ *scratch |= ((uint64_t)(num_bits_5)) << 56; + } +- uint8_t t_6 = *iop_a_src++; +- v_c = t_6; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; ++ v_planes = t_5; + } +- self->private_data.f_scratch <<= 1u; +- self->private_data.f_scratch |= (self->private_impl.f_bits >> 31u); +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 1u; +- } +- if ((self->private_data.f_scratch < 1u) || (18001u < self->private_data.f_scratch)) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); +- goto exit; +- } +- self->private_impl.f_num_sections = self->private_data.f_scratch; +- v_i = 0u; +- while (v_i < self->private_impl.f_num_huffman_codes) { +- self->private_data.f_mtft[v_i] = ((uint8_t)(v_i)); +- v_i += 1u; +- } +- v_i = 0u; +- while (v_i < self->private_impl.f_num_sections) { +- v_selector = 0u; +- while (true) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (v_planes != 1u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ uint32_t t_6; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_6 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_7 = *iop_a_src++; +- v_c = t_7; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6; ++ if (num_bits_6 == 8) { ++ t_6 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_6 += 8u; ++ *scratch |= ((uint64_t)(num_bits_6)) << 56; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; +- } +- if ((self->private_impl.f_bits >> 31u) == 0u) { +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- break; + } +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_selector += 1u; +- if (v_selector >= self->private_impl.f_num_huffman_codes) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); +- goto exit; ++ self->private_impl.f_bits_per_pixel = t_6; ++ } ++ } else if (self->private_impl.f_bitmap_info_len == 16u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ uint32_t t_7; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_7 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7; ++ if (num_bits_7 == 24) { ++ t_7 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_7 += 8u; ++ *scratch |= ((uint64_t)(num_bits_7)) << 56; ++ } + } ++ v_width = t_7; + } +- if (v_selector == 0u) { +- self->private_data.f_huffman_selectors[v_i] = self->private_data.f_mtft[0u]; +- } else { +- v_sel_ff = (v_selector & 255u); +- v_movee = self->private_data.f_mtft[v_sel_ff]; +- wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1u + v_sel_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_sel_ff)); +- self->private_data.f_mtft[0u] = v_movee; +- self->private_data.f_huffman_selectors[v_i] = v_movee; ++ if (v_width > 2147483647u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; ++ } else if (v_width > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; + } +- v_i += 1u; +- } +- v_i = 0u; +- while (v_i < self->private_impl.f_num_huffman_codes) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ self->private_impl.f_width = v_width; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18); ++ uint32_t t_8; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8; ++ if (num_bits_8 == 24) { ++ t_8 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_8 += 8u; ++ *scratch |= ((uint64_t)(num_bits_8)) << 56; ++ } ++ } ++ v_height = t_8; + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- status = wuffs_bzip2__decoder__read_code_lengths(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ if (v_height > 2147483647u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; ++ } else if (v_height > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; + } +- if (status.repr) { +- goto suspend; ++ self->private_impl.f_height = v_height; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20); ++ uint32_t t_9; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_9 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9; ++ if (num_bits_9 == 8) { ++ t_9 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_9 += 8u; ++ *scratch |= ((uint64_t)(num_bits_9)) << 56; ++ } ++ } ++ v_planes = t_9; + } +- v_status = wuffs_bzip2__decoder__build_huffman_tree(self, v_i); +- if (wuffs_base__status__is_error(&v_status)) { +- status = v_status; ++ if (v_planes != 1u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); + goto exit; + } +- wuffs_bzip2__decoder__build_huffman_table(self, v_i); +- v_i += 1u; +- } +- v_i = 0u; +- v_j = 0u; +- while (v_i < 256u) { +- if (self->private_data.f_presence[v_i] != 0u) { +- self->private_data.f_mtft[(v_j & 255u)] = ((uint8_t)(v_i)); +- v_j += 1u; +- } +- v_i += 1u; +- } +- v_i = 0u; +- while (v_i < 256u) { +- self->private_data.f_letter_counts[v_i] = 0u; +- v_i += 1u; +- } +- +- goto ok; +- ok: +- self->private_impl.p_prepare_block[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_prepare_block[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_prepare_block[0].v_i = v_i; +- self->private_data.s_prepare_block[0].v_selector = v_selector; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func bzip2.decoder.read_code_lengths +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__read_code_lengths( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint8_t v_c = 0; +- uint32_t v_i = 0; +- uint32_t v_code_length = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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_read_code_lengths[0]; +- if (coro_susp_point) { +- v_i = self->private_data.s_read_code_lengths[0].v_i; +- v_code_length = self->private_data.s_read_code_lengths[0].v_code_length; +- } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- self->private_impl.f_code_lengths_bitmask = 0u; +- v_i = 0u; +- while (v_i < 5u) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22); ++ uint32_t t_10; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_10 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10; ++ if (num_bits_10 == 8) { ++ t_10 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_10 += 8u; ++ *scratch |= ((uint64_t)(num_bits_10)) << 56; + } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; ++ self->private_impl.f_bits_per_pixel = t_10; + } +- v_code_length <<= 1u; +- v_code_length |= (self->private_impl.f_bits >> 31u); +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- v_i += 1u; +- } +- v_i = 0u; +- while (v_i < self->private_impl.f_num_symbols) { +- while (true) { +- if ((v_code_length < 1u) || (20u < v_code_length)) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); +- goto exit; +- } +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ } else { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24); ++ uint32_t t_11; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_11 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(25); ++ while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11; ++ if (num_bits_11 == 24) { ++ t_11 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_11 += 8u; ++ *scratch |= ((uint64_t)(num_bits_11)) << 56; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; + } +- if ((self->private_impl.f_bits >> 31u) == 0u) { +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- break; +- } +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ v_width = t_11; ++ } ++ if (v_width > 2147483647u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; ++ } else if (v_width > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } ++ self->private_impl.f_width = v_width; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(26); ++ uint32_t t_12; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_12 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(27); ++ while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_2 = *iop_a_src++; +- v_c = t_2; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_12 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_12; ++ if (num_bits_12 == 24) { ++ t_12 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_12 += 8u; ++ *scratch |= ((uint64_t)(num_bits_12)) << 56; + } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; + } +- if ((self->private_impl.f_bits >> 31u) == 0u) { +- v_code_length += 1u; ++ v_height = t_12; ++ } ++ if (v_height == 2147483648u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; ++ } else if (v_height > 2147483648u) { ++ v_height = ((uint32_t)(0u - v_height)); ++ if (v_height > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } ++ self->private_impl.f_height = v_height; ++ self->private_impl.f_top_down = true; ++ } else if (v_height > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } else { ++ self->private_impl.f_height = v_height; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(28); ++ uint32_t t_13; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_13 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; + } else { +- v_code_length -= 1u; ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(29); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_13 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_13; ++ if (num_bits_13 == 8) { ++ t_13 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_13 += 8u; ++ *scratch |= ((uint64_t)(num_bits_13)) << 56; ++ } + } +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; ++ v_planes = t_13; + } +- self->private_impl.f_code_lengths_bitmask |= (((uint32_t)(1u)) << (v_code_length & 31u)); +- self->private_data.f_bwt[v_i] = v_code_length; +- v_i += 1u; +- } +- +- goto ok; +- ok: +- self->private_impl.p_read_code_lengths[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_read_code_lengths[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_read_code_lengths[0].v_i = v_i; +- self->private_data.s_read_code_lengths[0].v_code_length = v_code_length; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func bzip2.decoder.build_huffman_tree +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__build_huffman_tree( +- wuffs_bzip2__decoder* self, +- uint32_t a_which) { +- uint32_t v_code_length = 0; +- uint32_t v_symbol_index = 0; +- uint32_t v_num_branch_nodes = 0; +- uint32_t v_stack_height = 0; +- uint32_t v_stack_values[21] = {0}; +- uint32_t v_node_index = 0; +- uint16_t v_leaf_value = 0; +- +- self->private_data.f_huffman_trees[a_which][0u][0u] = 0u; +- self->private_data.f_huffman_trees[a_which][0u][1u] = 0u; +- v_num_branch_nodes = 1u; +- v_stack_height = 1u; +- v_stack_values[0u] = 0u; +- v_code_length = 1u; +- while (v_code_length <= 20u) { +- if ((self->private_impl.f_code_lengths_bitmask & (((uint32_t)(1u)) << v_code_length)) == 0u) { +- v_code_length += 1u; +- continue; +- } +- v_symbol_index = 0u; +- while (v_symbol_index < self->private_impl.f_num_symbols) { +- if (self->private_data.f_bwt[v_symbol_index] != v_code_length) { +- v_symbol_index += 1u; +- continue; ++ if (v_planes != 1u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; + } +- while (true) { +- if (v_stack_height <= 0u) { +- return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_over_subscribed); +- } else if (v_stack_height >= v_code_length) { +- break; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(30); ++ uint32_t t_14; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_14 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(31); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_14 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_14; ++ if (num_bits_14 == 8) { ++ t_14 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_14 += 8u; ++ *scratch |= ((uint64_t)(num_bits_14)) << 56; ++ } + } +- v_node_index = v_stack_values[(v_stack_height - 1u)]; +- if (self->private_data.f_huffman_trees[a_which][v_node_index][0u] == 0u) { +- self->private_data.f_huffman_trees[a_which][v_node_index][0u] = ((uint16_t)(v_num_branch_nodes)); ++ self->private_impl.f_bits_per_pixel = t_14; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(32); ++ uint32_t t_15; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_15 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; + } else { +- self->private_data.f_huffman_trees[a_which][v_node_index][1u] = ((uint16_t)(v_num_branch_nodes)); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(33); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_15 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_15; ++ if (num_bits_15 == 24) { ++ t_15 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_15 += 8u; ++ *scratch |= ((uint64_t)(num_bits_15)) << 56; ++ } + } +- if (v_num_branch_nodes >= 257u) { +- return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_under_subscribed); ++ self->private_impl.f_compression = t_15; ++ } ++ if (self->private_impl.f_bits_per_pixel == 0u) { ++ if (self->private_impl.f_compression == 4u) { ++ self->private_impl.f_io_redirect_fourcc = 1246774599u; ++ status = wuffs_base__make_status(wuffs_base__note__i_o_redirect); ++ goto ok; ++ } else if (self->private_impl.f_compression == 5u) { ++ self->private_impl.f_io_redirect_fourcc = 1347307296u; ++ status = wuffs_base__make_status(wuffs_base__note__i_o_redirect); ++ goto ok; + } +- v_stack_values[v_stack_height] = v_num_branch_nodes; +- self->private_data.f_huffman_trees[a_which][v_num_branch_nodes][0u] = 0u; +- self->private_data.f_huffman_trees[a_which][v_num_branch_nodes][1u] = 0u; +- v_num_branch_nodes += 1u; +- v_stack_height += 1u; ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; + } +- v_node_index = v_stack_values[(v_stack_height - 1u)]; +- if (v_symbol_index < 2u) { +- v_leaf_value = ((uint16_t)((769u + v_symbol_index))); +- } else if ((v_symbol_index + 1u) < self->private_impl.f_num_symbols) { +- v_leaf_value = ((uint16_t)((511u + v_symbol_index))); +- } else { +- v_leaf_value = 768u; ++ self->private_data.s_do_decode_image_config.scratch = 20u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(34); ++ if (self->private_data.s_do_decode_image_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_image_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- if (self->private_data.f_huffman_trees[a_which][v_node_index][0u] == 0u) { +- self->private_data.f_huffman_trees[a_which][v_node_index][0u] = v_leaf_value; +- } else { +- self->private_data.f_huffman_trees[a_which][v_node_index][1u] = v_leaf_value; +- v_stack_height -= 1u; +- while (v_stack_height > 0u) { +- v_node_index = v_stack_values[(v_stack_height - 1u)]; +- if (self->private_data.f_huffman_trees[a_which][v_node_index][1u] == 0u) { +- break; ++ iop_a_src += self->private_data.s_do_decode_image_config.scratch; ++ if (self->private_impl.f_bitmap_info_len == 40u) { ++ if (self->private_impl.f_bits_per_pixel >= 16u) { ++ if (self->private_impl.f_padding >= 16u) { ++ self->private_impl.f_bitmap_info_len = 56u; ++ self->private_impl.f_padding -= 16u; ++ } else if (self->private_impl.f_padding >= 12u) { ++ self->private_impl.f_bitmap_info_len = 52u; ++ self->private_impl.f_padding -= 12u; + } +- v_stack_height -= 1u; + } ++ } else if ((self->private_impl.f_bitmap_info_len != 52u) && ++ (self->private_impl.f_bitmap_info_len != 56u) && ++ (self->private_impl.f_bitmap_info_len != 64u) && ++ (self->private_impl.f_bitmap_info_len != 108u) && ++ (self->private_impl.f_bitmap_info_len != 124u)) { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; ++ } ++ if (self->private_impl.f_compression == 6u) { ++ self->private_impl.f_compression = 3u; ++ } ++ if (self->private_impl.f_compression == 3u) { ++ if (self->private_impl.f_bitmap_info_len >= 52u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(35); ++ uint32_t t_16; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_16 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(36); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_16 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_16; ++ if (num_bits_16 == 24) { ++ t_16 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_16 += 8u; ++ *scratch |= ((uint64_t)(num_bits_16)) << 56; ++ } ++ } ++ self->private_impl.f_channel_masks[2u] = t_16; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(37); ++ uint32_t t_17; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_17 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(38); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_17 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_17; ++ if (num_bits_17 == 24) { ++ t_17 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_17 += 8u; ++ *scratch |= ((uint64_t)(num_bits_17)) << 56; ++ } ++ } ++ self->private_impl.f_channel_masks[1u] = t_17; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(39); ++ uint32_t t_18; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_18 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(40); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_18 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_18; ++ if (num_bits_18 == 24) { ++ t_18 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_18 += 8u; ++ *scratch |= ((uint64_t)(num_bits_18)) << 56; ++ } ++ } ++ self->private_impl.f_channel_masks[0u] = t_18; ++ } ++ if (self->private_impl.f_bitmap_info_len >= 56u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(41); ++ uint32_t t_19; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_19 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(42); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_19 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_19; ++ if (num_bits_19 == 24) { ++ t_19 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_19 += 8u; ++ *scratch |= ((uint64_t)(num_bits_19)) << 56; ++ } ++ } ++ self->private_impl.f_channel_masks[3u] = t_19; ++ } ++ self->private_data.s_do_decode_image_config.scratch = ((uint32_t)(self->private_impl.f_bitmap_info_len - 56u)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(43); ++ if (self->private_data.s_do_decode_image_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_image_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_image_config.scratch; ++ } ++ if ((self->private_impl.f_channel_masks[0u] == 255u) && (self->private_impl.f_channel_masks[1u] == 65280u) && (self->private_impl.f_channel_masks[2u] == 16711680u)) { ++ if (self->private_impl.f_bits_per_pixel == 24u) { ++ self->private_impl.f_compression = 0u; ++ } else if (self->private_impl.f_bits_per_pixel == 32u) { ++ if ((self->private_impl.f_channel_masks[3u] == 0u) || (self->private_impl.f_channel_masks[3u] == 4278190080u)) { ++ self->private_impl.f_compression = 0u; ++ } ++ } ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(44); ++ status = wuffs_bmp__decoder__process_masks(self); ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ } else if (self->private_impl.f_bitmap_info_len >= 40u) { ++ v_n = (self->private_impl.f_bitmap_info_len - 40u); ++ self->private_data.s_do_decode_image_config.scratch = v_n; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(45); ++ if (self->private_data.s_do_decode_image_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_image_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_image_config.scratch; ++ } else { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; + } +- v_symbol_index += 1u; + } +- v_code_length += 1u; ++ if (self->private_impl.f_compression != 3u) { ++ if (self->private_impl.f_bits_per_pixel < 16u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(46); ++ status = wuffs_bmp__decoder__read_palette(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ } ++ if (self->private_impl.f_compression == 0u) { ++ if ((self->private_impl.f_bits_per_pixel == 1u) || (self->private_impl.f_bits_per_pixel == 2u) || (self->private_impl.f_bits_per_pixel == 4u)) { ++ self->private_impl.f_src_pixfmt = 2198077448u; ++ self->private_impl.f_compression = 256u; ++ } else if (self->private_impl.f_bits_per_pixel == 8u) { ++ self->private_impl.f_src_pixfmt = 2198077448u; ++ } else if (self->private_impl.f_bits_per_pixel == 16u) { ++ self->private_impl.f_compression = 3u; ++ self->private_impl.f_channel_masks[0u] = 31u; ++ self->private_impl.f_channel_masks[1u] = 992u; ++ self->private_impl.f_channel_masks[2u] = 31744u; ++ self->private_impl.f_channel_masks[3u] = 0u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(47); ++ status = wuffs_bmp__decoder__process_masks(self); ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_src_pixfmt = 2164308923u; ++ } else if (self->private_impl.f_bits_per_pixel == 24u) { ++ self->private_impl.f_src_pixfmt = 2147485832u; ++ } else if (self->private_impl.f_bits_per_pixel == 32u) { ++ if (self->private_impl.f_channel_masks[3u] == 0u) { ++ self->private_impl.f_src_pixfmt = 2415954056u; ++ } else { ++ self->private_impl.f_src_pixfmt = 2164295816u; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; ++ } ++ } else if (self->private_impl.f_compression == 1u) { ++ if (self->private_impl.f_bits_per_pixel == 8u) { ++ self->private_impl.f_src_pixfmt = 2198077448u; ++ } else { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; ++ } ++ } else if (self->private_impl.f_compression == 2u) { ++ if (self->private_impl.f_bits_per_pixel == 4u) { ++ self->private_impl.f_src_pixfmt = 2198077448u; ++ } else { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; ++ } ++ } else if (self->private_impl.f_compression == 3u) { ++ if ((self->private_impl.f_bits_per_pixel == 16u) || (self->private_impl.f_bits_per_pixel == 32u)) { ++ self->private_impl.f_src_pixfmt = 2164308923u; ++ } else { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); ++ goto exit; ++ } ++ if (((self->private_impl.f_bitmap_info_len < 40u) || (self->private_impl.f_bitmap_info_len == 64u)) && ++ (self->private_impl.f_bits_per_pixel != 1u) && ++ (self->private_impl.f_bits_per_pixel != 4u) && ++ (self->private_impl.f_bits_per_pixel != 8u) && ++ (self->private_impl.f_bits_per_pixel != 24u)) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; ++ } ++ if (self->private_impl.f_bits_per_pixel == 1u) { ++ v_byte_width = ((self->private_impl.f_width >> 3u) + (((self->private_impl.f_width & 7u) + 7u) >> 3u)); ++ self->private_impl.f_pad_per_row = ((4u - (v_byte_width & 3u)) & 3u); ++ } else if (self->private_impl.f_bits_per_pixel == 2u) { ++ v_byte_width = ((self->private_impl.f_width >> 2u) + (((self->private_impl.f_width & 3u) + 3u) >> 2u)); ++ self->private_impl.f_pad_per_row = ((4u - (v_byte_width & 3u)) & 3u); ++ } else if (self->private_impl.f_bits_per_pixel == 4u) { ++ v_byte_width = ((self->private_impl.f_width >> 1u) + (self->private_impl.f_width & 1u)); ++ self->private_impl.f_pad_per_row = ((4u - (v_byte_width & 3u)) & 3u); ++ } else if (self->private_impl.f_bits_per_pixel == 8u) { ++ self->private_impl.f_pad_per_row = ((4u - (self->private_impl.f_width & 3u)) & 3u); ++ } else if (self->private_impl.f_bits_per_pixel == 16u) { ++ self->private_impl.f_pad_per_row = ((self->private_impl.f_width & 1u) * 2u); ++ } else if (self->private_impl.f_bits_per_pixel == 24u) { ++ self->private_impl.f_pad_per_row = (self->private_impl.f_width & 3u); ++ } else if (self->private_impl.f_bits_per_pixel == 32u) { ++ self->private_impl.f_pad_per_row = 0u; ++ } ++ self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ if (a_dst != NULL) { ++ v_dst_pixfmt = 2164295816u; ++ if ((self->private_impl.f_channel_num_bits[0u] > 8u) || ++ (self->private_impl.f_channel_num_bits[1u] > 8u) || ++ (self->private_impl.f_channel_num_bits[2u] > 8u) || ++ (self->private_impl.f_channel_num_bits[3u] > 8u)) { ++ v_dst_pixfmt = 2164308923u; ++ } else if (((self->private_impl.f_src_pixfmt == 2198077448u) || (self->private_impl.f_src_pixfmt == 2147485832u) || (self->private_impl.f_src_pixfmt == 2415954056u)) || ((self->private_impl.f_src_pixfmt == 2164308923u) && (self->private_impl.f_channel_masks[3u] == 0u))) { ++ v_dst_pixfmt = 2415954056u; ++ } ++ wuffs_base__image_config__set( ++ a_dst, ++ v_dst_pixfmt, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ self->private_impl.f_frame_config_io_position, ++ (self->private_impl.f_channel_masks[3u] == 0u)); ++ } ++ self->private_impl.f_call_sequence = 32u; ++ ++ ok: ++ self->private_impl.p_do_decode_image_config = 0; ++ goto exit; + } +- if (v_stack_height != 0u) { +- return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_under_subscribed); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- return wuffs_base__make_status(NULL); ++ ++ return status; + } + +-// -------- func bzip2.decoder.build_huffman_table ++// -------- func bmp.decoder.decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_bzip2__decoder__build_huffman_table( +- wuffs_bzip2__decoder* self, +- uint32_t a_which) { +- uint32_t v_i = 0; +- uint32_t v_bits = 0; +- uint16_t v_n_bits = 0; +- uint16_t v_child = 0; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_bmp__decoder__decode_frame_config( ++ wuffs_bmp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 2)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- while (v_i < 256u) { +- v_bits = (v_i << 24u); +- v_n_bits = 0u; +- v_child = 0u; +- while ((v_child < 257u) && (v_n_bits < 8u)) { +- v_child = self->private_data.f_huffman_trees[a_which][v_child][(v_bits >> 31u)]; +- v_bits <<= 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_n_bits += 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_bmp__decoder__do_decode_frame_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_bmp__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } +- self->private_data.f_huffman_tables[a_which][v_i] = ((uint16_t)((v_child | (v_n_bits << 12u)))); +- v_i += 1u; ++ ++ ok: ++ self->private_impl.p_decode_frame_config = 0; ++ goto exit; + } +- return wuffs_base__make_empty_struct(); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; + } + +-// -------- func bzip2.decoder.invert_bwt ++// -------- func bmp.decoder.do_decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_bzip2__decoder__invert_bwt( +- wuffs_bzip2__decoder* self) { +- uint32_t v_i = 0; +- uint32_t v_letter = 0; +- uint32_t v_sum = 0; +- uint32_t v_old_sum = 0; ++static wuffs_base__status ++wuffs_bmp__decoder__do_decode_frame_config( ++ wuffs_bmp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- v_sum = 0u; +- v_i = 0u; +- while (v_i < 256u) { +- v_old_sum = v_sum; +- v_sum += self->private_data.f_letter_counts[v_i]; +- self->private_data.f_letter_counts[v_i] = v_old_sum; +- v_i += 1u; +- } +- v_i = 0u; +- while (v_i < self->private_impl.f_block_size) { +- v_letter = (self->private_data.f_bwt[v_i] & 255u); +- self->private_data.f_bwt[(self->private_data.f_letter_counts[v_letter] & 1048575u)] |= (v_i << 12u); +- self->private_data.f_letter_counts[v_letter] += 1u; +- v_i += 1u; ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func bzip2.decoder.flush_fast +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_bzip2__decoder__flush_fast( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_dst) { +- uint32_t v_flush_pointer = 0; +- uint32_t v_flush_repeat_count = 0; +- uint8_t v_flush_prev = 0; +- uint32_t v_block_checksum_have = 0; +- uint32_t v_block_size = 0; +- uint32_t v_entry = 0; +- uint8_t v_curr = 0; + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- v_flush_pointer = self->private_impl.f_flush_pointer; +- v_flush_repeat_count = self->private_impl.f_flush_repeat_count; +- v_flush_prev = self->private_impl.f_flush_prev; +- v_block_checksum_have = self->private_impl.f_block_checksum_have; +- v_block_size = self->private_impl.f_block_size; +- while ((v_block_size > 0u) && (((uint64_t)(io2_a_dst - iop_a_dst)) >= 255u)) { +- if (v_flush_repeat_count < 4u) { +- v_entry = self->private_data.f_bwt[v_flush_pointer]; +- v_curr = ((uint8_t)(v_entry)); +- v_flush_pointer = (v_entry >> 12u); +- if (v_curr == v_flush_prev) { +- v_flush_repeat_count += 1u; +- } else { +- v_flush_repeat_count = 1u; ++ if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[(((uint8_t)((v_block_checksum_have >> 24u))) ^ v_curr)] ^ ((uint32_t)(v_block_checksum_have << 8u))); +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_curr), iop_a_dst += 1); +- v_flush_prev = v_curr; +- v_block_size -= 1u; +- } else { +- v_entry = self->private_data.f_bwt[v_flush_pointer]; +- v_curr = ((uint8_t)(v_entry)); +- v_flush_pointer = (v_entry >> 12u); +- v_flush_repeat_count = ((uint32_t)(v_curr)); +- while (v_flush_repeat_count > 0u) { +- v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[(((uint8_t)((v_block_checksum_have >> 24u))) ^ v_flush_prev)] ^ ((uint32_t)(v_block_checksum_have << 8u))); +- if (((uint64_t)(io2_a_dst - iop_a_dst)) > 0u) { +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_flush_prev), iop_a_dst += 1); +- } +- v_flush_repeat_count -= 1u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_bmp__decoder__do_decode_image_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; + } +- v_flush_repeat_count = 0u; +- v_flush_prev = v_curr; +- v_block_size -= 1u; ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); ++ goto exit; ++ } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ self->private_impl.f_call_sequence = 96u; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; + } ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height), ++ ((wuffs_base__flicks)(0u)), ++ 0u, ++ self->private_impl.f_frame_config_io_position, ++ 0u, ++ true, ++ false, ++ 4278190080u); ++ } ++ self->private_impl.f_call_sequence = 64u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame_config = 0; ++ goto exit; + } +- self->private_impl.f_flush_pointer = v_flush_pointer; +- self->private_impl.f_flush_repeat_count = v_flush_repeat_count; +- self->private_impl.f_flush_prev = v_flush_prev; +- self->private_impl.f_block_checksum_have = v_block_checksum_have; +- if (v_block_size <= 900000u) { +- self->private_impl.f_block_size = v_block_size; +- } +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- return wuffs_base__make_empty_struct(); ++ return status; + } + +-// -------- func bzip2.decoder.flush_slow ++// -------- func bmp.decoder.decode_frame + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_bzip2__decoder__flush_slow( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_dst) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_bmp__decoder__decode_frame( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 3)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_flush_pointer = 0; +- uint32_t v_flush_repeat_count = 0; +- uint8_t v_flush_prev = 0; +- uint32_t v_block_checksum_have = 0; +- uint32_t v_block_size = 0; +- uint32_t v_entry = 0; +- uint8_t v_curr = 0; +- +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_flush_slow[0]; +- if (coro_susp_point) { +- v_flush_pointer = self->private_data.s_flush_slow[0].v_flush_pointer; +- v_flush_repeat_count = self->private_data.s_flush_slow[0].v_flush_repeat_count; +- v_flush_prev = self->private_data.s_flush_slow[0].v_flush_prev; +- v_block_checksum_have = self->private_data.s_flush_slow[0].v_block_checksum_have; +- v_block_size = self->private_data.s_flush_slow[0].v_block_size; +- v_curr = self->private_data.s_flush_slow[0].v_curr; +- } ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- v_flush_pointer = self->private_impl.f_flush_pointer; +- v_flush_repeat_count = self->private_impl.f_flush_repeat_count; +- v_flush_prev = self->private_impl.f_flush_prev; +- v_block_checksum_have = self->private_impl.f_block_checksum_have; +- v_block_size = self->private_impl.f_block_size; +- while ((v_block_size > 0u) && ! (self->private_impl.p_flush_slow[0] != 0)) { +- if (v_flush_repeat_count < 4u) { +- v_entry = self->private_data.f_bwt[v_flush_pointer]; +- v_curr = ((uint8_t)(v_entry)); +- v_flush_pointer = (v_entry >> 12u); +- if (v_curr == v_flush_prev) { +- v_flush_repeat_count += 1u; +- } else { +- v_flush_repeat_count = 1u; +- } +- v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[(((uint8_t)((v_block_checksum_have >> 24u))) ^ v_curr)] ^ ((uint32_t)(v_block_checksum_have << 8u))); +- self->private_data.s_flush_slow[0].scratch = v_curr; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (iop_a_dst == io2_a_dst) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- goto suspend; +- } +- *iop_a_dst++ = ((uint8_t)(self->private_data.s_flush_slow[0].scratch)); +- v_flush_prev = v_curr; +- v_block_size -= 1u; +- } else { +- v_entry = self->private_data.f_bwt[v_flush_pointer]; +- v_curr = ((uint8_t)(v_entry)); +- v_flush_pointer = (v_entry >> 12u); +- v_flush_repeat_count = ((uint32_t)(v_curr)); +- while (v_flush_repeat_count > 0u) { +- v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[(((uint8_t)((v_block_checksum_have >> 24u))) ^ v_flush_prev)] ^ ((uint32_t)(v_block_checksum_have << 8u))); +- self->private_data.s_flush_slow[0].scratch = v_flush_prev; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (iop_a_dst == io2_a_dst) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- goto suspend; +- } +- *iop_a_dst++ = ((uint8_t)(self->private_data.s_flush_slow[0].scratch)); +- v_flush_repeat_count -= 1u; +- } +- v_flush_repeat_count = 0u; +- v_flush_prev = v_curr; +- v_block_size -= 1u; ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_bmp__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); ++ v_status = t_0; + } +- } +- self->private_impl.f_flush_pointer = v_flush_pointer; +- self->private_impl.f_flush_repeat_count = v_flush_repeat_count; +- self->private_impl.f_flush_prev = v_flush_prev; +- self->private_impl.f_block_checksum_have = v_block_checksum_have; +- if (v_block_size <= 900000u) { +- self->private_impl.f_block_size = v_block_size; ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_bmp__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } + +- goto ok; + ok: +- self->private_impl.p_flush_slow[0] = 0; ++ self->private_impl.p_decode_frame = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_flush_slow[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_flush_slow[0].v_flush_pointer = v_flush_pointer; +- self->private_data.s_flush_slow[0].v_flush_repeat_count = v_flush_repeat_count; +- self->private_data.s_flush_slow[0].v_flush_prev = v_flush_prev; +- self->private_data.s_flush_slow[0].v_block_checksum_have = v_block_checksum_have; +- self->private_data.s_flush_slow[0].v_block_size = v_block_size; +- self->private_data.s_flush_slow[0].v_curr = v_curr; ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; + + goto exit; + exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; + } +- + return status; + } + +-// -------- func bzip2.decoder.decode_huffman_fast ++// -------- func bmp.decoder.do_decode_frame + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_bzip2__decoder__decode_huffman_fast( +- wuffs_bzip2__decoder* self, +- wuffs_base__io_buffer* a_src) { ++wuffs_bmp__decoder__do_decode_frame( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint32_t v_block_size = 0; +- uint8_t v_which = 0; +- uint32_t v_ticks = 0; +- uint32_t v_section = 0; +- uint32_t v_run_shift = 0; +- uint16_t v_table_entry = 0; +- uint16_t v_child = 0; +- uint32_t v_child_ff = 0; +- uint32_t v_i = 0; +- uint32_t v_j = 0; +- uint32_t v_output = 0; +- uint32_t v_run = 0; +- uint32_t v_mtft0 = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -31802,90 +32760,132 @@ wuffs_bzip2__decoder__decode_huffman_fast( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- v_bits = self->private_impl.f_bits; +- v_n_bits = self->private_impl.f_n_bits; +- v_block_size = self->private_impl.f_block_size; +- v_which = self->private_impl.f_decode_huffman_which; +- v_ticks = self->private_impl.f_decode_huffman_ticks; +- v_section = self->private_impl.f_decode_huffman_section; +- v_run_shift = self->private_impl.f_decode_huffman_run_shift; +- while (((uint64_t)(io2_a_src - iop_a_src)) >= 4u) { +- if (v_ticks > 0u) { +- v_ticks -= 1u; +- } else { +- v_ticks = 49u; +- v_section += 1u; +- if (v_section >= self->private_impl.f_num_sections) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_number_of_sections); +- goto exit; ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- v_which = WUFFS_BZIP2__CLAMP_TO_5[(self->private_data.f_huffman_selectors[(v_section & 32767u)] & 7u)]; +- } +- v_bits |= (wuffs_base__peek_u32be__no_bounds_check(iop_a_src) >> v_n_bits); +- iop_a_src += ((31u - v_n_bits) >> 3u); +- v_n_bits |= 24u; +- v_table_entry = self->private_data.f_huffman_tables[v_which][(v_bits >> 24u)]; +- v_bits <<= (v_table_entry >> 12u); +- v_n_bits -= ((uint32_t)((v_table_entry >> 12u))); +- v_child = (v_table_entry & 1023u); +- while (v_child < 257u) { +- v_child = self->private_data.f_huffman_trees[v_which][v_child][(v_bits >> 31u)]; +- v_bits <<= 1u; +- if (v_n_bits <= 0u) { +- status = wuffs_base__make_status(wuffs_bzip2__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_bmp__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; + } +- v_n_bits -= 1u; +- } +- if (v_child < 768u) { +- v_child_ff = ((uint32_t)((v_child & 255u))); +- v_output = ((uint32_t)(self->private_data.f_mtft[v_child_ff])); +- wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1u + v_child_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_child_ff)); +- self->private_data.f_mtft[0u] = ((uint8_t)(v_output)); +- self->private_data.f_letter_counts[v_output] += 1u; +- self->private_data.f_bwt[v_block_size] = v_output; +- if (v_block_size >= self->private_impl.f_max_incl_block_size) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); +- goto exit; ++ if (status.repr) { ++ goto suspend; + } +- v_block_size += 1u; +- v_run_shift = 0u; +- continue; +- } else if (v_child == 768u) { +- self->private_impl.f_decode_huffman_finished = true; +- break; +- } +- if (v_run_shift >= 23u) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); +- goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; + } +- v_run = ((((uint32_t)(v_child)) & 3u) << v_run_shift); +- v_run_shift += 1u; +- v_i = v_block_size; +- v_j = (v_run + v_block_size); +- if (v_j > self->private_impl.f_max_incl_block_size) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); +- goto exit; ++ self->private_data.s_do_decode_frame.scratch = self->private_impl.f_padding; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (self->private_data.s_do_decode_frame.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_frame.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- v_block_size = v_j; +- v_mtft0 = ((uint32_t)(self->private_data.f_mtft[0u])); +- self->private_data.f_letter_counts[v_mtft0] += v_run; +- while (v_i < v_j) { +- self->private_data.f_bwt[v_i] = v_mtft0; +- v_i += 1u; ++ iop_a_src += self->private_data.s_do_decode_frame.scratch; ++ if ((self->private_impl.f_width > 0u) && (self->private_impl.f_height > 0u)) { ++ self->private_impl.f_dst_x = 0u; ++ if (self->private_impl.f_top_down) { ++ self->private_impl.f_dst_y = 0u; ++ self->private_impl.f_dst_y_inc = 1u; ++ } else { ++ self->private_impl.f_dst_y = ((uint32_t)(self->private_impl.f_height - 1u)); ++ self->private_impl.f_dst_y_inc = 4294967295u; ++ } ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)), ++ wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt), ++ wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ while (true) { ++ if (self->private_impl.f_compression == 0u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_status = wuffs_bmp__decoder__swizzle_none(self, a_dst, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } else if (self->private_impl.f_compression < 3u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_status = wuffs_bmp__decoder__swizzle_rle(self, a_dst, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } else if (self->private_impl.f_compression == 3u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_status = wuffs_bmp__decoder__swizzle_bitfields(self, a_dst, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } else { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_status = wuffs_bmp__decoder__swizzle_low_bit_depth(self, a_dst, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } else if (v_status.repr != wuffs_bmp__note__internal_note_short_read) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ } ++ self->private_data.s_do_decode_frame.scratch = self->private_impl.f_pending_pad; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (self->private_data.s_do_decode_frame.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_frame.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_frame.scratch; ++ self->private_impl.f_pending_pad = 0u; + } ++ self->private_impl.f_call_sequence = 96u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame = 0; ++ goto exit; + } +- self->private_impl.f_bits = v_bits; +- self->private_impl.f_n_bits = v_n_bits; +- self->private_impl.f_block_size = v_block_size; +- self->private_impl.f_decode_huffman_which = v_which; +- self->private_impl.f_decode_huffman_ticks = v_ticks; +- self->private_impl.f_decode_huffman_section = v_section; +- self->private_impl.f_decode_huffman_run_shift = v_run_shift; +- status = wuffs_base__make_status(NULL); +- goto ok; + +- ok: ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ + goto exit; + exit: + if (a_src && a_src->data.ptr) { +@@ -31895,24 +32895,27 @@ wuffs_bzip2__decoder__decode_huffman_fast( + return status; + } + +-// -------- func bzip2.decoder.decode_huffman_slow ++// -------- func bmp.decoder.swizzle_none + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_bzip2__decoder__decode_huffman_slow( +- wuffs_bzip2__decoder* self, ++wuffs_bmp__decoder__swizzle_none( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_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_node_index = 0; +- uint16_t v_child = 0; +- uint32_t v_child_ff = 0; +- uint32_t v_i = 0; +- uint32_t v_j = 0; +- uint32_t v_output = 0; +- uint32_t v_run = 0; +- uint32_t v_mtft0 = 0; ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row = 0; ++ uint32_t v_src_bytes_per_pixel = 0; ++ wuffs_base__slice_u8 v_dst_palette = {0}; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint64_t v_i = 0; ++ uint64_t v_j = 0; ++ uint64_t v_n = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -31925,99 +32928,90 @@ wuffs_bzip2__decoder__decode_huffman_slow( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_huffman_slow[0]; +- if (coro_susp_point) { +- v_node_index = self->private_data.s_decode_huffman_slow[0].v_node_index; ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ goto exit; + } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while ( ! (self->private_impl.p_decode_huffman_slow[0] != 0)) { +- if (self->private_impl.f_decode_huffman_ticks > 0u) { +- self->private_impl.f_decode_huffman_ticks -= 1u; +- } else { +- self->private_impl.f_decode_huffman_ticks = 49u; +- self->private_impl.f_decode_huffman_section += 1u; +- if (self->private_impl.f_decode_huffman_section >= self->private_impl.f_num_sections) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_number_of_sections); +- goto exit; +- } +- self->private_impl.f_decode_huffman_which = WUFFS_BZIP2__CLAMP_TO_5[(self->private_data.f_huffman_selectors[(self->private_impl.f_decode_huffman_section & 32767u)] & 7u)]; ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); ++ v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ label__outer__continue:; ++ while (true) { ++ while (self->private_impl.f_pending_pad > 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); ++ goto ok; + } +- v_node_index = 0u; +- while (true) { +- if (self->private_impl.f_n_bits <= 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- self->private_impl.f_bits = (((uint32_t)(v_c)) << 24u); +- self->private_impl.f_n_bits = 8u; +- } +- v_child = self->private_data.f_huffman_trees[self->private_impl.f_decode_huffman_which][v_node_index][(self->private_impl.f_bits >> 31u)]; +- self->private_impl.f_bits <<= 1u; +- self->private_impl.f_n_bits -= 1u; +- if (v_child < 257u) { +- v_node_index = ((uint32_t)(v_child)); +- continue; +- } else if (v_child < 768u) { +- v_child_ff = ((uint32_t)((v_child & 255u))); +- v_output = ((uint32_t)(self->private_data.f_mtft[v_child_ff])); +- wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1u + v_child_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_child_ff)); +- self->private_data.f_mtft[0u] = ((uint8_t)(v_output)); +- self->private_data.f_letter_counts[v_output] += 1u; +- self->private_data.f_bwt[self->private_impl.f_block_size] = v_output; +- if (self->private_impl.f_block_size >= self->private_impl.f_max_incl_block_size) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); +- goto exit; ++ self->private_impl.f_pending_pad -= 1u; ++ iop_a_src += 1u; ++ } ++ while (true) { ++ if (self->private_impl.f_dst_x == self->private_impl.f_width) { ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; ++ if (self->private_impl.f_dst_y >= self->private_impl.f_height) { ++ if (self->private_impl.f_height > 0u) { ++ self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row; + } +- self->private_impl.f_block_size += 1u; +- self->private_impl.f_decode_huffman_run_shift = 0u; +- break; +- } else if (v_child == 768u) { +- self->private_impl.f_decode_huffman_finished = true; + goto label__outer__break; ++ } else if (self->private_impl.f_pad_per_row != 0u) { ++ self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row; ++ goto label__outer__continue; + } +- if (self->private_impl.f_decode_huffman_run_shift >= 23u) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); ++ } ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); ++ } ++ v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); ++ if (v_i >= ((uint64_t)(v_dst.len))) { ++ if (self->private_impl.f_bits_per_pixel > 32u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); + goto exit; + } +- v_run = ((((uint32_t)(v_child)) & 3u) << self->private_impl.f_decode_huffman_run_shift); +- self->private_impl.f_decode_huffman_run_shift += 1u; +- v_i = self->private_impl.f_block_size; +- v_j = (v_run + self->private_impl.f_block_size); +- if (v_j > self->private_impl.f_max_incl_block_size) { +- status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); ++ v_src_bytes_per_pixel = (self->private_impl.f_bits_per_pixel / 8u); ++ if (v_src_bytes_per_pixel == 0u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file); + goto exit; + } +- self->private_impl.f_block_size = v_j; +- v_mtft0 = ((uint32_t)(self->private_data.f_mtft[0u])); +- self->private_data.f_letter_counts[v_mtft0] += v_run; +- while (v_i < v_j) { +- self->private_data.f_bwt[v_i] = v_mtft0; +- v_i += 1u; ++ v_n = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(v_src_bytes_per_pixel))); ++ v_n = wuffs_base__u64__min(v_n, ((uint64_t)(((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x))))); ++ v_j = v_n; ++ while (v_j >= 8u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 8u)))) { ++ iop_a_src += (v_src_bytes_per_pixel * 8u); ++ } ++ v_j -= 8u; + } +- break; ++ while (v_j > 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 1u)))) { ++ iop_a_src += (v_src_bytes_per_pixel * 1u); ++ } ++ v_j -= 1u; ++ } ++ } else { ++ v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( ++ &self->private_impl.f_swizzler, ++ wuffs_base__slice_u8__subslice_i(v_dst, v_i), ++ v_dst_palette, ++ &iop_a_src, ++ io2_a_src); ++ } ++ if (v_n == 0u) { ++ status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); ++ goto ok; + } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); + } +- label__outer__break:; +- +- goto ok; +- ok: +- self->private_impl.p_decode_huffman_slow[0] = 0; +- goto exit; + } ++ label__outer__break:; ++ status = wuffs_base__make_status(NULL); ++ goto ok; + +- goto suspend; +- suspend: +- self->private_impl.p_decode_huffman_slow[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_huffman_slow[0].v_node_index = v_node_index; +- ++ ok: + goto exit; + exit: + if (a_src && a_src->data.ptr) { +@@ -32027,256 +33021,33 @@ wuffs_bzip2__decoder__decode_huffman_slow( + return status; + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BZIP2) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR) +- +-// ---------------- Status Codes Implementations +- +-const char wuffs_cbor__error__bad_input[] = "#cbor: bad input"; +-const char wuffs_cbor__error__unsupported_recursion_depth[] = "#cbor: unsupported recursion depth"; +-const char wuffs_cbor__error__internal_error_inconsistent_i_o[] = "#cbor: internal error: inconsistent I/O"; +-const char wuffs_cbor__error__internal_error_inconsistent_token_length[] = "#cbor: internal error: inconsistent token length"; +- +-// ---------------- Private Consts +- +-static const uint32_t +-WUFFS_CBOR__LITERALS[4] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 8388612, 8388616, 8388610, 8388609, +-}; +- +-static const uint8_t +-WUFFS_CBOR__TOKEN_LENGTHS[32] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 1, 1, 1, 1, 1, 1, 1, 1, +- 1, 1, 1, 1, 1, 1, 1, 1, +- 1, 1, 1, 1, 1, 1, 1, 1, +- 2, 3, 5, 9, 0, 0, 0, 1, +-}; +- +-// ---------------- Private Initializer Prototypes +- +-// ---------------- Private Function Prototypes +- +-// ---------------- VTables +- +-const wuffs_base__token_decoder__func_ptrs +-wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__token_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__slice_u8))(&wuffs_cbor__decoder__decode_tokens), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_cbor__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_cbor__decoder__history_retain_length), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_cbor__decoder__set_quirk), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_cbor__decoder__workbuf_len), +-}; +- +-// ---------------- Initializer Implementations +- +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_cbor__decoder__initialize( +- wuffs_cbor__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); +- } +- +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); +- } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); +- } +- } +- +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name = +- wuffs_base__token_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers = +- (const void*)(&wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder); +- return wuffs_base__make_status(NULL); +-} +- +-wuffs_cbor__decoder* +-wuffs_cbor__decoder__alloc(void) { +- wuffs_cbor__decoder* x = +- (wuffs_cbor__decoder*)(calloc(sizeof(wuffs_cbor__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_cbor__decoder__initialize( +- x, sizeof(wuffs_cbor__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; +- } +- return x; +-} +- +-size_t +-sizeof__wuffs_cbor__decoder(void) { +- return sizeof(wuffs_cbor__decoder); +-} +- +-// ---------------- Function Implementations +- +-// -------- func cbor.decoder.get_quirk +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_cbor__decoder__get_quirk( +- const wuffs_cbor__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func cbor.decoder.set_quirk +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_cbor__decoder__set_quirk( +- wuffs_cbor__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); +-} +- +-// -------- func cbor.decoder.history_retain_length +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_cbor__decoder__history_retain_length( +- const wuffs_cbor__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func cbor.decoder.workbuf_len +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_cbor__decoder__workbuf_len( +- const wuffs_cbor__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- +- return wuffs_base__utility__empty_range_ii_u64(); +-} +- +-// -------- func cbor.decoder.decode_tokens ++// -------- func bmp.decoder.swizzle_rle + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_cbor__decoder__decode_tokens( +- wuffs_cbor__decoder* self, +- wuffs_base__token_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; ++static wuffs_base__status ++wuffs_bmp__decoder__swizzle_rle( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint64_t v_string_length = 0; +- uint64_t v_n64 = 0; +- uint32_t v_depth = 0; +- uint32_t v_stack_byte = 0; +- uint32_t v_stack_bit = 0; +- uint32_t v_stack_val = 0; +- uint32_t v_token_length = 0; +- uint32_t v_vminor = 0; +- uint32_t v_vminor_alt = 0; +- uint32_t v_continued = 0; +- uint8_t v_c = 0; +- uint8_t v_c_major = 0; +- uint8_t v_c_minor = 0; +- bool v_tagged = false; +- uint8_t v_indefinite_string_major_type = 0; ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row = 0; ++ wuffs_base__slice_u8 v_dst_palette = {0}; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_row = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint64_t v_i = 0; ++ uint64_t v_n = 0; ++ uint32_t v_p0 = 0; ++ uint8_t v_code = 0; ++ uint8_t v_indexes[2] = {0}; ++ uint32_t v_rle_state = 0; ++ uint32_t v_chunk_bits = 0; ++ uint32_t v_chunk_count = 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 && a_dst->data.ptr) { +- 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; +- } +- } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -32288,1231 +33059,590 @@ wuffs_cbor__decoder__decode_tokens( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_tokens[0]; +- if (coro_susp_point) { +- v_string_length = self->private_data.s_decode_tokens[0].v_string_length; +- v_depth = self->private_data.s_decode_tokens[0].v_depth; +- v_tagged = self->private_data.s_decode_tokens[0].v_tagged; +- v_indefinite_string_major_type = self->private_data.s_decode_tokens[0].v_indefinite_string_major_type; ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ goto exit; + } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- if (self->private_impl.f_end_of_data) { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); ++ v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ v_rle_state = self->private_impl.f_rle_state; ++ label__outer__continue:; ++ while (true) { ++ v_row = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) { ++ v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row); + } +- label__outer__continue:; ++ label__middle__continue:; + while (true) { ++ v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); ++ if (v_i <= ((uint64_t)(v_row.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_row, v_i); ++ } else { ++ v_dst = wuffs_base__utility__empty_slice_u8(); ++ } + while (true) { +- do { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- goto label__outer__continue; ++ if (v_rle_state == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { ++ break; + } +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_cbor__error__bad_input); ++ v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ if (v_code == 0u) { ++ v_rle_state = 2u; ++ continue; ++ } ++ self->private_impl.f_rle_length = ((uint32_t)(v_code)); ++ v_rle_state = 1u; ++ continue; ++ } else if (v_rle_state == 1u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { ++ break; ++ } ++ v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ if (self->private_impl.f_bits_per_pixel == 8u) { ++ v_p0 = 0u; ++ while (v_p0 < self->private_impl.f_rle_length) { ++ self->private_data.f_scratch[v_p0] = v_code; ++ v_p0 += 1u; ++ } ++ } else { ++ v_indexes[0u] = ((uint8_t)(((uint8_t)(v_code >> 4u)))); ++ v_indexes[1u] = ((uint8_t)(v_code & 15u)); ++ v_p0 = 0u; ++ while (v_p0 < self->private_impl.f_rle_length) { ++ self->private_data.f_scratch[(v_p0 + 0u)] = v_indexes[0u]; ++ self->private_data.f_scratch[(v_p0 + 1u)] = v_indexes[1u]; ++ v_p0 += 2u; ++ } ++ } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_rle_length)); ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, self->private_impl.f_rle_length); ++ v_rle_state = 0u; ++ goto label__middle__continue; ++ } else if (v_rle_state == 2u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { ++ break; ++ } ++ v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ if (v_code < 2u) { ++ if ((self->private_impl.f_dst_y >= self->private_impl.f_height) && (v_code == 0u)) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression); + goto exit; + } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_dst, v_dst_palette, 18446744073709551615u); ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; ++ if (v_code > 0u) { ++ goto label__outer__break; ++ } ++ v_rle_state = 0u; + goto label__outer__continue; ++ } else if (v_code == 2u) { ++ v_rle_state = 4u; ++ continue; + } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if ((v_indefinite_string_major_type != 0u) && (v_indefinite_string_major_type != (v_c >> 5u))) { +- if (v_c != 255u) { +- status = wuffs_base__make_status(wuffs_cbor__error__bad_input); +- goto exit; ++ self->private_impl.f_rle_length = ((uint32_t)(v_code)); ++ self->private_impl.f_rle_padded = ((self->private_impl.f_bits_per_pixel == 8u) && (((uint8_t)(v_code & 1u)) != 0u)); ++ v_rle_state = 3u; ++ continue; ++ } else if (v_rle_state == 3u) { ++ if (self->private_impl.f_bits_per_pixel == 8u) { ++ v_n = wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader( ++ &self->private_impl.f_swizzler, ++ self->private_impl.f_rle_length, ++ v_dst, ++ v_dst_palette, ++ &iop_a_src, ++ io2_a_src); ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_rle_length, ((uint32_t)(v_n))); ++ } else { ++ v_chunk_count = ((self->private_impl.f_rle_length + 3u) / 4u); ++ v_p0 = 0u; ++ while ((v_chunk_count > 0u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 2u)) { ++ v_chunk_bits = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2u; ++ self->private_data.f_scratch[(v_p0 + 0u)] = ((uint8_t)((15u & (v_chunk_bits >> 12u)))); ++ self->private_data.f_scratch[(v_p0 + 1u)] = ((uint8_t)((15u & (v_chunk_bits >> 8u)))); ++ self->private_data.f_scratch[(v_p0 + 2u)] = ((uint8_t)((15u & (v_chunk_bits >> 4u)))); ++ self->private_data.f_scratch[(v_p0 + 3u)] = ((uint8_t)((15u & (v_chunk_bits >> 0u)))); ++ v_p0 = ((v_p0 & 255u) + 4u); ++ v_chunk_count -= 1u; + } +- v_vminor = 4194560u; +- if (v_indefinite_string_major_type == 3u) { +- v_vminor |= 19u; ++ v_p0 = wuffs_base__u32__min(v_p0, self->private_impl.f_rle_length); ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, v_p0)); ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, v_p0); ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_rle_length, v_p0); ++ } ++ if (self->private_impl.f_rle_length > 0u) { ++ break; ++ } ++ if (self->private_impl.f_rle_padded) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { ++ break; + } +- v_indefinite_string_major_type = 0u; + iop_a_src += 1u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; ++ self->private_impl.f_rle_padded = false; ++ } ++ v_rle_state = 0u; ++ goto label__middle__continue; ++ } else if (v_rle_state == 4u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { ++ break; + } ++ self->private_impl.f_rle_delta_x = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); + iop_a_src += 1u; +- v_c_major = ((uint8_t)((v_c >> 5u))); +- v_c_minor = (v_c & 31u); +- if (v_c_minor < 24u) { +- v_string_length = ((uint64_t)(v_c_minor)); +- } else { +- while (true) { +- if (v_c_minor == 24u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= 1u) { +- v_string_length = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))); +- iop_a_src += 1u; +- break; +- } +- } else if (v_c_minor == 25u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= 2u) { +- v_string_length = ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); +- iop_a_src += 2u; +- break; +- } +- } else if (v_c_minor == 26u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= 4u) { +- v_string_length = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4u; +- break; +- } +- } else if (v_c_minor == 27u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= 8u) { +- v_string_length = wuffs_base__peek_u64be__no_bounds_check(iop_a_src); +- iop_a_src += 8u; +- break; +- } +- } else { +- v_string_length = 0u; +- break; +- } +- if (iop_a_src > io1_a_src) { +- iop_a_src--; +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_cbor__error__bad_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- goto label__outer__continue; +- } +- status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o); +- goto exit; +- } ++ v_rle_state = 5u; ++ continue; ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 1u) { ++ break; ++ } ++ v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ if (self->private_impl.f_rle_delta_x > 0u) { ++ wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_dst, v_dst_palette, ((uint64_t)(self->private_impl.f_rle_delta_x))); ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(self->private_impl.f_rle_delta_x))); ++ self->private_impl.f_rle_delta_x = 0u; ++ if (self->private_impl.f_dst_x > self->private_impl.f_width) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression); ++ goto exit; + } +- if (v_c_major == 0u) { +- if (v_c_minor < 26u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((14680064u | ((uint32_t)((v_string_length & 65535u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } else if (v_c_minor < 28u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((14680064u | ((uint32_t)((v_string_length >> 46u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- *iop_a_dst++ = wuffs_base__make_token( +- (~(v_string_length & 70368744177663u) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } +- } else if (v_c_major == 1u) { +- if (v_c_minor < 26u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((12582912u | (2097151u - ((uint32_t)((v_string_length & 65535u))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } else if (v_c_minor < 28u) { +- if (v_string_length < 9223372036854775808u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((12582912u | (2097151u - ((uint32_t)((v_string_length >> 46u))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- *iop_a_dst++ = wuffs_base__make_token( +- (~((18446744073709551615u - v_string_length) & 70368744177663u) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } else { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | +- (((uint64_t)(16777216u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(9u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } +- goto label__goto_parsed_a_leaf_value__break; +- } +- } else if (v_c_major == 2u) { +- if (v_c_minor < 28u) { +- if (v_string_length == 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194560u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194560u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } else if (v_c_minor == 31u) { +- if (v_indefinite_string_major_type != 0u) { +- break; +- } +- v_indefinite_string_major_type = 2u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194560u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__outer__continue; +- } else { +- break; +- } +- while (true) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); +- continue; +- } +- v_n64 = wuffs_base__u64__min(v_string_length, ((uint64_t)(io2_a_src - iop_a_src))); +- v_token_length = ((uint32_t)((v_n64 & 65535u))); +- if (v_n64 > 65535u) { +- v_token_length = 65535u; +- } else if (v_token_length <= 0u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_cbor__error__bad_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); +- continue; +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) { +- status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length); +- goto exit; +- } +- v_string_length -= ((uint64_t)(v_token_length)); +- v_continued = 0u; +- if ((v_string_length > 0u) || (v_indefinite_string_major_type > 0u)) { +- v_continued = 1u; +- } +- iop_a_src += v_token_length; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194816u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (v_string_length > 0u) { +- continue; +- } else if (v_indefinite_string_major_type > 0u) { +- goto label__outer__continue; +- } +- goto label__goto_parsed_a_leaf_value__break; +- } +- } else if (v_c_major == 3u) { +- if (v_c_minor < 28u) { +- if (v_string_length == 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } else if (v_c_minor == 31u) { +- if (v_indefinite_string_major_type != 0u) { +- break; +- } +- v_indefinite_string_major_type = 3u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__outer__continue; +- } else { +- break; +- } +- while (true) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); +- continue; +- } +- v_n64 = wuffs_base__u64__min(v_string_length, 65535u); +- v_n64 = ((uint64_t)(wuffs_base__utf_8__longest_valid_prefix(iop_a_src, +- ((size_t)(wuffs_base__u64__min(((uint64_t)(io2_a_src - iop_a_src)), v_n64)))))); +- v_token_length = ((uint32_t)((v_n64 & 65535u))); +- if (v_token_length <= 0u) { +- if ((a_src && a_src->meta.closed) || (((uint64_t)(io2_a_src - iop_a_src)) >= 4u)) { +- status = wuffs_base__make_status(wuffs_cbor__error__bad_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); +- continue; +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) { +- status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length); +- goto exit; +- } +- v_string_length -= ((uint64_t)(v_token_length)); +- v_continued = 0u; +- if ((v_string_length > 0u) || (v_indefinite_string_major_type > 0u)) { +- v_continued = 1u; +- } +- iop_a_src += v_token_length; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (v_string_length > 0u) { +- continue; +- } else if (v_indefinite_string_major_type > 0u) { +- goto label__outer__continue; +- } +- goto label__goto_parsed_a_leaf_value__break; +- } +- } else if (v_c_major == 4u) { +- if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0u) { +- break; +- } else if (v_depth >= 1024u) { +- v_token_length = ((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])); +- while ((v_token_length > 0u) && (iop_a_src > io1_a_src)) { +- iop_a_src--; +- v_token_length -= 1u; +- } +- status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth); +- goto exit; +- } +- v_vminor = 2105361u; +- v_vminor_alt = 2101282u; +- if (v_depth > 0u) { +- v_stack_byte = ((v_depth - 1u) / 16u); +- v_stack_bit = (((v_depth - 1u) & 15u) * 2u); +- if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { +- v_vminor = 2105377u; +- v_vminor_alt = 2105378u; +- } else { +- v_vminor = 2105409u; +- v_vminor_alt = 2113570u; +- } +- } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (v_c_minor == 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } +- v_stack_byte = (v_depth / 16u); +- v_stack_bit = ((v_depth & 15u) * 2u); +- self->private_data.f_stack[v_stack_byte] &= (4294967295u ^ (((uint32_t)(3u)) << v_stack_bit)); +- self->private_data.f_container_num_remaining[v_depth] = v_string_length; +- v_depth += 1u; +- v_tagged = false; +- goto label__outer__continue; +- } else if (v_c_major == 5u) { +- if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0u) { +- break; +- } else if (v_depth >= 1024u) { +- v_token_length = ((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])); +- while ((v_token_length > 0u) && (iop_a_src > io1_a_src)) { +- iop_a_src--; +- v_token_length -= 1u; +- } +- status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth); ++ } ++ if (v_code > 0u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_code -= 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ while (true) { ++ self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; ++ if (self->private_impl.f_dst_y >= self->private_impl.f_height) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression); + goto exit; + } +- v_vminor = 2113553u; +- v_vminor_alt = 2101314u; +- if (v_depth > 0u) { +- v_stack_byte = ((v_depth - 1u) / 16u); +- v_stack_bit = (((v_depth - 1u) & 15u) * 2u); +- if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { +- v_vminor = 2113569u; +- v_vminor_alt = 2105410u; +- } else { +- v_vminor = 2113601u; +- v_vminor_alt = 2113602u; +- } +- } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (v_c_minor == 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; ++ v_row = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) { ++ v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row); + } +- v_stack_byte = (v_depth / 16u); +- v_stack_bit = ((v_depth & 15u) * 2u); +- self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(3u)) << v_stack_bit); +- self->private_data.f_container_num_remaining[v_depth] = v_string_length; +- v_depth += 1u; +- v_tagged = false; +- goto label__outer__continue; +- } else if (v_c_major == 6u) { +- if (v_c_minor >= 28u) { ++ if (v_code <= 0u) { ++ wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, ((uint64_t)(self->private_impl.f_dst_x))); + break; + } +- if (v_string_length < 262144u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | +- (((uint64_t)((4194304u | ((uint32_t)(v_string_length))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } else { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | +- (((uint64_t)((4194304u | ((uint32_t)((v_string_length >> 46u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- *iop_a_dst++ = wuffs_base__make_token( +- (~(v_string_length & 70368744177663u) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } +- v_tagged = true; +- goto label__outer__continue; +- } else if (v_c_major == 7u) { +- if (v_c_minor < 20u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | +- (((uint64_t)((8388608u | ((uint32_t)((v_string_length & 255u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } else if (v_c_minor < 24u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(WUFFS_CBOR__LITERALS[(v_c_minor & 3u)])) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } else if (v_c_minor == 24u) { +- if (v_string_length < 24u) { +- if ( ! (iop_a_src > io1_a_src)) { +- status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- iop_a_src--; +- break; +- } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | +- (((uint64_t)((8388608u | ((uint32_t)((v_string_length & 255u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } else if (v_c_minor < 28u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(10490113u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } else if (v_c_minor == 31u) { +- if (v_tagged || (v_depth <= 0u)) { +- break; +- } +- v_depth -= 1u; +- if (self->private_data.f_container_num_remaining[v_depth] != 0u) { +- break; +- } +- v_stack_byte = (v_depth / 16u); +- v_stack_bit = ((v_depth & 15u) * 2u); +- v_stack_val = (3u & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit)); +- if (v_stack_val == 1u) { +- break; +- } +- if (v_stack_val != 3u) { +- v_vminor_alt = 2097186u; +- } else { +- v_vminor_alt = 2097218u; +- } +- if (v_depth <= 0u) { +- v_vminor_alt |= 4096u; +- } else { +- v_stack_byte = ((v_depth - 1u) / 16u); +- v_stack_bit = (((v_depth - 1u) & 15u) * 2u); +- if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { +- v_vminor_alt |= 8192u; +- } else { +- v_vminor_alt |= 16384u; +- } +- } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__goto_parsed_a_leaf_value__break; +- } +- } +- } while (0); +- if (iop_a_src > io1_a_src) { +- iop_a_src--; +- status = wuffs_base__make_status(wuffs_cbor__error__bad_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- label__goto_parsed_a_leaf_value__break:; +- v_tagged = false; +- while (v_depth > 0u) { +- v_stack_byte = ((v_depth - 1u) / 16u); +- v_stack_bit = (((v_depth - 1u) & 15u) * 2u); +- self->private_data.f_stack[v_stack_byte] ^= (((uint32_t)(1u)) << (v_stack_bit + 1u)); +- if (1u == (3u & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit))) { +- goto label__outer__continue; +- } +- if (self->private_data.f_container_num_remaining[(v_depth - 1u)] <= 0u) { +- goto label__outer__continue; +- } +- self->private_data.f_container_num_remaining[(v_depth - 1u)] -= 1u; +- if (self->private_data.f_container_num_remaining[(v_depth - 1u)] > 0u) { +- goto label__outer__continue; +- } +- while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); +- continue; +- } +- v_depth -= 1u; +- v_stack_byte = (v_depth / 16u); +- v_stack_bit = ((v_depth & 15u) * 2u); +- if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { +- v_vminor_alt = 2097186u; +- } else { +- v_vminor_alt = 2097218u; +- } +- if (v_depth <= 0u) { +- v_vminor_alt |= 4096u; +- } else { +- v_stack_byte = ((v_depth - 1u) / 16u); +- v_stack_bit = (((v_depth - 1u) & 15u) * 2u); +- if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { +- v_vminor_alt |= 8192u; +- } else { +- v_vminor_alt |= 16384u; ++ wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, 18446744073709551615u); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_code -= 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif + } + } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_rle_state = 0u; ++ goto label__middle__continue; + } +- break; ++ self->private_impl.f_rle_state = v_rle_state; ++ status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); ++ goto ok; + } +- self->private_impl.f_end_of_data = true; +- +- ok: +- self->private_impl.p_decode_tokens[0] = 0; +- goto exit; + } ++ label__outer__break:; ++ while (self->private_impl.f_dst_y < self->private_impl.f_height) { ++ v_row = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) { ++ v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row); ++ } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, 18446744073709551615u); ++ self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; ++ } ++ status = wuffs_base__make_status(NULL); ++ goto ok; + +- goto suspend; +- suspend: +- self->private_impl.p_decode_tokens[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; +- self->private_data.s_decode_tokens[0].v_string_length = v_string_length; +- self->private_data.s_decode_tokens[0].v_depth = v_depth; +- self->private_data.s_decode_tokens[0].v_tagged = v_tagged; +- self->private_data.s_decode_tokens[0].v_indefinite_string_major_type = v_indefinite_string_major_type; +- ++ ok: + goto exit; + exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } + return status; + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32) ++// -------- func bmp.decoder.swizzle_bitfields + +-// ---------------- Status Codes Implementations ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bmp__decoder__swizzle_bitfields( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-// ---------------- Private Consts ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row = 0; ++ wuffs_base__slice_u8 v_dst_palette = {0}; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint64_t v_i = 0; ++ uint64_t v_n = 0; ++ uint32_t v_p0 = 0; ++ uint32_t v_p1 = 0; ++ uint32_t v_p1_temp = 0; ++ uint32_t v_num_bits = 0; ++ uint32_t v_c = 0; ++ uint32_t v_c32 = 0; ++ uint32_t v_channel = 0; + +-static const uint32_t +-WUFFS_CRC32__IEEE_TABLE[16][256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- { +- 0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, +- 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, +- 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, +- 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, +- 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, +- 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, +- 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, +- 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, +- 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, +- 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, +- 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223, +- 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, +- 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, +- 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, +- 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, +- 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989, +- 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, +- 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, +- 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, +- 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, +- 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, +- 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161, +- 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, +- 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, +- 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, +- 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, +- 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567, +- 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, +- 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, +- 2932959818, 3654703836, 1088359270, 936918000, 2847714899, 3736837829, 1202900863, 817233897, +- 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, +- 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117, +- }, { +- 0, 421212481, 842424962, 724390851, 1684849924, 2105013317, 1448781702, 1329698503, +- 3369699848, 3519200073, 4210026634, 3824474571, 2897563404, 3048111693, 2659397006, 2274893007, +- 1254232657, 1406739216, 2029285587, 1643069842, 783210325, 934667796, 479770071, 92505238, +- 2182846553, 2600511768, 2955803355, 2838940570, 3866582365, 4285295644, 3561045983, 3445231262, +- 2508465314, 2359236067, 2813478432, 3198777185, 4058571174, 3908292839, 3286139684, 3670389349, +- 1566420650, 1145479147, 1869335592, 1987116393, 959540142, 539646703, 185010476, 303839341, +- 3745920755, 3327985586, 3983561841, 4100678960, 3140154359, 2721170102, 2300350837, 2416418868, +- 396344571, 243568058, 631889529, 1018359608, 1945336319, 1793607870, 1103436669, 1490954812, +- 4034481925, 3915546180, 3259968903, 3679722694, 2484439553, 2366552896, 2787371139, 3208174018, +- 950060301, 565965900, 177645455, 328046286, 1556873225, 1171730760, 1861902987, 2011255754, +- 3132841300, 2745199637, 2290958294, 2442530455, 3738671184, 3352078609, 3974232786, 4126854035, +- 1919080284, 1803150877, 1079293406, 1498383519, 370020952, 253043481, 607678682, 1025720731, +- 1711106983, 2095471334, 1472923941, 1322268772, 26324643, 411738082, 866634785, 717028704, +- 2904875439, 3024081134, 2668790573, 2248782444, 3376948395, 3495106026, 4219356713, 3798300520, +- 792689142, 908347575, 487136116, 68299317, 1263779058, 1380486579, 2036719216, 1618931505, +- 3890672638, 4278043327, 3587215740, 3435896893, 2206873338, 2593195963, 2981909624, 2829542713, +- 998479947, 580430090, 162921161, 279890824, 1609522511, 1190423566, 1842954189, 1958874764, +- 4082766403, 3930137346, 3245109441, 3631694208, 2536953671, 2385372678, 2768287173, 3155920004, +- 1900120602, 1750776667, 1131931800, 1517083097, 355290910, 204897887, 656092572, 1040194781, +- 3113746450, 2692952403, 2343461520, 2461357009, 3723805974, 3304059991, 4022511508, 4141455061, +- 2919742697, 3072101800, 2620513899, 2234183466, 3396041197, 3547351212, 4166851439, 3779471918, +- 1725839073, 2143618976, 1424512099, 1307796770, 45282277, 464110244, 813994343, 698327078, +- 3838160568, 4259225593, 3606301754, 3488152955, 2158586812, 2578602749, 2996767038, 2877569151, +- 740041904, 889656817, 506086962, 120682355, 1215357364, 1366020341, 2051441462, 1667084919, +- 3422213966, 3538019855, 4190942668, 3772220557, 2945847882, 3062702859, 2644537544, 2226864521, +- 52649286, 439905287, 823476164, 672009861, 1733269570, 2119477507, 1434057408, 1281543041, +- 2167981343, 2552493150, 3004082077, 2853541596, 3847487515, 4233048410, 3613549209, 3464057816, +- 1239502615, 1358593622, 2077699477, 1657543892, 764250643, 882293586, 532408465, 111204816, +- 1585378284, 1197851309, 1816695150, 1968414767, 974272232, 587794345, 136598634, 289367339, +- 2527558116, 2411481253, 2760973158, 3179948583, 4073438432, 3956313505, 3237863010, 3655790371, +- 347922877, 229101820, 646611775, 1066513022, 1892689081, 1774917112, 1122387515, 1543337850, +- 3697634229, 3313392372, 3998419255, 4148705398, 3087642289, 2702352368, 2319436851, 2468674930, +- }, { +- 0, 29518391, 59036782, 38190681, 118073564, 114017003, 76381362, 89069189, +- 236147128, 265370511, 228034006, 206958561, 152762724, 148411219, 178138378, 190596925, +- 472294256, 501532999, 530741022, 509615401, 456068012, 451764635, 413917122, 426358261, +- 305525448, 334993663, 296822438, 275991697, 356276756, 352202787, 381193850, 393929805, +- 944588512, 965684439, 1003065998, 973863097, 1061482044, 1049003019, 1019230802, 1023561829, +- 912136024, 933002607, 903529270, 874031361, 827834244, 815125939, 852716522, 856752605, +- 611050896, 631869351, 669987326, 640506825, 593644876, 580921211, 551983394, 556069653, +- 712553512, 733666847, 704405574, 675154545, 762387700, 749958851, 787859610, 792175277, +- 1889177024, 1901651959, 1931368878, 1927033753, 2006131996, 1985040171, 1947726194, 1976933189, +- 2122964088, 2135668303, 2098006038, 2093965857, 2038461604, 2017599123, 2047123658, 2076625661, +- 1824272048, 1836991623, 1866005214, 1861914857, 1807058540, 1786244187, 1748062722, 1777547317, +- 1655668488, 1668093247, 1630251878, 1625932113, 1705433044, 1684323811, 1713505210, 1742760333, +- 1222101792, 1226154263, 1263738702, 1251046777, 1339974652, 1310460363, 1281013650, 1301863845, +- 1187289752, 1191637167, 1161842422, 1149379777, 1103966788, 1074747507, 1112139306, 1133218845, +- 1425107024, 1429406311, 1467333694, 1454888457, 1408811148, 1379576507, 1350309090, 1371438805, +- 1524775400, 1528845279, 1499917702, 1487177649, 1575719220, 1546255107, 1584350554, 1605185389, +- 3778354048, 3774312887, 3803303918, 3816007129, 3862737756, 3892238699, 3854067506, 3833203973, +- 4012263992, 4007927823, 3970080342, 3982554209, 3895452388, 3924658387, 3953866378, 3932773565, +- 4245928176, 4241609415, 4271336606, 4283762345, 4196012076, 4225268251, 4187931714, 4166823541, +- 4076923208, 4072833919, 4035198246, 4047918865, 4094247316, 4123732899, 4153251322, 4132437965, +- 3648544096, 3636082519, 3673983246, 3678331705, 3732010428, 3753090955, 3723829714, 3694611429, +- 3614117080, 3601426159, 3572488374, 3576541825, 3496125444, 3516976691, 3555094634, 3525581405, +- 3311336976, 3298595879, 3336186494, 3340255305, 3260503756, 3281337595, 3251864226, 3222399125, +- 3410866088, 3398419871, 3368647622, 3372945905, 3427010420, 3448139075, 3485520666, 3456284973, +- 2444203584, 2423127159, 2452308526, 2481530905, 2527477404, 2539934891, 2502093554, 2497740997, +- 2679949304, 2659102159, 2620920726, 2650438049, 2562027300, 2574714131, 2603727690, 2599670141, +- 2374579504, 2353749767, 2383274334, 2412743529, 2323684844, 2336421851, 2298759554, 2294686645, +- 2207933576, 2186809023, 2149495014, 2178734801, 2224278612, 2236720739, 2266437690, 2262135309, +- 2850214048, 2820717207, 2858812622, 2879680249, 2934667388, 2938704459, 2909776914, 2897069605, +- 2817622296, 2788420399, 2759153014, 2780249921, 2700618180, 2704950259, 2742877610, 2730399645, +- 3049550800, 3020298727, 3057690558, 3078802825, 2999835404, 3004150075, 2974355298, 2961925461, +- 3151438440, 3121956959, 3092510214, 3113327665, 3168701108, 3172786307, 3210370778, 3197646061, +- }, { +- 0, 3099354981, 2852767883, 313896942, 2405603159, 937357362, 627793884, 2648127673, +- 3316918511, 2097696650, 1874714724, 3607201537, 1255587768, 4067088605, 3772741427, 1482887254, +- 1343838111, 3903140090, 4195393300, 1118632049, 3749429448, 1741137837, 1970407491, 3452858150, +- 2511175536, 756094997, 1067759611, 2266550430, 449832999, 2725482306, 2965774508, 142231497, +- 2687676222, 412010587, 171665333, 2995192016, 793786473, 2548850444, 2237264098, 1038456711, +- 1703315409, 3711623348, 3482275674, 1999841343, 3940814982, 1381529571, 1089329165, 4166106984, +- 4029413537, 1217896388, 1512189994, 3802027855, 2135519222, 3354724499, 3577784189, 1845280792, +- 899665998, 2367928107, 2677414085, 657096608, 3137160985, 37822588, 284462994, 2823350519, +- 2601801789, 598228824, 824021174, 2309093331, 343330666, 2898962447, 3195996129, 113467524, +- 1587572946, 3860600759, 4104763481, 1276501820, 3519211397, 1769898208, 2076913422, 3279374443, +- 3406630818, 1941006535, 1627703081, 3652755532, 1148164341, 4241751952, 3999682686, 1457141531, +- 247015245, 3053797416, 2763059142, 470583459, 2178658330, 963106687, 735213713, 2473467892, +- 992409347, 2207944806, 2435792776, 697522413, 3024379988, 217581361, 508405983, 2800865210, +- 4271038444, 1177467017, 1419450215, 3962007554, 1911572667, 3377213406, 3690561584, 1665525589, +- 1799331996, 3548628985, 3241568279, 2039091058, 3831314379, 1558270126, 1314193216, 4142438437, +- 2928380019, 372764438, 75645176, 3158189981, 568925988, 2572515393, 2346768303, 861712586, +- 3982079547, 1441124702, 1196457648, 4293663189, 1648042348, 3666298377, 3358779879, 1888390786, +- 686661332, 2421291441, 2196002399, 978858298, 2811169155, 523464422, 226935048, 3040519789, +- 3175145892, 100435649, 390670639, 2952089162, 841119475, 2325614998, 2553003640, 546822429, +- 2029308235, 3225988654, 3539796416, 1782671013, 4153826844, 1328167289, 1570739863, 3844338162, +- 1298864389, 4124540512, 3882013070, 1608431339, 3255406162, 2058742071, 1744848601, 3501990332, +- 2296328682, 811816591, 584513889, 2590678532, 129869501, 3204563416, 2914283062, 352848211, +- 494030490, 2781751807, 3078325777, 264757620, 2450577869, 715964072, 941166918, 2158327331, +- 3636881013, 1618608400, 1926213374, 3396585883, 1470427426, 4011365959, 4255988137, 1158766284, +- 1984818694, 3471935843, 3695453837, 1693991400, 4180638033, 1100160564, 1395044826, 3952793279, +- 3019491049, 189112716, 435162722, 2706139399, 1016811966, 2217162459, 2526189877, 774831696, +- 643086745, 2666061564, 2354934034, 887166583, 2838900430, 294275499, 54519365, 3145957664, +- 3823145334, 1532818963, 1240029693, 4048895640, 1820460577, 3560857924, 3331051178, 2117577167, +- 3598663992, 1858283101, 2088143283, 3301633750, 1495127663, 3785470218, 4078182116, 1269332353, +- 332098007, 2876706482, 3116540252, 25085497, 2628386432, 605395429, 916469259, 2384220526, +- 2254837415, 1054503362, 745528876, 2496903497, 151290352, 2981684885, 2735556987, 464596510, +- 1137851976, 4218313005, 3923506883, 1365741990, 3434129695, 1946996346, 1723425172, 3724871409, +- }, { +- 0, 1029712304, 2059424608, 1201699536, 4118849216, 3370159984, 2403399072, 2988497936, +- 812665793, 219177585, 1253054625, 2010132753, 3320900865, 4170237105, 3207642721, 2186319825, +- 1625331586, 1568718386, 438355170, 658566482, 2506109250, 2818578674, 4020265506, 3535817618, +- 1351670851, 1844508147, 709922595, 389064339, 2769320579, 2557498163, 3754961379, 3803185235, +- 3250663172, 4238411444, 3137436772, 2254525908, 876710340, 153198708, 1317132964, 1944187668, +- 4054934725, 3436268917, 2339452837, 3054575125, 70369797, 961670069, 2129760613, 1133623509, +- 2703341702, 2621542710, 3689016294, 3867263574, 1419845190, 1774270454, 778128678, 318858390, +- 2438067015, 2888948471, 3952189479, 3606153623, 1691440519, 1504803895, 504432359, 594620247, +- 1492342857, 1704161785, 573770537, 525542041, 2910060169, 2417219385, 3618876905, 3939730521, +- 1753420680, 1440954936, 306397416, 790849880, 2634265928, 2690882808, 3888375336, 3668168600, +- 940822475, 91481723, 1121164459, 2142483739, 3448989963, 4042473659, 3075684971, 2318603227, +- 140739594, 889433530, 1923340138, 1338244826, 4259521226, 3229813626, 2267247018, 3124975642, +- 2570221389, 2756861693, 3824297005, 3734113693, 1823658381, 1372780605, 376603373, 722643805, +- 2839690380, 2485261628, 3548540908, 4007806556, 1556257356, 1638052860, 637716780, 459464860, +- 4191346895, 3300051327, 2199040943, 3195181599, 206718479, 825388991, 1989285231, 1274166495, +- 3382881038, 4106388158, 3009607790, 2382549470, 1008864718, 21111934, 1189240494, 2072147742, +- 2984685714, 2357631266, 3408323570, 4131834434, 1147541074, 2030452706, 1051084082, 63335554, +- 2174155603, 3170292451, 4216760371, 3325460867, 1947622803, 1232499747, 248909555, 867575619, +- 3506841360, 3966111392, 2881909872, 2527485376, 612794832, 434546784, 1581699760, 1663499008, +- 3782634705, 3692447073, 2612412337, 2799048193, 351717905, 697754529, 1849071985, 1398190273, +- 1881644950, 1296545318, 182963446, 931652934, 2242328918, 3100053734, 4284967478, 3255255942, +- 1079497815, 2100821479, 983009079, 133672583, 3050795671, 2293717799, 3474399735, 4067887175, +- 281479188, 765927844, 1778867060, 1466397380, 3846680276, 3626469220, 2676489652, 2733102084, +- 548881365, 500656741, 1517752501, 1729575173, 3577210133, 3898068133, 2952246901, 2459410373, +- 3910527195, 3564487019, 2480257979, 2931134987, 479546907, 569730987, 1716854139, 1530213579, +- 3647316762, 3825568426, 2745561210, 2663766474, 753206746, 293940330, 1445287610, 1799716618, +- 2314567513, 3029685993, 4080348217, 3461678473, 2088098201, 1091956777, 112560889, 1003856713, +- 3112514712, 2229607720, 3276105720, 4263857736, 1275433560, 1902492648, 918929720, 195422344, +- 685033439, 364179055, 1377080511, 1869921551, 3713294623, 3761522863, 2811507327, 2599689167, +- 413436958, 633644462, 1650777982, 1594160846, 3978570462, 3494118254, 2548332990, 2860797966, +- 1211387997, 1968470509, 854852413, 261368461, 3182753437, 2161434413, 3346310653, 4195650637, +- 2017729436, 1160000044, 42223868, 1071931724, 2378480988, 2963576044, 4144295484, 3395602316, +- }, { +- 0, 3411858341, 1304994059, 2257875630, 2609988118, 1355649459, 3596215069, 486879416, +- 3964895853, 655315400, 2711298918, 1791488195, 2009251963, 3164476382, 973758832, 4048990933, +- 64357019, 3364540734, 1310630800, 2235723829, 2554806413, 1394316072, 3582976390, 517157411, +- 4018503926, 618222419, 2722963965, 1762783832, 1947517664, 3209171269, 970744811, 4068520014, +- 128714038, 3438335635, 1248109629, 2167961496, 2621261600, 1466012805, 3522553387, 447296910, +- 3959392091, 547575038, 2788632144, 1835791861, 1886307661, 3140622056, 1034314822, 4143626211, +- 75106221, 3475428360, 1236444838, 2196665603, 2682996155, 1421317662, 3525567664, 427767573, +- 3895035328, 594892389, 2782995659, 1857943406, 1941489622, 3101955187, 1047553757, 4113347960, +- 257428076, 3288652233, 1116777319, 2311878850, 2496219258, 1603640287, 3640781169, 308099796, +- 3809183745, 676813732, 2932025610, 1704983215, 2023410199, 3016104370, 894593820, 4262377657, +- 210634999, 3352484690, 1095150076, 2316991065, 2535410401, 1547934020, 3671583722, 294336591, +- 3772615322, 729897279, 2903845777, 1716123700, 2068629644, 2953845545, 914647431, 4258839074, +- 150212442, 3282623743, 1161604689, 2388688372, 2472889676, 1480171241, 3735940167, 368132066, +- 3836185911, 805002898, 2842635324, 1647574937, 2134298401, 3026852996, 855535146, 4188192143, +- 186781121, 3229539940, 1189784778, 2377547631, 2427670487, 1542429810, 3715886812, 371670393, +- 3882979244, 741170185, 2864262823, 1642462466, 2095107514, 3082559007, 824732849, 4201955092, +- 514856152, 3589064573, 1400419795, 2552522358, 2233554638, 1316849003, 3370776517, 62202976, +- 4075001525, 968836368, 3207280574, 1954014235, 1769133219, 2720925446, 616199592, 4024870413, +- 493229635, 3594175974, 1353627464, 2616354029, 2264355925, 1303087088, 3409966430, 6498043, +- 4046820398, 979978123, 3170710821, 2007099008, 1789187640, 2717386141, 661419827, 3962610838, +- 421269998, 3527459403, 1423225061, 2676515648, 2190300152, 1238466653, 3477467891, 68755798, +- 4115633027, 1041448998, 3095868040, 1943789869, 1860096405, 2776760880, 588673182, 3897205563, +- 449450869, 3516317904, 1459794558, 2623431131, 2170245475, 1242006214, 3432247400, 131015629, +- 4137259288, 1036337853, 3142660115, 1879958454, 1829294862, 2790523051, 549483013, 3952910752, +- 300424884, 3669282065, 1545650111, 2541513754, 2323209378, 1092980487, 3350330793, 216870412, +- 4256931033, 921128828, 2960342482, 2066738807, 1714085583, 2910195050, 736264132, 3770592353, +- 306060335, 3647131530, 1610005796, 2494197377, 2309971513, 1123257756, 3295149874, 255536279, +- 4268596802, 892423655, 3013951305, 2029645036, 1711070292, 2929725425, 674528607, 3815288570, +- 373562242, 3709388839, 1535949449, 2429577516, 2379569556, 1183418929, 3223189663, 188820282, +- 4195850735, 827017802, 3084859620, 2089020225, 1636228089, 2866415708, 743340786, 3876759895, +- 361896217, 3738094268, 1482340370, 2466671543, 2382584591, 1163888810, 3284924932, 144124321, +- 4190215028, 849168593, 3020503679, 2136336858, 1649465698, 2836138695, 798521449, 3838094284, +- }, { +- 0, 2792819636, 2543784233, 837294749, 4098827283, 1379413927, 1674589498, 3316072078, +- 871321191, 2509784531, 2758827854, 34034938, 3349178996, 1641505216, 1346337629, 4131942633, +- 1742642382, 3249117050, 4030828007, 1446413907, 2475800797, 904311657, 68069876, 2725880384, +- 1412551337, 4064729373, 3283010432, 1708771380, 2692675258, 101317902, 937551763, 2442587175, +- 3485284764, 1774858792, 1478633653, 4266992385, 1005723023, 2642744891, 2892827814, 169477906, +- 4233263099, 1512406095, 1808623314, 3451546982, 136139752, 2926205020, 2676114113, 972376437, +- 2825102674, 236236518, 1073525883, 2576072655, 1546420545, 4200303349, 3417542760, 1841601500, +- 2609703733, 1039917185, 202635804, 2858742184, 1875103526, 3384067218, 4166835727, 1579931067, +- 1141601657, 3799809741, 3549717584, 1977839588, 2957267306, 372464350, 668680259, 2175552503, +- 2011446046, 3516084394, 3766168119, 1175200131, 2209029901, 635180217, 338955812, 2990736784, +- 601221559, 2242044419, 3024812190, 306049834, 3617246628, 1911408144, 1074125965, 3866285881, +- 272279504, 3058543716, 2275784441, 567459149, 3832906691, 1107462263, 1944752874, 3583875422, +- 2343980261, 767641425, 472473036, 3126744696, 2147051766, 3649987394, 3899029983, 1309766251, +- 3092841090, 506333494, 801510315, 2310084639, 1276520081, 3932237093, 3683203000, 2113813516, +- 3966292011, 1243601823, 2079834370, 3716205238, 405271608, 3192979340, 2411259153, 701492901, +- 3750207052, 2045810168, 1209569125, 4000285905, 734575199, 2378150379, 3159862134, 438345922, +- 2283203314, 778166598, 529136603, 3120492655, 2086260449, 3660498261, 3955679176, 1303499900, +- 3153699989, 495890209, 744928700, 2316418568, 1337360518, 3921775410, 3626602927, 2120129051, +- 4022892092, 1237286280, 2018993941, 3726666913, 461853231, 3186645403, 2350400262, 711936178, +- 3693557851, 2052076527, 1270360434, 3989775046, 677911624, 2384402428, 3220639073, 427820757, +- 1202443118, 3789347034, 3493118535, 1984154099, 3018127229, 362020041, 612099668, 2181885408, +- 1950653705, 3526596285, 3822816288, 1168934804, 2148251930, 645706414, 395618355, 2984485767, +- 544559008, 2248295444, 3085590153, 295523645, 3560598451, 1917673479, 1134918298, 3855773998, +- 328860103, 3052210803, 2214924526, 577903450, 3889505748, 1101147744, 1883911421, 3594338121, +- 3424493451, 1785369663, 1535282850, 4260726038, 944946072, 2653270060, 2949491377, 163225861, +- 4294103532, 1501944408, 1752023237, 3457862513, 196998655, 2915761739, 2619532502, 978710370, +- 2881684293, 229902577, 1012666988, 2586515928, 1603020630, 4193987810, 3356702335, 1852063179, +- 2553040162, 1046169238, 263412747, 2848217023, 1818454321, 3390333573, 4227627032, 1569420204, +- 60859927, 2782375331, 2487203646, 843627658, 4159668740, 1368951216, 1617990445, 3322386585, +- 810543216, 2520310724, 2815490393, 27783917, 3288386659, 1652017111, 1402985802, 4125677310, +- 1685994201, 3255382381, 4091620336, 1435902020, 2419138250, 910562686, 128847843, 2715354199, +- 1469150398, 4058414858, 3222168983, 1719234083, 2749255853, 94984985, 876691844, 2453031472, +- }, { +- 0, 3433693342, 1109723005, 2391738339, 2219446010, 1222643300, 3329165703, 180685081, +- 3555007413, 525277995, 2445286600, 1567235158, 1471092047, 2600801745, 361370162, 3642757804, +- 2092642603, 2953916853, 1050555990, 4063508168, 4176560081, 878395215, 3134470316, 1987983410, +- 2942184094, 1676945920, 3984272867, 567356797, 722740324, 3887998202, 1764827929, 2778407815, +- 4185285206, 903635656, 3142804779, 2012833205, 2101111980, 2979425330, 1058630609, 4088621903, +- 714308067, 3862526333, 1756790430, 2753330688, 2933487385, 1651734407, 3975966820, 542535930, +- 2244825981, 1231508451, 3353891840, 188896414, 25648519, 3442302233, 1134713594, 2399689316, +- 1445480648, 2592229462, 336416693, 3634843435, 3529655858, 516441772, 2420588879, 1559052753, +- 698204909, 3845636723, 1807271312, 2803025166, 2916600855, 1635634313, 4025666410, 593021940, +- 4202223960, 919787974, 3093159461, 1962401467, 2117261218, 2996361020, 1008193759, 4038971457, +- 1428616134, 2576151384, 386135227, 3685348389, 3513580860, 499580322, 2471098945, 1608776415, +- 2260985971, 1248454893, 3303468814, 139259792, 42591881, 3458459159, 1085071860, 2349261162, +- 3505103035, 474062885, 2463016902, 1583654744, 1419882049, 2550902495, 377792828, 3660491170, +- 51297038, 3483679632, 1093385331, 2374089965, 2269427188, 1273935210, 3311514249, 164344343, +- 2890961296, 1627033870, 4000683757, 585078387, 672833386, 3836780532, 1782552599, 2794821769, +- 2142603813, 3005188795, 1032883544, 4047146438, 4227826911, 928351297, 3118105506, 1970307900, +- 1396409818, 2677114180, 287212199, 3719594553, 3614542624, 467372990, 2505346141, 1509854403, +- 2162073199, 1282711281, 3271268626, 240228748, 76845205, 3359543307, 1186043880, 2317064054, +- 796964081, 3811226735, 1839575948, 2702160658, 2882189835, 1734392469, 3924802934, 625327592, +- 4234522436, 818917338, 3191908409, 1927981223, 2016387518, 3028656416, 973776579, 4137723485, +- 2857232268, 1726474002, 3899187441, 616751215, 772270454, 3803048424, 1814228491, 2693328533, +- 2041117753, 3036871847, 999160644, 4146592730, 4259508931, 826864221, 3217552830, 1936586016, +- 3606501031, 442291769, 2496909786, 1484378436, 1388107869, 2652297411, 278519584, 3694387134, +- 85183762, 3384397196, 1194773103, 2342308593, 2170143720, 1307820918, 3279733909, 265733131, +- 2057717559, 3054258089, 948125770, 4096344276, 4276898253, 843467091, 3167309488, 1885556270, +- 2839764098, 1709792284, 3949353983, 667704161, 755585656, 3785577190, 1865176325, 2743489947, +- 102594076, 3401021058, 1144549729, 2291298815, 2186770662, 1325234296, 3228729243, 215514885, +- 3589828009, 424832311, 2547870420, 1534552650, 1370645331, 2635621325, 328688686, 3745342640, +- 2211456353, 1333405183, 3254067740, 224338562, 127544219, 3408931589, 1170156774, 2299866232, +- 1345666772, 2627681866, 303053225, 3736746295, 3565105198, 416624816, 2522494803, 1525692365, +- 4285207626, 868291796, 3176010551, 1910772649, 2065767088, 3079346734, 956571085, 4121828691, +- 747507711, 3760459617, 1856702594, 2717976604, 2831417605, 1684930971, 3940615800, 642451174, +- }, +- { +- 0, 393942083, 787884166, 965557445, 1575768332, 1251427663, 1931114890, 1684106697, +- 3151536664, 2896410203, 2502855326, 2186649309, 3862229780, 4048545623, 3368213394, 3753496529, +- 2898281073, 3149616690, 2184604407, 2504883892, 4046197629, 3864463166, 3755621371, 3366006712, +- 387506281, 6550570, 971950319, 781573292, 1257550181, 1569695014, 1677892067, 1937345952, +- 2196865699, 2508887776, 2886183461, 3145514598, 3743273903, 3362179052, 4058774313, 3868258154, +- 958996667, 777139448, 400492605, 10755198, 1690661303, 1941857780, 1244879153, 1565019506, +- 775012562, 961205393, 13101140, 398261271, 1943900638, 1688634781, 1563146584, 1246801179, +- 2515100362, 2190636681, 3139390028, 2892258831, 3355784134, 3749586821, 3874691904, 4052225795, +- 3734110983, 3387496260, 4033096577, 3877584834, 2206093835, 2483373640, 2911402637, 3136515790, +- 1699389727, 1915860316, 1270647193, 1556585946, 950464531, 803071056, 374397077, 19647702, +- 1917993334, 1697207605, 1554278896, 1272937907, 800985210, 952435769, 21510396, 372452543, +- 3381322606, 3740399405, 3883715560, 4027047851, 2489758306, 2199758369, 3130039012, 2917895847, +- 1550025124, 1259902439, 1922410786, 1710144865, 26202280, 385139947, 796522542, 939715693, +- 3887801276, 4039129087, 3377269562, 3728088953, 3126293168, 2905368307, 2493602358, 2212122229, +- 4037264341, 3889747862, 3730172755, 3375300368, 2907673305, 3124004506, 2209987167, 2495786524, +- 1266377165, 1543533966, 1703758155, 1928748296, 379007169, 32253058, 945887303, 790236164, +- 1716846671, 1898845196, 1218652361, 1608006794, 1002000707, 750929152, 357530053, 36990342, +- 3717046871, 3405166100, 4084959953, 3825245842, 2153902939, 2535122712, 2929187805, 3119304606, +- 3398779454, 3723384445, 3831720632, 4078468859, 2541294386, 2147616625, 3113171892, 2935238647, +- 1900929062, 1714877541, 1606142112, 1220599011, 748794154, 1004184937, 39295404, 355241455, +- 3835986668, 4091516591, 3394415210, 3710500393, 3108557792, 2922629027, 2545875814, 2160455461, +- 1601970420, 1208431799, 1904871538, 1727077425, 43020792, 367748539, 744905086, 991776061, +- 1214562461, 1595921630, 1720903707, 1911159896, 361271697, 49513938, 998160663, 738569556, +- 4089209477, 3838277318, 3712633347, 3392233024, 2924491657, 3106613194, 2158369551, 2547846988, +- 3100050248, 2948339467, 2519804878, 2169126797, 3844821572, 4065347079, 3420289730, 3701894785, +- 52404560, 342144275, 770279894, 982687125, 1593045084, 1233708063, 1879431386, 1736363161, +- 336019769, 58479994, 988899775, 764050940, 1240141877, 1586496630, 1729968307, 1885744368, +- 2950685473, 3097818978, 2166999975, 2522013668, 4063474221, 3846743662, 3703937707, 3418263272, +- 976650731, 760059304, 348170605, 62635310, 1742393575, 1889649828, 1227683937, 1582820386, +- 2179867635, 2526361520, 2937588597, 3093503798, 3691148031, 3413731004, 4076100217, 3851374138, +- 2532754330, 2173556697, 3087067932, 2944139103, 3407516310, 3697379029, 3857496592, 4070026835, +- 758014338, 978679233, 64506116, 346250567, 1891774606, 1740186829, 1580472328, 1229917259, +- }, { +- 0, 4022496062, 83218493, 3946298115, 166436986, 3861498692, 220098631, 3806075769, +- 332873972, 4229245898, 388141257, 4175494135, 440197262, 4127099824, 516501683, 4044053389, +- 665747944, 3362581206, 593187285, 3432594155, 776282514, 3246869164, 716239279, 3312622225, +- 880394524, 3686509090, 814485793, 3746462239, 1033003366, 3528460888, 963096923, 3601193573, +- 1331495888, 2694801646, 1269355501, 2758457555, 1186374570, 2843003028, 1111716759, 2910918825, +- 1552565028, 3007850522, 1484755737, 3082680359, 1432478558, 3131279456, 1368666979, 3193329757, +- 1760789048, 2268195078, 1812353541, 2210675003, 1628971586, 2396670332, 1710092927, 2318375233, +- 2066006732, 2498144754, 2144408305, 2417195471, 1926193846, 2634877320, 1983558283, 2583222709, +- 2662991776, 1903717534, 2588923805, 1972223139, 2538711002, 2022952164, 2477029351, 2087066841, +- 2372749140, 1655647338, 2308478825, 1717238871, 2223433518, 1799654416, 2155034387, 1873894445, +- 3105130056, 1456926070, 3185661557, 1378041163, 2969511474, 1597852940, 3020617231, 1539874097, +- 2864957116, 1157737858, 2922780289, 1106542015, 2737333958, 1290407416, 2816325371, 1210047941, +- 3521578096, 1042640718, 3574781005, 986759027, 3624707082, 936300340, 3707335735, 859512585, +- 3257943172, 770846650, 3334837433, 688390023, 3420185854, 605654976, 3475911875, 552361981, +- 4132013464, 428600998, 4072428965, 494812827, 4288816610, 274747100, 4216845791, 345349857, +- 3852387692, 173846098, 3781891409, 245988975, 3967116566, 62328360, 3900749099, 121822741, +- 3859089665, 164061759, 3807435068, 221426178, 4025395579, 2933317, 3944446278, 81334904, +- 4124199413, 437265099, 4045904328, 518386422, 4231653775, 335250097, 4174133682, 386814604, +- 3249244393, 778691543, 3311294676, 714879978, 3359647891, 662848429, 3434477742, 595039120, +- 3531393053, 1035903779, 3599308832, 961245982, 3684132967, 877986649, 3747788890, 815846244, +- 2841119441, 1184522735, 2913852140, 1114616274, 2696129195, 1332855189, 2756082326, 1266946472, +- 3129952805, 1431118107, 3195705880, 1371074854, 3009735263, 1554415969, 3079748194, 1481855324, +- 2398522169, 1630855175, 2315475716, 1707159610, 2266835779, 1759461501, 2213084030, 1814728768, +- 2636237773, 1927520499, 2580814832, 1981182158, 2496293815, 2064121993, 2420095882, 2147340468, +- 2025787041, 2541577631, 2085281436, 2475210146, 1901375195, 2660681189, 1973518054, 2590184920, +- 1801997909, 2225743211, 1872600680, 2153772374, 1652813359, 2369881361, 1719025170, 2310296876, +- 1594986313, 2966676599, 1541693300, 3022402634, 1459236659, 3107472397, 1376780046, 3184366640, +- 1288097725, 2734990467, 1211309952, 2817619134, 1160605639, 2867791097, 1104723962, 2920993988, +- 937561457, 3626001999, 857201996, 3704993394, 1040821515, 3519792693, 989625654, 3577615880, +- 607473029, 3421972155, 549494200, 3473077894, 769584639, 3256649409, 690699714, 3337180924, +- 273452185, 4287555495, 347692196, 4219156378, 430386403, 4133832669, 491977950, 4069562336, +- 60542061, 3965298515, 124656720, 3903616878, 175139863, 3853649705, 243645482, 3779581716, +- }, { +- 0, 3247366080, 1483520449, 2581751297, 2967040898, 1901571138, 3904227907, 691737987, +- 3133399365, 2068659845, 3803142276, 589399876, 169513671, 3415493895, 1383475974, 2482566342, +- 2935407819, 1870142219, 4137319690, 924099274, 506443593, 3751897225, 1178799752, 2278412616, +- 339027342, 3585866318, 1280941135, 2379694991, 2766951948, 1700956620, 4236308429, 1024339981, +- 2258407383, 1192382487, 3740284438, 528411094, 910556245, 4157285269, 1848198548, 2946996820, +- 1012887186, 4258378066, 1681119059, 2780629139, 2357599504, 1292419792, 3572147409, 358906641, +- 678054684, 3924071644, 1879503581, 2978491677, 2561882270, 1497229150, 3235873119, 22109855, +- 2460592729, 1395094937, 3401913240, 189516888, 577821147, 3825075739, 2048679962, 3146956762, +- 3595049455, 398902831, 2384764974, 1336573934, 1720805997, 2803873197, 1056822188, 4285729900, +- 1821112490, 2902796138, 887570795, 4117339819, 3696397096, 500978920, 2218668777, 1169222953, +- 2025774372, 3106931428, 550659301, 3780950821, 3362238118, 166293862, 2416645991, 1367722151, +- 3262987361, 66315169, 2584839584, 1537170016, 1923370979, 3005911075, 717813282, 3947244002, +- 1356109368, 2438613496, 146288633, 3375820857, 3759007162, 562248314, 3093388411, 2045739963, +- 3927406461, 731490493, 2994458300, 1945440636, 1523451135, 2604718911, 44219710, 3274466046, +- 4263662323, 1068272947, 2790189874, 1740649714, 1325080945, 2406874801, 379033776, 3608758128, +- 1155642294, 2238671990, 479005303, 3708016055, 4097359924, 901128180, 2891217397, 1843045941, +- 2011248031, 3060787807, 797805662, 3993195422, 3342353949, 112630237, 2673147868, 1591353372, +- 3441611994, 212601626, 2504944923, 1421914843, 2113644376, 3161815192, 630660761, 3826893145, +- 3642224980, 412692116, 2172340373, 1089836885, 1775141590, 2822790422, 832715543, 4029474007, +- 1674842129, 2723860433, 1001957840, 4197873168, 3540870035, 310623315, 2338445906, 1257178514, +- 4051548744, 821257608, 2836464521, 1755307081, 1101318602, 2150241802, 432566283, 3628511179, +- 1270766349, 2318435533, 332587724, 3529260300, 4217841807, 988411727, 2735444302, 1652903566, +- 1602977411, 2651169091, 132630338, 3328776322, 4015131905, 786223809, 3074340032, 1991273216, +- 3846741958, 616972294, 3173262855, 2091579847, 1435626564, 2485072772, 234706309, 3430124101, +- 2712218736, 1613231024, 4190475697, 944458353, 292577266, 3506339890, 1226630707, 2291284467, +- 459984181, 3672380149, 1124496628, 2189994804, 2880683703, 1782407543, 4091479926, 844224694, +- 257943739, 3469817723, 1462980986, 2529005242, 3213269817, 2114471161, 3890881272, 644152632, +- 3046902270, 1947391550, 3991973951, 746483711, 88439420, 3301680572, 1563018173, 2628197501, +- 657826727, 3871046759, 2136545894, 3201811878, 2548879397, 1449267173, 3481299428, 235845156, +- 2650161890, 1551408418, 3315268387, 68429027, 758067552, 3970035360, 1967360161, 3033356129, +- 2311284588, 1213053100, 3517963949, 270598509, 958010606, 4170500910, 1635167535, 2700636911, +- 855672361, 4069415401, 1802256360, 2866995240, 2212099499, 1113008747, 3686091882, 440112042, +- }, { +- 0, 2611301487, 3963330207, 2006897392, 50740095, 2560849680, 4013794784, 1956178319, +- 101480190, 2645113489, 3929532513, 1905435662, 84561281, 2662269422, 3912356638, 1922342769, +- 202960380, 2545787283, 3760419683, 2072395532, 253679235, 2495322860, 3810871324, 2021655667, +- 169122562, 2444351341, 3861841309, 2106214898, 152215677, 2461527058, 3844685538, 2123133581, +- 405920760, 2207553431, 4094313831, 1873742088, 456646791, 2157096168, 4144791064, 1823027831, +- 507358470, 2241388905, 4060492697, 1772322806, 490444409, 2258557462, 4043311334, 1789215881, +- 338245124, 2408348267, 4161972379, 1672996084, 388959611, 2357870868, 4212429796, 1622269835, +- 304431354, 2306870421, 4263435877, 1706791434, 287538053, 2324051946, 4246267162, 1723705717, +- 811841520, 2881944479, 3696765295, 1207788800, 862293135, 2831204576, 3747484176, 1157324415, +- 913293582, 2915732833, 3662962577, 1106318334, 896137841, 2932651550, 3646055662, 1123494017, +- 1014716940, 2816349795, 3493905555, 1273334012, 1065181555, 2765630748, 3544645612, 1222882179, +- 980888818, 2714919069, 3595350637, 1307180546, 963712909, 2731826146, 3578431762, 1324336509, +- 676490248, 3019317351, 3295277719, 1607253752, 726947703, 2968591128, 3345992168, 1556776327, +- 777919222, 3053147801, 3261432937, 1505806342, 760750473, 3070062054, 3244539670, 1522987897, +- 608862708, 3220163995, 3362856811, 1406423812, 659339915, 3169449700, 3413582868, 1355966587, +- 575076106, 3118709605, 3464325525, 1440228858, 557894773, 3135602714, 3447411434, 1457397381, +- 1623683040, 4217512847, 2365387135, 391757072, 1673614495, 4167309552, 2415577600, 341804655, +- 1724586270, 4251866481, 2331019137, 290835438, 1707942497, 4268256782, 2314648830, 307490961, +- 1826587164, 4152020595, 2162433155, 457265388, 1876539747, 4101829900, 2212636668, 407333779, +- 1792275682, 4051089549, 2263378557, 491595282, 1775619997, 4067460082, 2246988034, 508239213, +- 2029433880, 3813931127, 2496473735, 258500328, 2079362919, 3763716872, 2546668024, 208559511, +- 2130363110, 3848244873, 2462145657, 157552662, 2113730969, 3864638966, 2445764358, 174205801, +- 1961777636, 4014675339, 2564147067, 57707284, 2011718299, 3964481268, 2614361092, 7778411, +- 1927425818, 3913769845, 2665066885, 92077546, 1910772837, 3930150922, 2648673018, 108709525, +- 1352980496, 3405878399, 3164554895, 658115296, 1403183983, 3355946752, 3214507504, 607924639, +- 1453895406, 3440239233, 3130208369, 557218846, 1437504913, 3456883198, 3113552654, 573589345, +- 1555838444, 3340335491, 2961681267, 723707676, 1606028947, 3290383100, 3011612684, 673504355, +- 1521500946, 3239382909, 3062619533, 758026722, 1505130605, 3256038402, 3045975794, 774417053, +- 1217725416, 3543158663, 2762906999, 1057739032, 1267939479, 3493229816, 2812847624, 1007544935, +- 1318679830, 3577493881, 2728586121, 956803046, 1302285929, 3594125830, 2711933174, 973184153, +- 1150152212, 3743982203, 2830528651, 856898788, 1200346475, 3694041348, 2880457716, 806684571, +- 1115789546, 3643069573, 2931426933, 891243034, 1099408277, 3659722746, 2914794762, 907637093, +- }, { +- 0, 3717650821, 1616688459, 3184159950, 3233376918, 489665299, 2699419613, 2104690264, +- 1510200173, 2274691816, 979330598, 3888758691, 2595928571, 1194090622, 4209380528, 661706037, +- 3020400346, 1771143007, 3562738577, 164481556, 1958661196, 2837976521, 350386439, 3379863682, +- 3993269687, 865250354, 2388181244, 1406015865, 784146209, 4079732388, 1323412074, 2474079215, +- 3011398645, 1860735600, 3542286014, 246687547, 1942430051, 2924607718, 328963112, 3456978349, +- 3917322392, 887832861, 2300653011, 1421341782, 700772878, 4099025803, 1234716485, 2483986112, +- 125431087, 3673109674, 1730500708, 3132326369, 3351283641, 441867836, 2812031730, 2047535991, +- 1568292418, 2163009479, 1025936137, 3769651852, 2646824148, 1079348561, 4255113631, 537475098, +- 3180171691, 1612400686, 3721471200, 4717925, 2100624189, 2694980280, 493375094, 3237910515, +- 3884860102, 974691139, 2278750093, 1514417672, 657926224, 4204917205, 1198234907, 2600289438, +- 160053105, 3558665972, 1775665722, 3024116671, 3375586791, 346391650, 2842683564, 1962488105, +- 1401545756, 2384412057, 869618007, 3997403346, 2469432970, 1319524111, 4083956673, 788193860, +- 250862174, 3546612699, 1856990997, 3006903952, 3461001416, 333211981, 2920678787, 1937824774, +- 1425017139, 2305216694, 883735672, 3912918525, 2487837605, 1239398944, 4095071982, 696455019, +- 3136584836, 1734518017, 3668494799, 121507914, 2051872274, 2816200599, 437363545, 3347544796, +- 3774328809, 1029797484, 2158697122, 1564328743, 542033279, 4258798842, 1074950196, 2642717105, +- 2691310871, 2113731730, 3224801372, 497043929, 1624461185, 3175454212, 9435850, 3709412175, +- 4201248378, 671035391, 2587181873, 1201904308, 986750188, 3880142185, 1519135143, 2266689570, +- 342721485, 3388693064, 1949382278, 2846355203, 3570723163, 155332830, 3028835344, 1763607957, +- 1315852448, 2482538789, 775087595, 4087626862, 2396469814, 1396827059, 4002123645, 857560824, +- 320106210, 3464673127, 1934154665, 2933785132, 3551331444, 238804465, 3018961215, 1852270778, +- 1226292623, 2491507722, 692783300, 4108177729, 2309936921, 1412959900, 3924976210, 879016919, +- 2803091512, 2055541181, 3343875443, 450471158, 1739236014, 3124525867, 133568485, 3663777376, +- 4245691221, 545702608, 2639048222, 1088059291, 1034514883, 3762268230, 1576387720, 2153979149, +- 501724348, 3228659001, 2109407735, 2687359090, 3713981994, 13109167, 3171052385, 1620357860, +- 1206151121, 2591211092, 666423962, 4197321503, 2271022407, 1523307714, 3875649548, 982999433, +- 2850034278, 1953942499, 3384583981, 338329256, 1767471344, 3033506165, 151375291, 3566408766, +- 4091789579, 779425934, 2478797888, 1311354309, 861580189, 4006375960, 1392910038, 2391852883, +- 2929327945, 1930372812, 3469036034, 324244359, 1847629279, 3015068762, 243015828, 3555391761, +- 4103744548, 688715169, 2496043375, 1229996266, 874727090, 3920994103, 1417671673, 2313759356, +- 446585235, 3339223062, 2059594968, 2807313757, 3660002053, 129100416, 3128657486, 1743609803, +- 1084066558, 2634765179, 549535669, 4250396208, 2149900392, 1571961325, 3765982499, 1039043750, +- }, { +- 0, 2635063670, 3782132909, 2086741467, 430739227, 2225303149, 4173482934, 1707977408, +- 861478454, 2924937024, 3526875803, 1329085421, 720736557, 3086643291, 3415954816, 1452586230, +- 1722956908, 4223524122, 2279405761, 450042295, 2132718455, 3792785921, 2658170842, 58693292, +- 1441473114, 3370435372, 3028674295, 696911745, 1279765825, 3511176247, 2905172460, 807831706, +- 3445913816, 1349228974, 738901109, 2969918723, 3569940419, 1237784245, 900084590, 2829701656, +- 4265436910, 1664255896, 525574723, 2187084597, 3885099509, 2057177219, 117386584, 2616249390, +- 2882946228, 920233410, 1253605401, 3619119471, 2994391983, 796207833, 1393823490, 3457937012, +- 2559531650, 92322804, 2044829231, 3840835417, 2166609305, 472659183, 1615663412, 4249022530, +- 1102706673, 3702920839, 2698457948, 1037619754, 1477802218, 3306854812, 3111894087, 611605809, +- 1927342535, 4025419953, 2475568490, 243387420, 1800169180, 4131620778, 2317525617, 388842247, +- 655084445, 3120835307, 3328511792, 1533734470, 1051149446, 2745738736, 3754524715, 1120297309, +- 340972971, 2304586973, 4114354438, 1748234352, 234773168, 2431761350, 3968900637, 1906278251, +- 2363330345, 299003487, 1840466820, 4038896370, 2507210802, 142532932, 1948239007, 3910149609, +- 3213136159, 579563625, 1592415666, 3286611140, 2787646980, 992477042, 1195825833, 3662232543, +- 3933188933, 2002801203, 184645608, 2517538462, 4089658462, 1858919720, 313391347, 2409765253, +- 3644239219, 1144605701, 945318366, 2773977256, 3231326824, 1570095902, 569697989, 3170568115, +- 2205413346, 511446676, 1646078799, 4279421497, 2598330617, 131105167, 2075239508, 3871229218, +- 2955604436, 757403810, 1363424633, 3427521551, 2844163791, 881434553, 1223211618, 3588709140, +- 3854685070, 2026779384, 78583587, 2577462869, 4235025557, 1633861091, 486774840, 2148301134, +- 3600338360, 1268198606, 938871061, 2868504675, 3476308643, 1379640277, 777684494, 3008718712, +- 1310168890, 3541595724, 2943964055, 846639841, 1471879201, 3400857943, 3067468940, 735723002, +- 2102298892, 3762382970, 2619362721, 19901655, 1692534295, 4193118049, 2240594618, 411247564, +- 681945942, 3047836192, 3385552891, 1422167693, 822682701, 2886124859, 3496468704, 1298661782, +- 469546336, 2264093718, 4203901389, 1738379451, 38812283, 2673859341, 3812556502, 2117148576, +- 3268024339, 1606809957, 598006974, 3198893512, 3680933640, 1181316734, 973624229, 2802299603, +- 4052944421, 1822222163, 285065864, 2381456382, 3896478014, 1966106696, 156323219, 2489232613, +- 2759337087, 964150537, 1159127250, 3625517476, 3184831332, 551242258, 1555722185, 3249901247, +- 2535537225, 170842943, 1984954084, 3946848146, 2391651666, 327308324, 1877176831, 4075589769, +- 263086283, 2460058045, 4005602406, 1942963472, 369291216, 2332888742, 4151061373, 1784924683, +- 1022852861, 2717425547, 3717839440, 1083595558, 626782694, 3092517008, 3291821387, 1497027645, +- 1763466407, 4094934481, 2289211402, 360544636, 1890636732, 3988730570, 2447251217, 215086695, +- 1514488465, 3343557607, 3140191804, 639919946, 1139395978, 3739626748, 2726758695, 1065936977, +- }, { +- 0, 3120290792, 2827399569, 293431929, 2323408227, 864534155, 586863858, 2600537882, +- 3481914503, 1987188591, 1729068310, 3740575486, 1173727716, 4228805132, 3983743093, 1418249117, +- 1147313999, 4254680231, 3974377182, 1428157750, 3458136620, 2011505092, 1721256893, 3747844181, +- 2347455432, 839944224, 594403929, 2593536433, 26687147, 3094146371, 2836498234, 283794642, +- 2294627998, 826205558, 541298447, 2578994407, 45702141, 3141697557, 2856315500, 331624836, +- 1196225049, 4273416689, 4023010184, 1446090848, 3442513786, 1959480466, 1706436331, 3696098563, +- 3433538001, 1968994873, 1679888448, 3722103720, 1188807858, 4280295258, 3999102243, 1470541515, +- 53374294, 3134568126, 2879970503, 307431215, 2303854645, 816436189, 567589284, 2553242188, +- 3405478781, 1929420949, 1652411116, 3682996484, 1082596894, 4185703926, 3892424591, 1375368295, +- 91404282, 3163122706, 2918450795, 336584067, 2400113305, 922028401, 663249672, 2658384096, +- 2392450098, 929185754, 639587747, 2682555979, 82149713, 3172883129, 2892181696, 362343208, +- 1091578037, 4176212829, 3918960932, 1349337804, 3412872662, 1922537022, 1676344391, 3658557359, +- 1111377379, 4224032267, 3937989746, 1396912026, 3359776896, 1908013928, 1623494929, 3644803833, +- 2377615716, 877417100, 623982837, 2630542109, 130804743, 3190831087, 2941083030, 381060734, +- 106748588, 3215393092, 2933549885, 388083925, 2350956495, 903570471, 614862430, 2640172470, +- 3386185259, 1882115523, 1632872378, 3634920530, 1135178568, 4199721120, 3945775833, 1389631793, +- 1317531835, 4152109907, 3858841898, 1610259138, 3304822232, 2097172016, 1820140617, 3582394273, +- 2165193788, 955639764, 696815021, 2423477829, 192043359, 2995356343, 2750736590, 437203750, +- 182808564, 3005133852, 2724453989, 462947725, 2157513367, 962777471, 673168134, 2447663342, +- 3312231283, 2090301595, 1844056802, 3557935370, 1326499344, 4142603768, 3885397889, 1584245865, +- 3326266917, 2142836173, 1858371508, 3611272284, 1279175494, 4123357358, 3837270743, 1564721471, +- 164299426, 2955991370, 2706223923, 414607579, 2209834945, 978107433, 724686416, 2462715320, +- 2183156074, 1004243586, 715579643, 2472360723, 140260361, 2980573153, 2698675608, 421617264, +- 1302961645, 4099032581, 3845074044, 1557460884, 3352688782, 2116952934, 1867729183, 3601371895, +- 2222754758, 1032278062, 754596439, 2499928511, 234942117, 3086693709, 2793824052, 528319708, +- 1274365761, 4061043881, 3816027856, 1518873912, 3246989858, 2020800970, 1762628531, 3505670235, +- 3223196809, 2045103969, 1754834200, 3512958704, 1247965674, 4086934018, 3806642299, 1528765331, +- 261609486, 3060532198, 2802936223, 518697591, 2246819181, 1007707781, 762121468, 2492913428, +- 213497176, 3041029808, 2755593417, 499441441, 2261110843, 1061030867, 776167850, 2545465922, +- 3274734047, 2060165687, 1807140942, 3528266662, 1229724860, 4038575956, 3788156205, 1479636677, +- 1222322711, 4045468159, 3764231046, 1504067694, 3265744756, 2069664924, 1780612837, 3554288909, +- 2270357136, 1051278712, 802445057, 2519698665, 221152243, 3033880603, 2779263586, 475261322, +- }, { +- 0, 2926088593, 2275419491, 701019378, 3560000647, 2052709654, 1402038756, 4261017717, +- 1930665807, 3715829470, 4105419308, 1524313021, 2804077512, 155861593, 545453739, 2397726522, +- 3861331614, 1213181711, 1636244477, 3488582252, 840331801, 2625561480, 3048626042, 467584747, +- 2503254481, 995897408, 311723186, 3170637091, 1090907478, 4016929991, 3332753461, 1758288292, +- 390036349, 3109546732, 2426363422, 1056427919, 3272488954, 1835443819, 1152258713, 3938878216, +- 1680663602, 3393484195, 3817652561, 1306808512, 2954733749, 510998820, 935169494, 2580880455, +- 4044899811, 1601229938, 1991794816, 3637571857, 623446372, 2336332021, 2726898695, 216120726, +- 2181814956, 744704829, 95158223, 2881711710, 1446680107, 4166125498, 3516576584, 2146575065, +- 780072698, 2148951915, 2849952665, 129384968, 4199529085, 1411853292, 2112855838, 3548843663, +- 1567451573, 4077254692, 3670887638, 1957027143, 2304517426, 657765539, 251396177, 2694091200, +- 3361327204, 1714510325, 1341779207, 3784408214, 476611811, 2986349938, 2613617024, 899690513, +- 3142211371, 354600634, 1021997640, 2458051545, 1870338988, 3239283261, 3906682575, 1186180958, +- 960597383, 2536053782, 3202459876, 277428597, 3983589632, 1125666961, 1792074851, 3300423154, +- 1246892744, 3829039961, 3455203243, 1671079482, 2657312335, 806080478, 432241452, 3081497277, +- 3748049689, 1896751752, 1489409658, 4138600427, 190316446, 2772397583, 2365053693, 580864876, +- 2893360214, 35503559, 735381813, 2243795108, 2017747153, 3593269568, 4293150130, 1368183843, +- 1560145396, 4069882981, 3680356503, 1966430470, 2295112051, 648294626, 258769936, 2701399425, +- 804156091, 2173100842, 2823706584, 103204425, 4225711676, 1438101421, 2088704863, 3524758222, +- 3134903146, 347226875, 1031468553, 2467456920, 1860935661, 3229814396, 3914054286, 1193487135, +- 3385412645, 1738661300, 1315531078, 3758225623, 502792354, 3012596019, 2589468097, 875607120, +- 1271043721, 3853125400, 3429020650, 1644831355, 2683558414, 832261023, 408158061, 3057348348, +- 953223622, 2528745559, 3211865253, 286899508, 3974120769, 1116263632, 1799381026, 3307794867, +- 2917509143, 59586950, 709201268, 2217549029, 2043995280, 3619452161, 4269064691, 1344032866, +- 3740677976, 1889445577, 1498812987, 4148069290, 180845535, 2762992206, 2372361916, 588238637, +- 1921194766, 3706423967, 4112727661, 1531686908, 2796705673, 148555288, 554857194, 2407195515, +- 26248257, 2952271312, 2251333922, 676868275, 3584149702, 2076793175, 1375858085, 4234771508, +- 2493785488, 986493953, 319029491, 3178008930, 1083533591, 4009621638, 3342158964, 1767759333, +- 3887577823, 1239362382, 1612160956, 3464433197, 864482904, 2649647049, 3022443323, 441336490, +- 1706844275, 3419730402, 3793503504, 1282724993, 2978819316, 535149925, 908921239, 2554697734, +- 380632892, 3100077741, 2433735263, 1063734222, 3265180603, 1828069930, 1161729752, 3948283721, +- 2207997677, 770953084, 71007118, 2857626143, 1470763626, 4190274555, 3490330377, 2120394392, +- 4035494306, 1591758899, 1999168705, 3644880208, 616140069, 2328960180, 2736367686, 225524183, +- }, +-}; ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } + +-static const uint8_t +-WUFFS_CRC32__IEEE_X86_SSE42_K1K2[16] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 212, 43, 68, 84, 1, 0, 0, 0, +- 150, 21, 228, 198, 1, 0, 0, 0, +-}; +- +-static const uint8_t +-WUFFS_CRC32__IEEE_X86_SSE42_K3K4[16] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 208, 151, 25, 117, 1, 0, 0, 0, +- 158, 0, 170, 204, 0, 0, 0, 0, +-}; +- +-static const uint8_t +-WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ[16] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 36, 97, 205, 99, 1, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +-}; +- +-static const uint8_t +-WUFFS_CRC32__IEEE_X86_SSE42_PXMU[16] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 65, 6, 113, 219, 1, 0, 0, 0, +- 65, 22, 1, 247, 1, 0, 0, 0, +-}; +- +-// ---------------- Private Initializer Prototypes +- +-// ---------------- Private Function Prototypes +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x); ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ goto exit; ++ } ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); ++ v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ label__outer__continue:; ++ while (true) { ++ while (self->private_impl.f_pending_pad > 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); ++ goto ok; ++ } ++ self->private_impl.f_pending_pad -= 1u; ++ iop_a_src += 1u; ++ } ++ while (true) { ++ if (self->private_impl.f_dst_x == self->private_impl.f_width) { ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; ++ if (self->private_impl.f_dst_y >= self->private_impl.f_height) { ++ if (self->private_impl.f_height > 0u) { ++ self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row; ++ } ++ goto label__outer__break; ++ } else if (self->private_impl.f_pad_per_row != 0u) { ++ self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row; ++ goto label__outer__continue; ++ } ++ } ++ v_p1_temp = ((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x)); ++ v_p1 = wuffs_base__u32__min(v_p1_temp, 256u); ++ v_p0 = 0u; ++ while (v_p0 < v_p1) { ++ if (self->private_impl.f_bits_per_pixel == 16u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { ++ break; ++ } ++ v_c32 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2u; ++ } else { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ break; ++ } ++ v_c32 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4u; ++ } ++ v_channel = 0u; ++ while (v_channel < 4u) { ++ if (self->private_impl.f_channel_num_bits[v_channel] == 0u) { ++ self->private_data.f_scratch[((8u * v_p0) + (2u * v_channel) + 0u)] = 255u; ++ self->private_data.f_scratch[((8u * v_p0) + (2u * v_channel) + 1u)] = 255u; ++ } else { ++ v_c = ((v_c32 & self->private_impl.f_channel_masks[v_channel]) >> self->private_impl.f_channel_shifts[v_channel]); ++ v_num_bits = ((uint32_t)(self->private_impl.f_channel_num_bits[v_channel])); ++ while (v_num_bits < 16u) { ++ v_c |= ((uint32_t)(v_c << v_num_bits)); ++ v_num_bits *= 2u; ++ } ++ v_c >>= (v_num_bits - 16u); ++ self->private_data.f_scratch[((8u * v_p0) + (2u * v_channel) + 0u)] = ((uint8_t)((v_c >> 0u))); ++ self->private_data.f_scratch[((8u * v_p0) + (2u * v_channel) + 1u)] = ((uint8_t)((v_c >> 8u))); ++ } ++ v_channel += 1u; ++ } ++ v_p0 += 1u; ++ } ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); ++ } ++ v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); ++ if (v_i >= ((uint64_t)(v_dst.len))) { ++ v_n = ((uint64_t)(v_p0)); ++ } else { ++ v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, (8u * v_p0))); ++ } ++ if (v_n == 0u) { ++ status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); ++ goto ok; ++ } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); ++ } ++ } ++ label__outer__break:; ++ status = wuffs_base__make_status(NULL); ++ goto ok; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up__choosy_default( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x); ++ ok: ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } + +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up_arm_crc32( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x); +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32) ++ return status; ++} + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up_x86_avx2( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_64) ++// -------- func bmp.decoder.swizzle_low_bit_depth + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up_x86_sse42( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- +-// ---------------- VTables +- +-const wuffs_base__hasher_u32__func_ptrs +-wuffs_crc32__ieee_hasher__func_ptrs_for__wuffs_base__hasher_u32 = { +- (uint32_t(*)(const void*))(&wuffs_crc32__ieee_hasher__checksum_u32), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_crc32__ieee_hasher__get_quirk), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_crc32__ieee_hasher__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- wuffs_base__slice_u8))(&wuffs_crc32__ieee_hasher__update), +- (uint32_t(*)(void*, +- wuffs_base__slice_u8))(&wuffs_crc32__ieee_hasher__update_u32), +-}; ++static wuffs_base__status ++wuffs_bmp__decoder__swizzle_low_bit_depth( ++ wuffs_bmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-// ---------------- Initializer Implementations ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row = 0; ++ wuffs_base__slice_u8 v_dst_palette = {0}; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint64_t v_i = 0; ++ uint64_t v_n = 0; ++ uint32_t v_p0 = 0; ++ uint32_t v_chunk_bits = 0; ++ uint32_t v_chunk_count = 0; ++ uint32_t v_pixels_per_chunk = 0; + +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_crc32__ieee_hasher__initialize( +- wuffs_crc32__ieee_hasher* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ goto exit; ++ } ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); ++ v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ while (true) { ++ if (self->private_impl.f_dst_x == self->private_impl.f_width) { ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc; ++ if (self->private_impl.f_dst_y >= self->private_impl.f_height) { ++ break; ++ } + } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); ++ } ++ v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); ++ if (v_i >= ((uint64_t)(v_dst.len))) { ++ if (self->private_impl.f_bits_per_pixel == 1u) { ++ v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 31u) / 32u); ++ v_pixels_per_chunk = 32u; ++ } else if (self->private_impl.f_bits_per_pixel == 2u) { ++ v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 15u) / 16u); ++ v_pixels_per_chunk = 16u; ++ } else { ++ v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 7u) / 8u); ++ v_pixels_per_chunk = 8u; ++ } ++ while ((v_chunk_count >= 64u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 256u)) { ++ iop_a_src += 256u; ++ self->private_impl.f_dst_x = wuffs_base__u32__min(self->private_impl.f_width, ((uint32_t)(self->private_impl.f_dst_x + (v_pixels_per_chunk * 64u)))); ++ v_chunk_count -= 64u; ++ } ++ while ((v_chunk_count >= 8u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 32u)) { ++ iop_a_src += 32u; ++ self->private_impl.f_dst_x = wuffs_base__u32__min(self->private_impl.f_width, ((uint32_t)(self->private_impl.f_dst_x + (v_pixels_per_chunk * 8u)))); ++ v_chunk_count -= 8u; ++ } ++ while (v_chunk_count > 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); ++ goto ok; ++ } ++ iop_a_src += 4u; ++ self->private_impl.f_dst_x = wuffs_base__u32__min(self->private_impl.f_width, ((uint32_t)(self->private_impl.f_dst_x + (v_pixels_per_chunk * 1u)))); ++ v_chunk_count -= 1u; ++ } ++ continue; ++ } ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i); ++ v_p0 = 0u; ++ if (self->private_impl.f_bits_per_pixel == 1u) { ++ v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 31u) / 32u); ++ v_chunk_count = wuffs_base__u32__min(v_chunk_count, 16u); ++ while ((v_chunk_count > 0u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4u)) { ++ v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4u; ++ self->private_data.f_scratch[(v_p0 + 0u)] = ((uint8_t)((1u & (v_chunk_bits >> 31u)))); ++ self->private_data.f_scratch[(v_p0 + 1u)] = ((uint8_t)((1u & (v_chunk_bits >> 30u)))); ++ self->private_data.f_scratch[(v_p0 + 2u)] = ((uint8_t)((1u & (v_chunk_bits >> 29u)))); ++ self->private_data.f_scratch[(v_p0 + 3u)] = ((uint8_t)((1u & (v_chunk_bits >> 28u)))); ++ self->private_data.f_scratch[(v_p0 + 4u)] = ((uint8_t)((1u & (v_chunk_bits >> 27u)))); ++ self->private_data.f_scratch[(v_p0 + 5u)] = ((uint8_t)((1u & (v_chunk_bits >> 26u)))); ++ self->private_data.f_scratch[(v_p0 + 6u)] = ((uint8_t)((1u & (v_chunk_bits >> 25u)))); ++ self->private_data.f_scratch[(v_p0 + 7u)] = ((uint8_t)((1u & (v_chunk_bits >> 24u)))); ++ self->private_data.f_scratch[(v_p0 + 8u)] = ((uint8_t)((1u & (v_chunk_bits >> 23u)))); ++ self->private_data.f_scratch[(v_p0 + 9u)] = ((uint8_t)((1u & (v_chunk_bits >> 22u)))); ++ self->private_data.f_scratch[(v_p0 + 10u)] = ((uint8_t)((1u & (v_chunk_bits >> 21u)))); ++ self->private_data.f_scratch[(v_p0 + 11u)] = ((uint8_t)((1u & (v_chunk_bits >> 20u)))); ++ self->private_data.f_scratch[(v_p0 + 12u)] = ((uint8_t)((1u & (v_chunk_bits >> 19u)))); ++ self->private_data.f_scratch[(v_p0 + 13u)] = ((uint8_t)((1u & (v_chunk_bits >> 18u)))); ++ self->private_data.f_scratch[(v_p0 + 14u)] = ((uint8_t)((1u & (v_chunk_bits >> 17u)))); ++ self->private_data.f_scratch[(v_p0 + 15u)] = ((uint8_t)((1u & (v_chunk_bits >> 16u)))); ++ self->private_data.f_scratch[(v_p0 + 16u)] = ((uint8_t)((1u & (v_chunk_bits >> 15u)))); ++ self->private_data.f_scratch[(v_p0 + 17u)] = ((uint8_t)((1u & (v_chunk_bits >> 14u)))); ++ self->private_data.f_scratch[(v_p0 + 18u)] = ((uint8_t)((1u & (v_chunk_bits >> 13u)))); ++ self->private_data.f_scratch[(v_p0 + 19u)] = ((uint8_t)((1u & (v_chunk_bits >> 12u)))); ++ self->private_data.f_scratch[(v_p0 + 20u)] = ((uint8_t)((1u & (v_chunk_bits >> 11u)))); ++ self->private_data.f_scratch[(v_p0 + 21u)] = ((uint8_t)((1u & (v_chunk_bits >> 10u)))); ++ self->private_data.f_scratch[(v_p0 + 22u)] = ((uint8_t)((1u & (v_chunk_bits >> 9u)))); ++ self->private_data.f_scratch[(v_p0 + 23u)] = ((uint8_t)((1u & (v_chunk_bits >> 8u)))); ++ self->private_data.f_scratch[(v_p0 + 24u)] = ((uint8_t)((1u & (v_chunk_bits >> 7u)))); ++ self->private_data.f_scratch[(v_p0 + 25u)] = ((uint8_t)((1u & (v_chunk_bits >> 6u)))); ++ self->private_data.f_scratch[(v_p0 + 26u)] = ((uint8_t)((1u & (v_chunk_bits >> 5u)))); ++ self->private_data.f_scratch[(v_p0 + 27u)] = ((uint8_t)((1u & (v_chunk_bits >> 4u)))); ++ self->private_data.f_scratch[(v_p0 + 28u)] = ((uint8_t)((1u & (v_chunk_bits >> 3u)))); ++ self->private_data.f_scratch[(v_p0 + 29u)] = ((uint8_t)((1u & (v_chunk_bits >> 2u)))); ++ self->private_data.f_scratch[(v_p0 + 30u)] = ((uint8_t)((1u & (v_chunk_bits >> 1u)))); ++ self->private_data.f_scratch[(v_p0 + 31u)] = ((uint8_t)((1u & (v_chunk_bits >> 0u)))); ++ v_p0 = ((v_p0 & 511u) + 32u); ++ v_chunk_count -= 1u; ++ } ++ } else if (self->private_impl.f_bits_per_pixel == 2u) { ++ v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 15u) / 16u); ++ v_chunk_count = wuffs_base__u32__min(v_chunk_count, 32u); ++ while ((v_chunk_count > 0u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4u)) { ++ v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4u; ++ self->private_data.f_scratch[(v_p0 + 0u)] = ((uint8_t)((3u & (v_chunk_bits >> 30u)))); ++ self->private_data.f_scratch[(v_p0 + 1u)] = ((uint8_t)((3u & (v_chunk_bits >> 28u)))); ++ self->private_data.f_scratch[(v_p0 + 2u)] = ((uint8_t)((3u & (v_chunk_bits >> 26u)))); ++ self->private_data.f_scratch[(v_p0 + 3u)] = ((uint8_t)((3u & (v_chunk_bits >> 24u)))); ++ self->private_data.f_scratch[(v_p0 + 4u)] = ((uint8_t)((3u & (v_chunk_bits >> 22u)))); ++ self->private_data.f_scratch[(v_p0 + 5u)] = ((uint8_t)((3u & (v_chunk_bits >> 20u)))); ++ self->private_data.f_scratch[(v_p0 + 6u)] = ((uint8_t)((3u & (v_chunk_bits >> 18u)))); ++ self->private_data.f_scratch[(v_p0 + 7u)] = ((uint8_t)((3u & (v_chunk_bits >> 16u)))); ++ self->private_data.f_scratch[(v_p0 + 8u)] = ((uint8_t)((3u & (v_chunk_bits >> 14u)))); ++ self->private_data.f_scratch[(v_p0 + 9u)] = ((uint8_t)((3u & (v_chunk_bits >> 12u)))); ++ self->private_data.f_scratch[(v_p0 + 10u)] = ((uint8_t)((3u & (v_chunk_bits >> 10u)))); ++ self->private_data.f_scratch[(v_p0 + 11u)] = ((uint8_t)((3u & (v_chunk_bits >> 8u)))); ++ self->private_data.f_scratch[(v_p0 + 12u)] = ((uint8_t)((3u & (v_chunk_bits >> 6u)))); ++ self->private_data.f_scratch[(v_p0 + 13u)] = ((uint8_t)((3u & (v_chunk_bits >> 4u)))); ++ self->private_data.f_scratch[(v_p0 + 14u)] = ((uint8_t)((3u & (v_chunk_bits >> 2u)))); ++ self->private_data.f_scratch[(v_p0 + 15u)] = ((uint8_t)((3u & (v_chunk_bits >> 0u)))); ++ v_p0 = ((v_p0 & 511u) + 16u); ++ v_chunk_count -= 1u; ++ } + } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 7u) / 8u); ++ v_chunk_count = wuffs_base__u32__min(v_chunk_count, 64u); ++ while ((v_chunk_count > 0u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4u)) { ++ v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4u; ++ self->private_data.f_scratch[(v_p0 + 0u)] = ((uint8_t)((15u & (v_chunk_bits >> 28u)))); ++ self->private_data.f_scratch[(v_p0 + 1u)] = ((uint8_t)((15u & (v_chunk_bits >> 24u)))); ++ self->private_data.f_scratch[(v_p0 + 2u)] = ((uint8_t)((15u & (v_chunk_bits >> 20u)))); ++ self->private_data.f_scratch[(v_p0 + 3u)] = ((uint8_t)((15u & (v_chunk_bits >> 16u)))); ++ self->private_data.f_scratch[(v_p0 + 4u)] = ((uint8_t)((15u & (v_chunk_bits >> 12u)))); ++ self->private_data.f_scratch[(v_p0 + 5u)] = ((uint8_t)((15u & (v_chunk_bits >> 8u)))); ++ self->private_data.f_scratch[(v_p0 + 6u)] = ((uint8_t)((15u & (v_chunk_bits >> 4u)))); ++ self->private_data.f_scratch[(v_p0 + 7u)] = ((uint8_t)((15u & (v_chunk_bits >> 0u)))); ++ v_p0 = ((v_p0 & 511u) + 8u); ++ v_chunk_count -= 1u; ++ } ++ } ++ v_p0 = wuffs_base__u32__min(v_p0, wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x)); ++ v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, v_p0)); ++ if (v_n == 0u) { ++ status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read); ++ goto ok; + } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); + } ++ status = wuffs_base__make_status(NULL); ++ goto ok; + +- self->private_impl.choosy_up = &wuffs_crc32__ieee_hasher__up__choosy_default; ++ ok: ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } + +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name = +- wuffs_base__hasher_u32__vtable_name; +- self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers = +- (const void*)(&wuffs_crc32__ieee_hasher__func_ptrs_for__wuffs_base__hasher_u32); +- return wuffs_base__make_status(NULL); ++ return status; + } + +-wuffs_crc32__ieee_hasher* +-wuffs_crc32__ieee_hasher__alloc(void) { +- wuffs_crc32__ieee_hasher* x = +- (wuffs_crc32__ieee_hasher*)(calloc(sizeof(wuffs_crc32__ieee_hasher), 1)); +- if (!x) { +- return NULL; ++// -------- func bmp.decoder.frame_dirty_rect ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_bmp__decoder__frame_dirty_rect( ++ const wuffs_bmp__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); + } +- if (wuffs_crc32__ieee_hasher__initialize( +- x, sizeof(wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); + } +- return x; +-} + +-size_t +-sizeof__wuffs_crc32__ieee_hasher(void) { +- return sizeof(wuffs_crc32__ieee_hasher); ++ return wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height); + } + +-// ---------------- Function Implementations +- +-// -------- func crc32.ieee_hasher.get_quirk ++// -------- func bmp.decoder.num_animation_loops + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_crc32__ieee_hasher__get_quirk( +- const wuffs_crc32__ieee_hasher* self, +- uint32_t a_key) { ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_bmp__decoder__num_animation_loops( ++ const wuffs_bmp__decoder* self) { + if (!self) { + return 0; + } +@@ -33524,709 +33654,531 @@ wuffs_crc32__ieee_hasher__get_quirk( + return 0u; + } + +-// -------- func crc32.ieee_hasher.set_quirk ++// -------- func bmp.decoder.num_decoded_frame_configs + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_crc32__ieee_hasher__set_quirk( +- wuffs_crc32__ieee_hasher* self, +- uint32_t a_key, +- uint64_t a_value) { ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_bmp__decoder__num_decoded_frame_configs( ++ const wuffs_bmp__decoder* self) { + if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ return 0; + } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } + +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ if (self->private_impl.f_call_sequence > 32u) { ++ return 1u; ++ } ++ return 0u; + } + +-// -------- func crc32.ieee_hasher.update ++// -------- func bmp.decoder.num_decoded_frames + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__update( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x) { ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_bmp__decoder__num_decoded_frames( ++ const wuffs_bmp__decoder* self) { + if (!self) { +- return wuffs_base__make_empty_struct(); ++ return 0; + } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } + +- if (self->private_impl.f_state == 0u) { +- self->private_impl.choosy_up = ( +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32) +- wuffs_base__cpu_arch__have_arm_crc32() ? &wuffs_crc32__ieee_hasher__up_arm_crc32 : +-#endif +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +- wuffs_base__cpu_arch__have_x86_avx2() ? &wuffs_crc32__ieee_hasher__up_x86_avx2 : +-#endif +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_crc32__ieee_hasher__up_x86_sse42 : +-#endif +- self->private_impl.choosy_up); ++ if (self->private_impl.f_call_sequence > 64u) { ++ return 1u; + } +- wuffs_crc32__ieee_hasher__up(self, a_x); +- return wuffs_base__make_empty_struct(); ++ return 0u; + } + +-// -------- func crc32.ieee_hasher.update_u32 ++// -------- func bmp.decoder.restart_frame + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_crc32__ieee_hasher__update_u32( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_bmp__decoder__restart_frame( ++ wuffs_bmp__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position) { + if (!self) { +- return 0; ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return 0; ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } + +- wuffs_crc32__ieee_hasher__update(self, a_x); +- return self->private_impl.f_state; ++ if (self->private_impl.f_call_sequence < 32u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } ++ if (a_index != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_call_sequence = 40u; ++ self->private_impl.f_frame_config_io_position = a_io_position; ++ return wuffs_base__make_status(NULL); + } + +-// -------- func crc32.ieee_hasher.up ++// -------- func bmp.decoder.set_report_metadata + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x) { +- return (*self->private_impl.choosy_up)(self, a_x); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_bmp__decoder__set_report_metadata( ++ wuffs_bmp__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_base__make_empty_struct(); + } + ++// -------- func bmp.decoder.tell_me_more ++ + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up__choosy_default( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x) { +- uint32_t v_s = 0; +- wuffs_base__slice_u8 v_p = {0}; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_bmp__decoder__tell_me_more( ++ wuffs_bmp__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- v_s = (4294967295u ^ self->private_impl.f_state); +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 16; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32); +- while (v_p.ptr < i_end0_p) { +- v_s ^= ((((uint32_t)(v_p.ptr[0u])) << 0u) | +- (((uint32_t)(v_p.ptr[1u])) << 8u) | +- (((uint32_t)(v_p.ptr[2u])) << 16u) | +- (((uint32_t)(v_p.ptr[3u])) << 24u)); +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][v_p.ptr[15u]] ^ +- WUFFS_CRC32__IEEE_TABLE[1u][v_p.ptr[14u]] ^ +- WUFFS_CRC32__IEEE_TABLE[2u][v_p.ptr[13u]] ^ +- WUFFS_CRC32__IEEE_TABLE[3u][v_p.ptr[12u]] ^ +- WUFFS_CRC32__IEEE_TABLE[4u][v_p.ptr[11u]] ^ +- WUFFS_CRC32__IEEE_TABLE[5u][v_p.ptr[10u]] ^ +- WUFFS_CRC32__IEEE_TABLE[6u][v_p.ptr[9u]] ^ +- WUFFS_CRC32__IEEE_TABLE[7u][v_p.ptr[8u]] ^ +- WUFFS_CRC32__IEEE_TABLE[8u][v_p.ptr[7u]] ^ +- WUFFS_CRC32__IEEE_TABLE[9u][v_p.ptr[6u]] ^ +- WUFFS_CRC32__IEEE_TABLE[10u][v_p.ptr[5u]] ^ +- WUFFS_CRC32__IEEE_TABLE[11u][v_p.ptr[4u]] ^ +- WUFFS_CRC32__IEEE_TABLE[12u][(255u & (v_s >> 24u))] ^ +- WUFFS_CRC32__IEEE_TABLE[13u][(255u & (v_s >> 16u))] ^ +- WUFFS_CRC32__IEEE_TABLE[14u][(255u & (v_s >> 8u))] ^ +- WUFFS_CRC32__IEEE_TABLE[15u][(255u & (v_s >> 0u))]); +- v_p.ptr += 16; +- v_s ^= ((((uint32_t)(v_p.ptr[0u])) << 0u) | +- (((uint32_t)(v_p.ptr[1u])) << 8u) | +- (((uint32_t)(v_p.ptr[2u])) << 16u) | +- (((uint32_t)(v_p.ptr[3u])) << 24u)); +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][v_p.ptr[15u]] ^ +- WUFFS_CRC32__IEEE_TABLE[1u][v_p.ptr[14u]] ^ +- WUFFS_CRC32__IEEE_TABLE[2u][v_p.ptr[13u]] ^ +- WUFFS_CRC32__IEEE_TABLE[3u][v_p.ptr[12u]] ^ +- WUFFS_CRC32__IEEE_TABLE[4u][v_p.ptr[11u]] ^ +- WUFFS_CRC32__IEEE_TABLE[5u][v_p.ptr[10u]] ^ +- WUFFS_CRC32__IEEE_TABLE[6u][v_p.ptr[9u]] ^ +- WUFFS_CRC32__IEEE_TABLE[7u][v_p.ptr[8u]] ^ +- WUFFS_CRC32__IEEE_TABLE[8u][v_p.ptr[7u]] ^ +- WUFFS_CRC32__IEEE_TABLE[9u][v_p.ptr[6u]] ^ +- WUFFS_CRC32__IEEE_TABLE[10u][v_p.ptr[5u]] ^ +- WUFFS_CRC32__IEEE_TABLE[11u][v_p.ptr[4u]] ^ +- WUFFS_CRC32__IEEE_TABLE[12u][(255u & (v_s >> 24u))] ^ +- WUFFS_CRC32__IEEE_TABLE[13u][(255u & (v_s >> 16u))] ^ +- WUFFS_CRC32__IEEE_TABLE[14u][(255u & (v_s >> 8u))] ^ +- WUFFS_CRC32__IEEE_TABLE[15u][(255u & (v_s >> 0u))]); +- v_p.ptr += 16; +- } +- v_p.len = 16; +- uint8_t* i_end1_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 16) * 16); +- while (v_p.ptr < i_end1_p) { +- v_s ^= ((((uint32_t)(v_p.ptr[0u])) << 0u) | +- (((uint32_t)(v_p.ptr[1u])) << 8u) | +- (((uint32_t)(v_p.ptr[2u])) << 16u) | +- (((uint32_t)(v_p.ptr[3u])) << 24u)); +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][v_p.ptr[15u]] ^ +- WUFFS_CRC32__IEEE_TABLE[1u][v_p.ptr[14u]] ^ +- WUFFS_CRC32__IEEE_TABLE[2u][v_p.ptr[13u]] ^ +- WUFFS_CRC32__IEEE_TABLE[3u][v_p.ptr[12u]] ^ +- WUFFS_CRC32__IEEE_TABLE[4u][v_p.ptr[11u]] ^ +- WUFFS_CRC32__IEEE_TABLE[5u][v_p.ptr[10u]] ^ +- WUFFS_CRC32__IEEE_TABLE[6u][v_p.ptr[9u]] ^ +- WUFFS_CRC32__IEEE_TABLE[7u][v_p.ptr[8u]] ^ +- WUFFS_CRC32__IEEE_TABLE[8u][v_p.ptr[7u]] ^ +- WUFFS_CRC32__IEEE_TABLE[9u][v_p.ptr[6u]] ^ +- WUFFS_CRC32__IEEE_TABLE[10u][v_p.ptr[5u]] ^ +- WUFFS_CRC32__IEEE_TABLE[11u][v_p.ptr[4u]] ^ +- WUFFS_CRC32__IEEE_TABLE[12u][(255u & (v_s >> 24u))] ^ +- WUFFS_CRC32__IEEE_TABLE[13u][(255u & (v_s >> 16u))] ^ +- WUFFS_CRC32__IEEE_TABLE[14u][(255u & (v_s >> 8u))] ^ +- WUFFS_CRC32__IEEE_TABLE[15u][(255u & (v_s >> 0u))]); +- v_p.ptr += 16; +- } +- v_p.len = 1; +- uint8_t* i_end2_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end2_p) { +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][(((uint8_t)(v_s)) ^ v_p.ptr[0u])] ^ (v_s >> 8u)); +- v_p.ptr += 1; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_tell_me_more; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_bmp__decoder__do_tell_me_more(self, a_dst, a_minfo, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_bmp__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } +- v_p.len = 0; ++ ++ ok: ++ self->private_impl.p_tell_me_more = 0; ++ goto exit; + } +- self->private_impl.f_state = (4294967295u ^ v_s); +- return wuffs_base__make_empty_struct(); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_tell_me_more = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; + } + +-// -------- func crc32.ieee_hasher.checksum_u32 ++// -------- func bmp.decoder.do_tell_me_more + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_crc32__ieee_hasher__checksum_u32( +- const wuffs_crc32__ieee_hasher* self) { +- if (!self) { +- return 0; ++static wuffs_base__status ++wuffs_bmp__decoder__do_tell_me_more( ++ wuffs_bmp__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ if (self->private_impl.f_io_redirect_fourcc <= 1u) { ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); ++ goto exit; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ if (a_minfo != NULL) { ++ wuffs_base__more_information__set(a_minfo, ++ 1u, ++ self->private_impl.f_io_redirect_fourcc, ++ 0u, ++ self->private_impl.f_io_redirect_pos, ++ 18446744073709551615u); + } ++ self->private_impl.f_io_redirect_fourcc = 1u; + +- return self->private_impl.f_state; ++ goto ok; ++ ok: ++ goto exit; ++ exit: ++ return status; + } + +-// ‼ WUFFS MULTI-FILE SECTION +arm_crc32 +-// -------- func crc32.ieee_hasher.up_arm_crc32 ++// -------- func bmp.decoder.workbuf_len + +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32) + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up_arm_crc32( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x) { +- wuffs_base__slice_u8 v_p = {0}; +- uint32_t v_s = 0; +- +- v_s = (4294967295u ^ self->private_impl.f_state); +- while ((((uint64_t)(a_x.len)) > 0u) && ((15u & ((uint32_t)(0xFFFu & (uintptr_t)(a_x.ptr)))) != 0u)) { +- v_s = __crc32b(v_s, a_x.ptr[0u]); +- a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_bmp__decoder__workbuf_len( ++ const wuffs_bmp__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); + } +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 8; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 128) * 128); +- while (v_p.ptr < i_end0_p) { +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- } +- v_p.len = 8; +- uint8_t* i_end1_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8); +- while (v_p.ptr < i_end1_p) { +- v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); +- v_p.ptr += 8; +- } +- v_p.len = 1; +- uint8_t* i_end2_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end2_p) { +- v_s = __crc32b(v_s, v_p.ptr[0u]); +- v_p.ptr += 1; +- } +- v_p.len = 0; ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); + } +- self->private_impl.f_state = (4294967295u ^ v_s); +- return wuffs_base__make_empty_struct(); ++ ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32) +-// ‼ WUFFS MULTI-FILE SECTION -arm_crc32 + +-// ‼ WUFFS MULTI-FILE SECTION +x86_avx2 +-// -------- func crc32.ieee_hasher.up_x86_avx2 ++// -------- func bmp.decoder.read_palette + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up_x86_avx2( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x) { +- uint32_t v_s = 0; +- wuffs_base__slice_u8 v_p = {0}; +- __m128i v_k = {0}; +- __m128i v_x0 = {0}; +- __m128i v_x1 = {0}; +- __m128i v_x2 = {0}; +- __m128i v_x3 = {0}; +- __m128i v_y0 = {0}; +- __m128i v_y1 = {0}; +- __m128i v_y2 = {0}; +- __m128i v_y3 = {0}; +- uint64_t v_tail_index = 0; ++static wuffs_base__status ++wuffs_bmp__decoder__read_palette( ++ wuffs_bmp__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- v_s = (4294967295u ^ self->private_impl.f_state); +- while ((((uint64_t)(a_x.len)) > 0u) && ((15u & ((uint32_t)(0xFFFu & (uintptr_t)(a_x.ptr)))) != 0u)) { +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][(((uint8_t)(v_s)) ^ a_x.ptr[0u])] ^ (v_s >> 8u)); +- a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); ++ uint32_t v_i = 0; ++ uint32_t v_argb = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- if (((uint64_t)(a_x.len)) < 64u) { +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 1; +- uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end0_p) { +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][(((uint8_t)(v_s)) ^ v_p.ptr[0u])] ^ (v_s >> 8u)); +- v_p.ptr += 1; ++ ++ uint32_t coro_susp_point = self->private_impl.p_read_palette; ++ if (coro_susp_point) { ++ v_i = self->private_data.s_read_palette.v_i; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_bitmap_info_len == 12u) { ++ while ((v_i < 256u) && (self->private_impl.f_padding >= 3u)) { ++ self->private_impl.f_padding -= 3u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { ++ t_0 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); ++ iop_a_src += 3; ++ } else { ++ self->private_data.s_read_palette.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_read_palette.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 16) { ++ t_0 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ v_argb = t_0; ++ } ++ v_argb |= 4278190080u; ++ self->private_data.f_src_palette[((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); ++ self->private_data.f_src_palette[((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); ++ self->private_data.f_src_palette[((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); ++ self->private_data.f_src_palette[((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); ++ v_i += 1u; ++ } ++ } else { ++ while ((v_i < 256u) && (self->private_impl.f_padding >= 4u)) { ++ self->private_impl.f_padding -= 4u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_read_palette.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_read_palette.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ v_argb = t_1; ++ } ++ v_argb |= 4278190080u; ++ self->private_data.f_src_palette[((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); ++ self->private_data.f_src_palette[((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); ++ self->private_data.f_src_palette[((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); ++ self->private_data.f_src_palette[((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); ++ v_i += 1u; + } +- v_p.len = 0; + } +- self->private_impl.f_state = (4294967295u ^ v_s); +- return wuffs_base__make_empty_struct(); +- } +- v_x0 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u)); +- v_x1 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u)); +- v_x2 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32u)); +- v_x3 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48u)); +- v_x0 = _mm_xor_si128(v_x0, _mm_cvtsi32_si128((int32_t)(v_s))); +- v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K1K2)); +- { +- wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, 64u); +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 64; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 64) * 64); +- while (v_p.ptr < i_end0_p) { +- v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_y1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0u)); +- v_y2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(0u)); +- v_y3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(0u)); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17u)); +- v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(17u)); +- v_x2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(17u)); +- v_x3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(17u)); +- v_x0 = _mm_xor_si128(_mm_xor_si128(v_x0, v_y0), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 0u))); +- v_x1 = _mm_xor_si128(_mm_xor_si128(v_x1, v_y1), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16u))); +- v_x2 = _mm_xor_si128(_mm_xor_si128(v_x2, v_y2), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 32u))); +- v_x3 = _mm_xor_si128(_mm_xor_si128(v_x3, v_y3), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 48u))); +- v_p.ptr += 64; ++ while (v_i < 256u) { ++ self->private_data.f_src_palette[((4u * v_i) + 0u)] = 0u; ++ self->private_data.f_src_palette[((4u * v_i) + 1u)] = 0u; ++ self->private_data.f_src_palette[((4u * v_i) + 2u)] = 0u; ++ self->private_data.f_src_palette[((4u * v_i) + 3u)] = 255u; ++ v_i += 1u; + } +- v_p.len = 0; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_read_palette = 0; ++ goto exit; + } +- v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K3K4)); +- v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17u)); +- v_x0 = _mm_xor_si128(v_x0, v_x1); +- v_x0 = _mm_xor_si128(v_x0, v_y0); +- v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17u)); +- v_x0 = _mm_xor_si128(v_x0, v_x2); +- v_x0 = _mm_xor_si128(v_x0, v_y0); +- v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17u)); +- v_x0 = _mm_xor_si128(v_x0, v_x3); +- v_x0 = _mm_xor_si128(v_x0, v_y0); +- v_x1 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(16u)); +- v_x2 = _mm_set_epi32((int32_t)(0u), (int32_t)(4294967295u), (int32_t)(0u), (int32_t)(4294967295u)); +- v_x0 = _mm_srli_si128(v_x0, (int32_t)(8u)); +- v_x0 = _mm_xor_si128(v_x0, v_x1); +- v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ)); +- v_x1 = _mm_srli_si128(v_x0, (int32_t)(4u)); +- v_x0 = _mm_and_si128(v_x0, v_x2); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_x0 = _mm_xor_si128(v_x0, v_x1); +- v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_PXMU)); +- v_x1 = _mm_and_si128(v_x0, v_x2); +- v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(16u)); +- v_x1 = _mm_and_si128(v_x1, v_x2); +- v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0u)); +- v_x0 = _mm_xor_si128(v_x0, v_x1); +- v_s = ((uint32_t)(_mm_extract_epi32(v_x0, (int32_t)(1u)))); +- v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551552u); +- if (v_tail_index < ((uint64_t)(a_x.len))) { +- { +- wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index); +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 1; +- uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end0_p) { +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][(((uint8_t)(v_s)) ^ v_p.ptr[0u])] ^ (v_s >> 8u)); +- v_p.ptr += 1; +- } +- v_p.len = 0; +- } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_read_palette = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_read_palette.v_i = v_i; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- self->private_impl.f_state = (4294967295u ^ v_s); +- return wuffs_base__make_empty_struct(); ++ ++ return status; + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_64) +-// ‼ WUFFS MULTI-FILE SECTION -x86_avx2 + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-// -------- func crc32.ieee_hasher.up_x86_sse42 ++// -------- func bmp.decoder.process_masks + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_crc32__ieee_hasher__up_x86_sse42( +- wuffs_crc32__ieee_hasher* self, +- wuffs_base__slice_u8 a_x) { +- uint32_t v_s = 0; +- wuffs_base__slice_u8 v_p = {0}; +- __m128i v_k = {0}; +- __m128i v_x0 = {0}; +- __m128i v_x1 = {0}; +- __m128i v_x2 = {0}; +- __m128i v_x3 = {0}; +- __m128i v_y0 = {0}; +- __m128i v_y1 = {0}; +- __m128i v_y2 = {0}; +- __m128i v_y3 = {0}; +- uint64_t v_tail_index = 0; ++static wuffs_base__status ++wuffs_bmp__decoder__process_masks( ++ wuffs_bmp__decoder* self) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- v_s = (4294967295u ^ self->private_impl.f_state); +- while ((((uint64_t)(a_x.len)) > 0u) && ((15u & ((uint32_t)(0xFFFu & (uintptr_t)(a_x.ptr)))) != 0u)) { +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][(((uint8_t)(v_s)) ^ a_x.ptr[0u])] ^ (v_s >> 8u)); +- a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); +- } +- if (((uint64_t)(a_x.len)) < 64u) { +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 1; +- uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end0_p) { +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][(((uint8_t)(v_s)) ^ v_p.ptr[0u])] ^ (v_s >> 8u)); +- v_p.ptr += 1; ++ uint32_t v_i = 0; ++ uint32_t v_mask = 0; ++ uint32_t v_n = 0; ++ ++ while (v_i < 4u) { ++ v_mask = self->private_impl.f_channel_masks[v_i]; ++ if (v_mask != 0u) { ++ v_n = 0u; ++ while ((v_mask & 1u) == 0u) { ++ v_n += 1u; ++ v_mask >>= 1u; + } +- v_p.len = 0; +- } +- self->private_impl.f_state = (4294967295u ^ v_s); +- return wuffs_base__make_empty_struct(); +- } +- v_x0 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u)); +- v_x1 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u)); +- v_x2 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32u)); +- v_x3 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48u)); +- v_x0 = _mm_xor_si128(v_x0, _mm_cvtsi32_si128((int32_t)(v_s))); +- v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K1K2)); +- { +- wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, 64u); +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 64; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 64) * 64); +- while (v_p.ptr < i_end0_p) { +- v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_y1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0u)); +- v_y2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(0u)); +- v_y3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(0u)); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17u)); +- v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(17u)); +- v_x2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(17u)); +- v_x3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(17u)); +- v_x0 = _mm_xor_si128(_mm_xor_si128(v_x0, v_y0), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 0u))); +- v_x1 = _mm_xor_si128(_mm_xor_si128(v_x1, v_y1), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16u))); +- v_x2 = _mm_xor_si128(_mm_xor_si128(v_x2, v_y2), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 32u))); +- v_x3 = _mm_xor_si128(_mm_xor_si128(v_x3, v_y3), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 48u))); +- v_p.ptr += 64; +- } +- v_p.len = 0; +- } +- v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K3K4)); +- v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17u)); +- v_x0 = _mm_xor_si128(v_x0, v_x1); +- v_x0 = _mm_xor_si128(v_x0, v_y0); +- v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17u)); +- v_x0 = _mm_xor_si128(v_x0, v_x2); +- v_x0 = _mm_xor_si128(v_x0, v_y0); +- v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17u)); +- v_x0 = _mm_xor_si128(v_x0, v_x3); +- v_x0 = _mm_xor_si128(v_x0, v_y0); +- v_x1 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(16u)); +- v_x2 = _mm_set_epi32((int32_t)(0u), (int32_t)(4294967295u), (int32_t)(0u), (int32_t)(4294967295u)); +- v_x0 = _mm_srli_si128(v_x0, (int32_t)(8u)); +- v_x0 = _mm_xor_si128(v_x0, v_x1); +- v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ)); +- v_x1 = _mm_srli_si128(v_x0, (int32_t)(4u)); +- v_x0 = _mm_and_si128(v_x0, v_x2); +- v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0u)); +- v_x0 = _mm_xor_si128(v_x0, v_x1); +- v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_PXMU)); +- v_x1 = _mm_and_si128(v_x0, v_x2); +- v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(16u)); +- v_x1 = _mm_and_si128(v_x1, v_x2); +- v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0u)); +- v_x0 = _mm_xor_si128(v_x0, v_x1); +- v_s = ((uint32_t)(_mm_extract_epi32(v_x0, (int32_t)(1u)))); +- v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551552u); +- if (v_tail_index < ((uint64_t)(a_x.len))) { +- { +- wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index); +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 1; +- uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end0_p) { +- v_s = (WUFFS_CRC32__IEEE_TABLE[0u][(((uint8_t)(v_s)) ^ v_p.ptr[0u])] ^ (v_s >> 8u)); +- v_p.ptr += 1; ++ self->private_impl.f_channel_shifts[v_i] = ((uint8_t)((v_n & 31u))); ++ v_n = 0u; ++ while ((v_mask & 1u) == 1u) { ++ v_n += 1u; ++ v_mask >>= 1u; + } +- v_p.len = 0; ++ if ((v_mask != 0u) || (v_n > 32u)) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; ++ } ++ self->private_impl.f_channel_num_bits[v_i] = ((uint8_t)(v_n)); ++ } else if (v_i != 3u) { ++ status = wuffs_base__make_status(wuffs_bmp__error__bad_header); ++ goto exit; + } ++ v_i += 1u; + } +- self->private_impl.f_state = (4294967295u ^ v_s); +- return wuffs_base__make_empty_struct(); ++ ++ goto ok; ++ ok: ++ goto exit; ++ exit: ++ return status; + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BZIP2) + + // ---------------- Status Codes Implementations + +-const char wuffs_deflate__error__bad_huffman_code_over_subscribed[] = "#deflate: bad Huffman code (over-subscribed)"; +-const char wuffs_deflate__error__bad_huffman_code_under_subscribed[] = "#deflate: bad Huffman code (under-subscribed)"; +-const char wuffs_deflate__error__bad_huffman_code_length_count[] = "#deflate: bad Huffman code length count"; +-const char wuffs_deflate__error__bad_huffman_code_length_repetition[] = "#deflate: bad Huffman code length repetition"; +-const char wuffs_deflate__error__bad_huffman_code[] = "#deflate: bad Huffman code"; +-const char wuffs_deflate__error__bad_huffman_minimum_code_length[] = "#deflate: bad Huffman minimum code length"; +-const char wuffs_deflate__error__bad_block[] = "#deflate: bad block"; +-const char wuffs_deflate__error__bad_distance[] = "#deflate: bad distance"; +-const char wuffs_deflate__error__bad_distance_code_count[] = "#deflate: bad distance code count"; +-const char wuffs_deflate__error__bad_literal_length_code_count[] = "#deflate: bad literal/length code count"; +-const char wuffs_deflate__error__inconsistent_stored_block_length[] = "#deflate: inconsistent stored block length"; +-const char wuffs_deflate__error__missing_end_of_block_code[] = "#deflate: missing end-of-block code"; +-const char wuffs_deflate__error__no_huffman_codes[] = "#deflate: no Huffman codes"; +-const char wuffs_deflate__error__truncated_input[] = "#deflate: truncated input"; +-const char wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state[] = "#deflate: internal error: inconsistent Huffman decoder state"; +-const char wuffs_deflate__error__internal_error_inconsistent_i_o[] = "#deflate: internal error: inconsistent I/O"; +-const char wuffs_deflate__error__internal_error_inconsistent_distance[] = "#deflate: internal error: inconsistent distance"; +-const char wuffs_deflate__error__internal_error_inconsistent_n_bits[] = "#deflate: internal error: inconsistent n_bits"; ++const char wuffs_bzip2__error__bad_huffman_code_over_subscribed[] = "#bzip2: bad Huffman code (over-subscribed)"; ++const char wuffs_bzip2__error__bad_huffman_code_under_subscribed[] = "#bzip2: bad Huffman code (under-subscribed)"; ++const char wuffs_bzip2__error__bad_block_header[] = "#bzip2: bad block header"; ++const char wuffs_bzip2__error__bad_block_length[] = "#bzip2: bad block length"; ++const char wuffs_bzip2__error__bad_checksum[] = "#bzip2: bad checksum"; ++const char wuffs_bzip2__error__bad_header[] = "#bzip2: bad header"; ++const char wuffs_bzip2__error__bad_number_of_sections[] = "#bzip2: bad number of sections"; ++const char wuffs_bzip2__error__truncated_input[] = "#bzip2: truncated input"; ++const char wuffs_bzip2__error__unsupported_block_randomization[] = "#bzip2: unsupported block randomization"; ++const char wuffs_bzip2__error__internal_error_inconsistent_huffman_decoder_state[] = "#bzip2: internal error: inconsistent Huffman decoder state"; + + // ---------------- Private Consts + + static const uint8_t +-WUFFS_DEFLATE__CODE_ORDER[19] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 16, 17, 18, 0, 8, 7, 9, 6, +- 10, 5, 11, 4, 12, 3, 13, 2, +- 14, 1, 15, +-}; +- +-static const uint8_t +-WUFFS_DEFLATE__REVERSE8[256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 128, 64, 192, 32, 160, 96, 224, +- 16, 144, 80, 208, 48, 176, 112, 240, +- 8, 136, 72, 200, 40, 168, 104, 232, +- 24, 152, 88, 216, 56, 184, 120, 248, +- 4, 132, 68, 196, 36, 164, 100, 228, +- 20, 148, 84, 212, 52, 180, 116, 244, +- 12, 140, 76, 204, 44, 172, 108, 236, +- 28, 156, 92, 220, 60, 188, 124, 252, +- 2, 130, 66, 194, 34, 162, 98, 226, +- 18, 146, 82, 210, 50, 178, 114, 242, +- 10, 138, 74, 202, 42, 170, 106, 234, +- 26, 154, 90, 218, 58, 186, 122, 250, +- 6, 134, 70, 198, 38, 166, 102, 230, +- 22, 150, 86, 214, 54, 182, 118, 246, +- 14, 142, 78, 206, 46, 174, 110, 238, +- 30, 158, 94, 222, 62, 190, 126, 254, +- 1, 129, 65, 193, 33, 161, 97, 225, +- 17, 145, 81, 209, 49, 177, 113, 241, +- 9, 137, 73, 201, 41, 169, 105, 233, +- 25, 153, 89, 217, 57, 185, 121, 249, +- 5, 133, 69, 197, 37, 165, 101, 229, +- 21, 149, 85, 213, 53, 181, 117, 245, +- 13, 141, 77, 205, 45, 173, 109, 237, +- 29, 157, 93, 221, 61, 189, 125, 253, +- 3, 131, 67, 195, 35, 163, 99, 227, +- 19, 147, 83, 211, 51, 179, 115, 243, +- 11, 139, 75, 203, 43, 171, 107, 235, +- 27, 155, 91, 219, 59, 187, 123, 251, +- 7, 135, 71, 199, 39, 167, 103, 231, +- 23, 151, 87, 215, 55, 183, 119, 247, +- 15, 143, 79, 207, 47, 175, 111, 239, +- 31, 159, 95, 223, 63, 191, 127, 255, +-}; +- +-static const uint32_t +-WUFFS_DEFLATE__LCODE_MAGIC_NUMBERS[32] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 1073741824, 1073742080, 1073742336, 1073742592, 1073742848, 1073743104, 1073743360, 1073743616, +- 1073743888, 1073744400, 1073744912, 1073745424, 1073745952, 1073746976, 1073748000, 1073749024, +- 1073750064, 1073752112, 1073754160, 1073756208, 1073758272, 1073762368, 1073766464, 1073770560, +- 1073774672, 1073782864, 1073791056, 1073799248, 1073807104, 134217728, 134217728, 134217728, ++WUFFS_BZIP2__CLAMP_TO_5[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 1u, 2u, 3u, 4u, 5u, 5u, 5u, + }; + + static const uint32_t +-WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[32] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 1073741824, 1073742080, 1073742336, 1073742592, 1073742864, 1073743376, 1073743904, 1073744928, +- 1073745968, 1073748016, 1073750080, 1073754176, 1073758288, 1073766480, 1073774688, 1073791072, +- 1073807472, 1073840240, 1073873024, 1073938560, 1074004112, 1074135184, 1074266272, 1074528416, +- 1074790576, 1075314864, 1075839168, 1076887744, 1077936336, 1080033488, 134217728, 134217728, ++WUFFS_BZIP2__REV_CRC32_TABLE[256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 79764919u, 159529838u, 222504665u, 319059676u, 398814059u, 445009330u, 507990021u, ++ 638119352u, 583659535u, 797628118u, 726387553u, 890018660u, 835552979u, 1015980042u, 944750013u, ++ 1276238704u, 1221641927u, 1167319070u, 1095957929u, 1595256236u, 1540665371u, 1452775106u, 1381403509u, ++ 1780037320u, 1859660671u, 1671105958u, 1733955601u, 2031960084u, 2111593891u, 1889500026u, 1952343757u, ++ 2552477408u, 2632100695u, 2443283854u, 2506133561u, 2334638140u, 2414271883u, 2191915858u, 2254759653u, ++ 3190512472u, 3135915759u, 3081330742u, 3009969537u, 2905550212u, 2850959411u, 2762807018u, 2691435357u, ++ 3560074640u, 3505614887u, 3719321342u, 3648080713u, 3342211916u, 3287746299u, 3467911202u, 3396681109u, ++ 4063920168u, 4143685023u, 4223187782u, 4286162673u, 3779000052u, 3858754371u, 3904687514u, 3967668269u, ++ 881225847u, 809987520u, 1023691545u, 969234094u, 662832811u, 591600412u, 771767749u, 717299826u, ++ 311336399u, 374308984u, 453813921u, 533576470u, 25881363u, 88864420u, 134795389u, 214552010u, ++ 2023205639u, 2086057648u, 1897238633u, 1976864222u, 1804852699u, 1867694188u, 1645340341u, 1724971778u, ++ 1587496639u, 1516133128u, 1461550545u, 1406951526u, 1302016099u, 1230646740u, 1142491917u, 1087903418u, ++ 2896545431u, 2825181984u, 2770861561u, 2716262478u, 3215044683u, 3143675388u, 3055782693u, 3001194130u, ++ 2326604591u, 2389456536u, 2200899649u, 2280525302u, 2578013683u, 2640855108u, 2418763421u, 2498394922u, ++ 3769900519u, 3832873040u, 3912640137u, 3992402750u, 4088425275u, 4151408268u, 4197601365u, 4277358050u, ++ 3334271071u, 3263032808u, 3476998961u, 3422541446u, 3585640067u, 3514407732u, 3694837229u, 3640369242u, ++ 1762451694u, 1842216281u, 1619975040u, 1682949687u, 2047383090u, 2127137669u, 1938468188u, 2001449195u, ++ 1325665622u, 1271206113u, 1183200824u, 1111960463u, 1543535498u, 1489069629u, 1434599652u, 1363369299u, ++ 622672798u, 568075817u, 748617968u, 677256519u, 907627842u, 853037301u, 1067152940u, 995781531u, ++ 51762726u, 131386257u, 177728840u, 240578815u, 269590778u, 349224269u, 429104020u, 491947555u, ++ 4046411278u, 4126034873u, 4172115296u, 4234965207u, 3794477266u, 3874110821u, 3953728444u, 4016571915u, ++ 3609705398u, 3555108353u, 3735388376u, 3664026991u, 3290680682u, 3236090077u, 3449943556u, 3378572211u, ++ 3174993278u, 3120533705u, 3032266256u, 2961025959u, 2923101090u, 2868635157u, 2813903052u, 2742672763u, ++ 2604032198u, 2683796849u, 2461293480u, 2524268063u, 2284983834u, 2364738477u, 2175806836u, 2238787779u, ++ 1569362073u, 1498123566u, 1409854455u, 1355396672u, 1317987909u, 1246755826u, 1192025387u, 1137557660u, ++ 2072149281u, 2135122070u, 1912620623u, 1992383480u, 1753615357u, 1816598090u, 1627664531u, 1707420964u, ++ 295390185u, 358241886u, 404320391u, 483945776u, 43990325u, 106832002u, 186451547u, 266083308u, ++ 932423249u, 861060070u, 1041341759u, 986742920u, 613929101u, 542559546u, 756411363u, 701822548u, ++ 3316196985u, 3244833742u, 3425377559u, 3370778784u, 3601682597u, 3530312978u, 3744426955u, 3689838204u, ++ 3819031489u, 3881883254u, 3928223919u, 4007849240u, 4037393693u, 4100235434u, 4180117107u, 4259748804u, ++ 2310601993u, 2373574846u, 2151335527u, 2231098320u, 2596047829u, 2659030626u, 2470359227u, 2550115596u, ++ 2947551409u, 2876312838u, 2788305887u, 2733848168u, 3165939309u, 3094707162u, 3040238851u, 2985771188u, + }; + +-#define WUFFS_DEFLATE__HUFFS_TABLE_SIZE 1024 +- +-#define WUFFS_DEFLATE__HUFFS_TABLE_MASK 1023 +- + // ---------------- Private Initializer Prototypes + + // ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__do_transform_io( +- wuffs_deflate__decoder* self, ++wuffs_bzip2__decoder__do_transform_io( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src, + wuffs_base__slice_u8 a_workbuf); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__decode_blocks( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_bzip2__decoder__prepare_block( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__decode_uncompressed( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_bzip2__decoder__read_code_lengths( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__init_fixed_huffman( +- wuffs_deflate__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__init_dynamic_huffman( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_src); ++wuffs_bzip2__decoder__build_huffman_tree( ++ wuffs_bzip2__decoder* self, ++ uint32_t a_which); + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__init_huff( +- wuffs_deflate__decoder* self, +- uint32_t a_which, +- uint32_t a_n_codes0, +- uint32_t a_n_codes1, +- uint32_t a_base_symbol); ++static wuffs_base__empty_struct ++wuffs_bzip2__decoder__build_huffman_table( ++ wuffs_bzip2__decoder* self, ++ uint32_t a_which); + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_bmi2( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) ++static wuffs_base__empty_struct ++wuffs_bzip2__decoder__invert_bwt( ++ wuffs_bzip2__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_fast32( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src); ++static wuffs_base__empty_struct ++wuffs_bzip2__decoder__flush_fast( ++ wuffs_bzip2__decoder* self, ++ wuffs_base__io_buffer* a_dst); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_fast64( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src); ++wuffs_bzip2__decoder__flush_slow( ++ wuffs_bzip2__decoder* self, ++ wuffs_base__io_buffer* a_dst); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_fast64__choosy_default( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_bzip2__decoder__decode_huffman_fast( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_slow( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_bzip2__decoder__decode_huffman_slow( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_src); + + // ---------------- VTables + + const wuffs_base__io_transformer__func_ptrs +-wuffs_deflate__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++wuffs_bzip2__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++ (wuffs_base__optional_u63(*)(const void*))(&wuffs_bzip2__decoder__dst_history_retain_length), + (uint64_t(*)(const void*, +- uint32_t))(&wuffs_deflate__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_deflate__decoder__history_retain_length), ++ uint32_t))(&wuffs_bzip2__decoder__get_quirk), + (wuffs_base__status(*)(void*, + uint32_t, +- uint64_t))(&wuffs_deflate__decoder__set_quirk), ++ uint64_t))(&wuffs_bzip2__decoder__set_quirk), + (wuffs_base__status(*)(void*, + wuffs_base__io_buffer*, + wuffs_base__io_buffer*, +- wuffs_base__slice_u8))(&wuffs_deflate__decoder__transform_io), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_deflate__decoder__workbuf_len), ++ wuffs_base__slice_u8))(&wuffs_bzip2__decoder__transform_io), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_bzip2__decoder__workbuf_len), + }; + + // ---------------- Initializer Implementations + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_deflate__decoder__initialize( +- wuffs_deflate__decoder* self, ++wuffs_bzip2__decoder__initialize( ++ wuffs_bzip2__decoder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options){ +@@ -34263,25 +34215,23 @@ wuffs_deflate__decoder__initialize( + } + } + +- self->private_impl.choosy_decode_huffman_fast64 = &wuffs_deflate__decoder__decode_huffman_fast64__choosy_default; +- + self->private_impl.magic = WUFFS_BASE__MAGIC; + self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = + wuffs_base__io_transformer__vtable_name; + self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = +- (const void*)(&wuffs_deflate__decoder__func_ptrs_for__wuffs_base__io_transformer); ++ (const void*)(&wuffs_bzip2__decoder__func_ptrs_for__wuffs_base__io_transformer); + return wuffs_base__make_status(NULL); + } + +-wuffs_deflate__decoder* +-wuffs_deflate__decoder__alloc(void) { +- wuffs_deflate__decoder* x = +- (wuffs_deflate__decoder*)(calloc(sizeof(wuffs_deflate__decoder), 1)); ++wuffs_bzip2__decoder* ++wuffs_bzip2__decoder__alloc(void) { ++ wuffs_bzip2__decoder* x = ++ (wuffs_bzip2__decoder*)(calloc(1, sizeof(wuffs_bzip2__decoder))); + if (!x) { + return NULL; + } +- if (wuffs_deflate__decoder__initialize( +- x, sizeof(wuffs_deflate__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ if (wuffs_bzip2__decoder__initialize( ++ x, sizeof(wuffs_bzip2__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { + free(x); + return NULL; + } +@@ -34289,59 +34239,18 @@ wuffs_deflate__decoder__alloc(void) { + } + + size_t +-sizeof__wuffs_deflate__decoder(void) { +- return sizeof(wuffs_deflate__decoder); ++sizeof__wuffs_bzip2__decoder(void) { ++ return sizeof(wuffs_bzip2__decoder); + } + + // ---------------- Function Implementations + +-// -------- func deflate.decoder.add_history +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_deflate__decoder__add_history( +- wuffs_deflate__decoder* self, +- wuffs_base__slice_u8 a_hist) { +- if (!self) { +- return wuffs_base__make_empty_struct(); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); +- } +- +- wuffs_base__slice_u8 v_s = {0}; +- uint64_t v_n_copied = 0; +- uint32_t v_already_full = 0; +- +- v_s = a_hist; +- if (((uint64_t)(v_s.len)) >= 32768u) { +- v_s = wuffs_base__slice_u8__suffix(v_s, 32768u); +- wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s); +- self->private_impl.f_history_index = 32768u; +- } else { +- v_n_copied = wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_history, (self->private_impl.f_history_index & 32767u), 32768), v_s); +- if (v_n_copied < ((uint64_t)(v_s.len))) { +- v_s = wuffs_base__slice_u8__subslice_i(v_s, v_n_copied); +- v_n_copied = wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s); +- self->private_impl.f_history_index = (((uint32_t)((v_n_copied & 32767u))) + 32768u); +- } else { +- v_already_full = 0u; +- if (self->private_impl.f_history_index >= 32768u) { +- v_already_full = 32768u; +- } +- self->private_impl.f_history_index = ((self->private_impl.f_history_index & 32767u) + ((uint32_t)((v_n_copied & 32767u))) + v_already_full); +- } +- } +- wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_history, 32768, 33025), wuffs_base__make_slice_u8(self->private_data.f_history, 33025)); +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func deflate.decoder.get_quirk ++// -------- func bzip2.decoder.get_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_deflate__decoder__get_quirk( +- const wuffs_deflate__decoder* self, ++wuffs_bzip2__decoder__get_quirk( ++ const wuffs_bzip2__decoder* self, + uint32_t a_key) { + if (!self) { + return 0; +@@ -34351,15 +34260,18 @@ wuffs_deflate__decoder__get_quirk( + return 0; + } + ++ if ((a_key == 1u) && self->private_impl.f_ignore_checksum) { ++ return 1u; ++ } + return 0u; + } + +-// -------- func deflate.decoder.set_quirk ++// -------- func bzip2.decoder.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_deflate__decoder__set_quirk( +- wuffs_deflate__decoder* self, ++wuffs_bzip2__decoder__set_quirk( ++ wuffs_bzip2__decoder* self, + uint32_t a_key, + uint64_t a_value) { + if (!self) { +@@ -34372,32 +34284,36 @@ wuffs_deflate__decoder__set_quirk( + : wuffs_base__error__initialize_not_called); + } + ++ if (a_key == 1u) { ++ self->private_impl.f_ignore_checksum = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } + return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func deflate.decoder.history_retain_length ++// -------- func bzip2.decoder.dst_history_retain_length + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_deflate__decoder__history_retain_length( +- const wuffs_deflate__decoder* self) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_bzip2__decoder__dst_history_retain_length( ++ const wuffs_bzip2__decoder* self) { + if (!self) { +- return 0; ++ return wuffs_base__utility__make_optional_u63(false, 0u); + } + if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && + (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ return wuffs_base__utility__make_optional_u63(false, 0u); + } + +- return 0u; ++ return wuffs_base__utility__make_optional_u63(true, 0u); + } + +-// -------- func deflate.decoder.workbuf_len ++// -------- func bzip2.decoder.workbuf_len + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_deflate__decoder__workbuf_len( +- const wuffs_deflate__decoder* self) { ++wuffs_bzip2__decoder__workbuf_len( ++ const wuffs_bzip2__decoder* self) { + if (!self) { + return wuffs_base__utility__empty_range_ii_u64(); + } +@@ -34406,15 +34322,15 @@ wuffs_deflate__decoder__workbuf_len( + return wuffs_base__utility__empty_range_ii_u64(); + } + +- return wuffs_base__utility__make_range_ii_u64(1u, 1u); ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); + } + +-// -------- func deflate.decoder.transform_io ++// -------- func bzip2.decoder.transform_io + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_deflate__decoder__transform_io( +- wuffs_deflate__decoder* self, ++wuffs_bzip2__decoder__transform_io( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src, + wuffs_base__slice_u8 a_workbuf) { +@@ -34441,17 +34357,17 @@ wuffs_deflate__decoder__transform_io( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_transform_io[0]; ++ uint32_t coro_susp_point = self->private_impl.p_transform_io; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_deflate__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); ++ wuffs_base__status t_0 = wuffs_bzip2__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_deflate__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_bzip2__error__truncated_input); + goto exit; + } + status = v_status; +@@ -34459,13 +34375,13 @@ wuffs_deflate__decoder__transform_io( + } + + ok: +- self->private_impl.p_transform_io[0] = 0; ++ self->private_impl.p_transform_io = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; + + goto exit; +@@ -34476,103 +34392,22 @@ wuffs_deflate__decoder__transform_io( + return status; + } + +-// -------- func deflate.decoder.do_transform_io ++// -------- func bzip2.decoder.do_transform_io + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__do_transform_io( +- wuffs_deflate__decoder* self, ++wuffs_bzip2__decoder__do_transform_io( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src, + wuffs_base__slice_u8 a_workbuf) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint64_t v_mark = 0; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } +- +- uint32_t coro_susp_point = self->private_impl.p_do_transform_io[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- self->private_impl.choosy_decode_huffman_fast64 = ( +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- wuffs_base__cpu_arch__have_x86_bmi2() ? &wuffs_deflate__decoder__decode_huffman_bmi2 : +-#endif +- self->private_impl.choosy_decode_huffman_fast64); +- while (true) { +- v_mark = ((uint64_t)(iop_a_dst - io0_a_dst)); +- { +- if (a_dst) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- wuffs_base__status t_0 = wuffs_deflate__decoder__decode_blocks(self, a_dst, a_src); +- v_status = t_0; +- if (a_dst) { +- iop_a_dst = a_dst->data.ptr + a_dst->meta.wi; +- } +- } +- if ( ! wuffs_base__status__is_suspension(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_transformed_history_count, wuffs_base__io__count_since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)))); +- wuffs_deflate__decoder__add_history(self, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } +- +- ok: +- self->private_impl.p_do_transform_io[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_do_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func deflate.decoder.decode_blocks +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__decode_blocks( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_final = 0; +- uint32_t v_b0 = 0; +- uint32_t v_type = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_i = 0; ++ uint64_t v_tag = 0; + wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint32_t v_final_checksum_want = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -34585,125 +34420,206 @@ wuffs_deflate__decoder__decode_blocks( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_blocks[0]; ++ uint32_t coro_susp_point = self->private_impl.p_do_transform_io; + if (coro_susp_point) { +- v_final = self->private_data.s_decode_blocks[0].v_final; ++ v_i = self->private_data.s_do_transform_io.v_i; ++ v_tag = self->private_data.s_do_transform_io.v_tag; ++ v_final_checksum_want = self->private_data.s_do_transform_io.v_final_checksum_want; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- label__outer__continue:; +- while (v_final == 0u) { +- while (self->private_impl.f_n_bits < 3u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (v_c8 != 66u) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (v_c8 != 90u) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ if (v_c8 != 104u) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ if ((v_c8 < 49u) || (57u < v_c8)) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_header); ++ goto exit; ++ } ++ self->private_impl.f_max_incl_block_size = (((uint32_t)(((uint8_t)(v_c8 - 48u)))) * 100000u); ++ while (true) { ++ v_tag = 0u; ++ v_i = 0u; ++ while (v_i < 48u) { ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; + } +- uint32_t t_0 = *iop_a_src++; +- v_b0 = t_0; ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } +- self->private_impl.f_bits |= (v_b0 << (self->private_impl.f_n_bits & 3u)); +- self->private_impl.f_n_bits = ((self->private_impl.f_n_bits & 3u) + 8u); ++ v_tag <<= 1u; ++ v_tag |= ((uint64_t)((self->private_impl.f_bits >> 31u))); ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_i += 1u; + } +- v_final = (self->private_impl.f_bits & 1u); +- v_type = ((self->private_impl.f_bits >> 1u) & 3u); +- self->private_impl.f_bits >>= 3u; +- self->private_impl.f_n_bits -= 3u; +- if (v_type == 0u) { ++ if (v_tag == 25779555029136u) { ++ break; ++ } else if (v_tag != 54156738319193u) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ status = wuffs_bzip2__decoder__prepare_block(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_block_size = 0u; ++ self->private_impl.f_decode_huffman_finished = false; ++ self->private_impl.f_decode_huffman_which = WUFFS_BZIP2__CLAMP_TO_5[((uint8_t)(self->private_data.f_huffman_selectors[0u] & 7u))]; ++ self->private_impl.f_decode_huffman_ticks = 50u; ++ self->private_impl.f_decode_huffman_section = 0u; ++ self->private_impl.f_decode_huffman_run_shift = 0u; ++ while ( ! self->private_impl.f_decode_huffman_finished) { + if (a_src) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- status = wuffs_deflate__decoder__decode_uncompressed(self, a_dst, a_src); ++ v_status = wuffs_bzip2__decoder__decode_huffman_fast(self, a_src); + if (a_src) { + iop_a_src = a_src->data.ptr + a_src->meta.ri; + } +- if (status.repr) { +- goto suspend; +- } +- continue; +- } else if (v_type == 1u) { +- v_status = wuffs_deflate__decoder__init_fixed_huffman(self); +- if ( ! wuffs_base__status__is_ok(&v_status)) { ++ if (wuffs_base__status__is_error(&v_status)) { + status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; ++ goto exit; ++ } else if (self->private_impl.f_decode_huffman_finished) { ++ break; + } +- } else if (v_type == 2u) { + if (a_src) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_deflate__decoder__init_dynamic_huffman(self, a_src); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ status = wuffs_bzip2__decoder__decode_huffman_slow(self, a_src); + if (a_src) { + iop_a_src = a_src->data.ptr + a_src->meta.ri; + } + if (status.repr) { + goto suspend; + } +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_block); ++ } ++ wuffs_bzip2__decoder__invert_bwt(self); ++ self->private_impl.f_block_checksum_have = 4294967295u; ++ if (self->private_impl.f_original_pointer >= self->private_impl.f_block_size) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); + goto exit; + } +- self->private_impl.f_end_of_block = false; +- while (true) { +- if (sizeof(void*) == 4u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_status = wuffs_deflate__decoder__decode_huffman_fast32(self, a_dst, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } else { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_status = wuffs_deflate__decoder__decode_huffman_fast64(self, a_dst, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } +- if (wuffs_base__status__is_error(&v_status)) { +- status = v_status; +- goto exit; +- } +- if (self->private_impl.f_end_of_block) { +- goto label__outer__continue; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- status = wuffs_deflate__decoder__decode_huffman_slow(self, a_dst, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ self->private_impl.f_flush_pointer = (self->private_data.f_bwt[self->private_impl.f_original_pointer] >> 12u); ++ self->private_impl.f_flush_repeat_count = 0u; ++ self->private_impl.f_flush_prev = 0u; ++ while (self->private_impl.f_block_size > 0u) { ++ wuffs_bzip2__decoder__flush_fast(self, a_dst); ++ if (self->private_impl.f_block_size <= 0u) { ++ break; + } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ status = wuffs_bzip2__decoder__flush_slow(self, a_dst); + if (status.repr) { + goto suspend; + } +- if (self->private_impl.f_end_of_block) { +- goto label__outer__continue; ++ } ++ self->private_impl.f_block_checksum_have ^= 4294967295u; ++ if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_block_checksum_have != self->private_impl.f_block_checksum_want)) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_checksum); ++ goto exit; ++ } ++ self->private_impl.f_final_checksum_have = (self->private_impl.f_block_checksum_have ^ ((self->private_impl.f_final_checksum_have >> 31u) | ((uint32_t)(self->private_impl.f_final_checksum_have << 1u)))); ++ } ++ v_final_checksum_want = 0u; ++ v_i = 0u; ++ while (v_i < 32u) { ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; + } ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } ++ v_final_checksum_want <<= 1u; ++ v_final_checksum_want |= (self->private_impl.f_bits >> 31u); ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_i += 1u; ++ } ++ if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_final_checksum_have != v_final_checksum_want)) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_checksum); ++ goto exit; + } + ++ goto ok; + ok: +- self->private_impl.p_decode_blocks[0] = 0; ++ self->private_impl.p_do_transform_io = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_blocks[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_blocks[0].v_final = v_final; ++ self->private_impl.p_do_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_transform_io.v_i = v_i; ++ self->private_data.s_do_transform_io.v_tag = v_tag; ++ self->private_data.s_do_transform_io.v_final_checksum_want = v_final_checksum_want; + + goto exit; + exit: +@@ -34714,32 +34630,23 @@ wuffs_deflate__decoder__decode_blocks( + return status; + } + +-// -------- func deflate.decoder.decode_uncompressed ++// -------- func bzip2.decoder.prepare_block + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__decode_uncompressed( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_bzip2__decoder__prepare_block( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_length = 0; +- uint32_t v_n_copied = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_i = 0; ++ uint32_t v_j = 0; ++ uint32_t v_selector = 0; ++ uint32_t v_sel_ff = 0; ++ uint8_t v_movee = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -34751,387 +34658,287 @@ wuffs_deflate__decoder__decode_uncompressed( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_uncompressed[0]; ++ uint32_t coro_susp_point = self->private_impl.p_prepare_block; + if (coro_susp_point) { +- v_length = self->private_data.s_decode_uncompressed[0].v_length; ++ v_i = self->private_data.s_prepare_block.v_i; ++ v_selector = self->private_data.s_prepare_block.v_selector; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; +- } +- self->private_impl.f_n_bits = 0u; +- self->private_impl.f_bits = 0u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_uncompressed[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { ++ self->private_impl.f_block_checksum_want = 0u; ++ v_i = 0u; ++ while (v_i < 32u) { ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_uncompressed[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; +- if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; + } ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } +- v_length = t_0; +- } +- if ((((v_length) & 0xFFFFu) + ((v_length) >> (32u - 16u))) != 65535u) { +- status = wuffs_base__make_status(wuffs_deflate__error__inconsistent_stored_block_length); +- goto exit; +- } +- v_length = ((v_length) & 0xFFFFu); +- while (true) { +- v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_reader( +- &iop_a_dst, io2_a_dst,v_length, &iop_a_src, io2_a_src); +- if (v_length <= v_n_copied) { +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- v_length -= v_n_copied; +- if (((uint64_t)(io2_a_dst - iop_a_dst)) == 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- } else { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); +- } ++ self->private_impl.f_block_checksum_want <<= 1u; ++ self->private_impl.f_block_checksum_want |= (self->private_impl.f_bits >> 31u); ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_i += 1u; + } +- +- ok: +- self->private_impl.p_decode_uncompressed[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_uncompressed[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_uncompressed[0].v_length = v_length; +- +- goto exit; +- exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func deflate.decoder.init_fixed_huffman +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__init_fixed_huffman( +- wuffs_deflate__decoder* self) { +- uint32_t v_i = 0; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- while (v_i < 144u) { +- self->private_data.f_code_lengths[v_i] = 8u; +- v_i += 1u; +- } +- while (v_i < 256u) { +- self->private_data.f_code_lengths[v_i] = 9u; +- v_i += 1u; +- } +- while (v_i < 280u) { +- self->private_data.f_code_lengths[v_i] = 7u; +- v_i += 1u; +- } +- while (v_i < 288u) { +- self->private_data.f_code_lengths[v_i] = 8u; +- v_i += 1u; +- } +- while (v_i < 320u) { +- self->private_data.f_code_lengths[v_i] = 5u; +- v_i += 1u; +- } +- v_status = wuffs_deflate__decoder__init_huff(self, +- 0u, +- 0u, +- 288u, +- 257u); +- if (wuffs_base__status__is_error(&v_status)) { +- return v_status; +- } +- v_status = wuffs_deflate__decoder__init_huff(self, +- 1u, +- 288u, +- 320u, +- 0u); +- if (wuffs_base__status__is_error(&v_status)) { +- return v_status; +- } +- return wuffs_base__make_status(NULL); +-} +- +-// -------- func deflate.decoder.init_dynamic_huffman +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__init_dynamic_huffman( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint32_t v_b0 = 0; +- uint32_t v_n_lit = 0; +- uint32_t v_n_dist = 0; +- uint32_t v_n_clen = 0; +- uint32_t v_i = 0; +- uint32_t v_b1 = 0; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- uint32_t v_mask = 0; +- uint32_t v_table_entry = 0; +- uint32_t v_table_entry_n_bits = 0; +- uint32_t v_b2 = 0; +- uint32_t v_n_extra_bits = 0; +- uint8_t v_rep_symbol = 0; +- uint32_t v_rep_count = 0; +- uint32_t v_b3 = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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_init_dynamic_huffman[0]; +- if (coro_susp_point) { +- v_bits = self->private_data.s_init_dynamic_huffman[0].v_bits; +- v_n_bits = self->private_data.s_init_dynamic_huffman[0].v_n_bits; +- v_n_lit = self->private_data.s_init_dynamic_huffman[0].v_n_lit; +- v_n_dist = self->private_data.s_init_dynamic_huffman[0].v_n_dist; +- v_n_clen = self->private_data.s_init_dynamic_huffman[0].v_n_clen; +- v_i = self->private_data.s_init_dynamic_huffman[0].v_i; +- v_mask = self->private_data.s_init_dynamic_huffman[0].v_mask; +- v_n_extra_bits = self->private_data.s_init_dynamic_huffman[0].v_n_extra_bits; +- v_rep_symbol = self->private_data.s_init_dynamic_huffman[0].v_rep_symbol; +- v_rep_count = self->private_data.s_init_dynamic_huffman[0].v_rep_count; +- } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- v_bits = self->private_impl.f_bits; +- v_n_bits = self->private_impl.f_n_bits; +- while (v_n_bits < 14u) { ++ if (self->private_impl.f_n_bits <= 0u) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint32_t t_0 = *iop_a_src++; +- v_b0 = t_0; ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; + } +- v_bits |= (v_b0 << v_n_bits); +- v_n_bits += 8u; +- } +- v_n_lit = (((v_bits) & 0x1Fu) + 257u); +- if (v_n_lit > 286u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_literal_length_code_count); +- goto exit; ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } +- v_bits >>= 5u; +- v_n_dist = (((v_bits) & 0x1Fu) + 1u); +- if (v_n_dist > 30u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_distance_code_count); ++ if ((self->private_impl.f_bits >> 31u) != 0u) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__unsupported_block_randomization); + goto exit; + } +- v_bits >>= 5u; +- v_n_clen = (((v_bits) & 0xFu) + 4u); +- v_bits >>= 4u; +- v_n_bits -= 14u; ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ self->private_impl.f_original_pointer = 0u; + v_i = 0u; +- while (v_i < v_n_clen) { +- while (v_n_bits < 3u) { ++ while (v_i < 24u) { ++ if (self->private_impl.f_n_bits <= 0u) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint32_t t_1 = *iop_a_src++; +- v_b1 = t_1; ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; + } +- v_bits |= (v_b1 << v_n_bits); +- v_n_bits += 8u; ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } +- self->private_data.f_code_lengths[WUFFS_DEFLATE__CODE_ORDER[v_i]] = ((uint8_t)((v_bits & 7u))); +- v_bits >>= 3u; +- v_n_bits -= 3u; ++ self->private_impl.f_original_pointer <<= 1u; ++ self->private_impl.f_original_pointer |= (self->private_impl.f_bits >> 31u); ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; + v_i += 1u; + } +- while (v_i < 19u) { +- self->private_data.f_code_lengths[WUFFS_DEFLATE__CODE_ORDER[v_i]] = 0u; ++ v_i = 0u; ++ while (v_i < 256u) { ++ self->private_data.f_presence[v_i] = 0u; + v_i += 1u; + } +- v_status = wuffs_deflate__decoder__init_huff(self, +- 0u, +- 0u, +- 19u, +- 4095u); +- if (wuffs_base__status__is_error(&v_status)) { +- status = v_status; +- goto exit; +- } +- v_mask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); + v_i = 0u; +- while (v_i < (v_n_lit + v_n_dist)) { +- while (true) { +- v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_mask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- if (v_n_bits >= v_table_entry_n_bits) { +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- break; +- } ++ while (v_i < 256u) { ++ if (self->private_impl.f_n_bits <= 0u) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint32_t t_2 = *iop_a_src++; +- v_b2 = t_2; ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; + } +- v_bits |= (v_b2 << v_n_bits); +- v_n_bits += 8u; ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } +- if ((v_table_entry >> 24u) != 128u) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; ++ if ((self->private_impl.f_bits >> 31u) != 0u) { ++ self->private_data.f_presence[v_i] = 1u; + } +- v_table_entry = ((v_table_entry >> 8u) & 255u); +- if (v_table_entry < 16u) { +- self->private_data.f_code_lengths[v_i] = ((uint8_t)(v_table_entry)); +- v_i += 1u; ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_i += 16u; ++ } ++ self->private_data.f_scratch = 0u; ++ v_i = 0u; ++ while (v_i < 256u) { ++ if (self->private_data.f_presence[v_i] == 0u) { ++ v_i += 16u; + continue; + } +- v_n_extra_bits = 0u; +- v_rep_symbol = 0u; +- v_rep_count = 0u; +- if (v_table_entry == 16u) { +- v_n_extra_bits = 2u; +- if (v_i <= 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_repetition); +- goto exit; ++ while (true) { ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; ++ } ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; ++ } ++ self->private_data.f_scratch += (self->private_impl.f_bits >> 31u); ++ self->private_data.f_presence[(v_i & 255u)] = ((uint8_t)((self->private_impl.f_bits >> 31u))); ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_i += 1u; ++ if ((v_i & 15u) == 0u) { ++ break; + } +- v_rep_symbol = (self->private_data.f_code_lengths[(v_i - 1u)] & 15u); +- v_rep_count = 3u; +- } else if (v_table_entry == 17u) { +- v_n_extra_bits = 3u; +- v_rep_symbol = 0u; +- v_rep_count = 3u; +- } else if (v_table_entry == 18u) { +- v_n_extra_bits = 7u; +- v_rep_symbol = 0u; +- v_rep_count = 11u; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; + } +- while (v_n_bits < v_n_extra_bits) { ++ } ++ if ((self->private_data.f_scratch < 1u) || (256u < self->private_data.f_scratch)) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); ++ goto exit; ++ } ++ self->private_impl.f_num_symbols = (self->private_data.f_scratch + 2u); ++ self->private_data.f_scratch = 0u; ++ v_i = 0u; ++ while (v_i < 3u) { ++ if (self->private_impl.f_n_bits <= 0u) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint32_t t_3 = *iop_a_src++; +- v_b3 = t_3; ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; + } +- v_bits |= (v_b3 << v_n_bits); +- v_n_bits += 8u; ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } +- v_rep_count += ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_n_extra_bits)); +- v_bits >>= v_n_extra_bits; +- v_n_bits -= v_n_extra_bits; +- while (v_rep_count > 0u) { +- if (v_i >= (v_n_lit + v_n_dist)) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_count); +- goto exit; ++ self->private_data.f_scratch <<= 1u; ++ self->private_data.f_scratch |= (self->private_impl.f_bits >> 31u); ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_i += 1u; ++ } ++ if ((self->private_data.f_scratch < 2u) || (6u < self->private_data.f_scratch)) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); ++ goto exit; ++ } ++ self->private_impl.f_num_huffman_codes = self->private_data.f_scratch; ++ self->private_data.f_scratch = 0u; ++ v_i = 0u; ++ while (v_i < 15u) { ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; + } +- self->private_data.f_code_lengths[v_i] = v_rep_symbol; +- v_i += 1u; +- v_rep_count -= 1u; ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } ++ self->private_data.f_scratch <<= 1u; ++ self->private_data.f_scratch |= (self->private_impl.f_bits >> 31u); ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_i += 1u; + } +- if (v_i != (v_n_lit + v_n_dist)) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_count); ++ if ((self->private_data.f_scratch < 1u) || (18001u < self->private_data.f_scratch)) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); + goto exit; + } +- if (self->private_data.f_code_lengths[256u] == 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__missing_end_of_block_code); +- goto exit; ++ self->private_impl.f_num_sections = self->private_data.f_scratch; ++ v_i = 0u; ++ while (v_i < self->private_impl.f_num_huffman_codes) { ++ self->private_data.f_mtft[v_i] = ((uint8_t)(v_i)); ++ v_i += 1u; + } +- v_status = wuffs_deflate__decoder__init_huff(self, +- 0u, +- 0u, +- v_n_lit, +- 257u); +- if (wuffs_base__status__is_error(&v_status)) { +- status = v_status; +- goto exit; ++ v_i = 0u; ++ while (v_i < self->private_impl.f_num_sections) { ++ v_selector = 0u; ++ while (true) { ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_7 = *iop_a_src++; ++ v_c8 = t_7; ++ } ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; ++ } ++ if ((self->private_impl.f_bits >> 31u) == 0u) { ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ break; ++ } ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_selector += 1u; ++ if (v_selector >= self->private_impl.f_num_huffman_codes) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); ++ goto exit; ++ } ++ } ++ if (v_selector == 0u) { ++ self->private_data.f_huffman_selectors[v_i] = self->private_data.f_mtft[0u]; ++ } else { ++ v_sel_ff = (v_selector & 255u); ++ v_movee = self->private_data.f_mtft[v_sel_ff]; ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1u + v_sel_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_sel_ff)); ++ self->private_data.f_mtft[0u] = v_movee; ++ self->private_data.f_huffman_selectors[v_i] = v_movee; ++ } ++ v_i += 1u; + } +- v_status = wuffs_deflate__decoder__init_huff(self, +- 1u, +- v_n_lit, +- (v_n_lit + v_n_dist), +- 0u); +- if (wuffs_base__status__is_error(&v_status)) { +- status = v_status; +- goto exit; ++ v_i = 0u; ++ while (v_i < self->private_impl.f_num_huffman_codes) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ status = wuffs_bzip2__decoder__read_code_lengths(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ v_status = wuffs_bzip2__decoder__build_huffman_tree(self, v_i); ++ if (wuffs_base__status__is_error(&v_status)) { ++ status = v_status; ++ goto exit; ++ } ++ wuffs_bzip2__decoder__build_huffman_table(self, v_i); ++ v_i += 1u; ++ } ++ v_i = 0u; ++ v_j = 0u; ++ while (v_i < 256u) { ++ if (self->private_data.f_presence[v_i] != 0u) { ++ self->private_data.f_mtft[(v_j & 255u)] = ((uint8_t)(v_i)); ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 256u) { ++ self->private_data.f_letter_counts[v_i] = 0u; ++ v_i += 1u; + } +- self->private_impl.f_bits = v_bits; +- self->private_impl.f_n_bits = v_n_bits; + + goto ok; + ok: +- self->private_impl.p_init_dynamic_huffman[0] = 0; ++ self->private_impl.p_prepare_block = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_init_dynamic_huffman[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_init_dynamic_huffman[0].v_bits = v_bits; +- self->private_data.s_init_dynamic_huffman[0].v_n_bits = v_n_bits; +- self->private_data.s_init_dynamic_huffman[0].v_n_lit = v_n_lit; +- self->private_data.s_init_dynamic_huffman[0].v_n_dist = v_n_dist; +- self->private_data.s_init_dynamic_huffman[0].v_n_clen = v_n_clen; +- self->private_data.s_init_dynamic_huffman[0].v_i = v_i; +- self->private_data.s_init_dynamic_huffman[0].v_mask = v_mask; +- self->private_data.s_init_dynamic_huffman[0].v_n_extra_bits = v_n_extra_bits; +- self->private_data.s_init_dynamic_huffman[0].v_rep_symbol = v_rep_symbol; +- self->private_data.s_init_dynamic_huffman[0].v_rep_count = v_rep_count; ++ self->private_impl.p_prepare_block = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_prepare_block.v_i = v_i; ++ self->private_data.s_prepare_block.v_selector = v_selector; + + goto exit; + exit: +@@ -35142,285 +34949,295 @@ wuffs_deflate__decoder__init_dynamic_huffman( + return status; + } + +-// -------- func deflate.decoder.init_huff ++// -------- func bzip2.decoder.read_code_lengths + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__init_huff( +- wuffs_deflate__decoder* self, +- uint32_t a_which, +- uint32_t a_n_codes0, +- uint32_t a_n_codes1, +- uint32_t a_base_symbol) { +- uint16_t v_counts[16] = {0}; ++wuffs_bzip2__decoder__read_code_lengths( ++ wuffs_bzip2__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; + uint32_t v_i = 0; +- uint32_t v_remaining = 0; +- uint16_t v_offsets[16] = {0}; +- uint32_t v_n_symbols = 0; +- uint32_t v_count = 0; +- uint16_t v_symbols[320] = {0}; +- uint32_t v_min_cl = 0; +- uint32_t v_max_cl = 0; +- uint32_t v_initial_high_bits = 0; +- uint32_t v_prev_cl = 0; +- uint32_t v_prev_redirect_key = 0; +- uint32_t v_top = 0; +- uint32_t v_next_top = 0; +- uint32_t v_code = 0; +- uint32_t v_key = 0; +- uint32_t v_value = 0; +- uint32_t v_cl = 0; +- uint32_t v_redirect_key = 0; +- uint32_t v_j = 0; +- uint32_t v_reversed_key = 0; +- uint32_t v_symbol = 0; +- uint32_t v_high_bits = 0; +- uint32_t v_delta = 0; ++ uint32_t v_code_length = 0; + +- v_i = a_n_codes0; +- while (v_i < a_n_codes1) { +- if (v_counts[(self->private_data.f_code_lengths[v_i] & 15u)] >= 320u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_counts[(self->private_data.f_code_lengths[v_i] & 15u)] += 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- v_i += 1u; +- } +- if ((((uint32_t)(v_counts[0u])) + a_n_codes0) == a_n_codes1) { +- return wuffs_base__make_status(wuffs_deflate__error__no_huffman_codes); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- v_remaining = 1u; +- v_i = 1u; +- while (v_i <= 15u) { +- if (v_remaining > 1073741824u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +- v_remaining <<= 1u; +- if (v_remaining < ((uint32_t)(v_counts[v_i]))) { +- return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_over_subscribed); +- } +- v_remaining -= ((uint32_t)(v_counts[v_i])); +- v_i += 1u; ++ ++ uint32_t coro_susp_point = self->private_impl.p_read_code_lengths; ++ if (coro_susp_point) { ++ v_i = self->private_data.s_read_code_lengths.v_i; ++ v_code_length = self->private_data.s_read_code_lengths.v_code_length; + } +- if (v_remaining != 0u) { +- if ((a_which == 1u) && (v_counts[1u] == 1u) && ((((uint32_t)(v_counts[0u])) + a_n_codes0 + 1u) == a_n_codes1)) { +- v_i = 0u; +- while (v_i <= 29u) { +- if (self->private_data.f_code_lengths[(a_n_codes0 + v_i)] == 1u) { +- self->private_impl.f_n_huffs_bits[1u] = 1u; +- self->private_data.f_huffs[1u][0u] = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[v_i] | 1u); +- self->private_data.f_huffs[1u][1u] = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[31u] | 1u); +- return wuffs_base__make_status(NULL); ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ self->private_impl.f_code_lengths_bitmask = 0u; ++ v_i = 0u; ++ while (v_i < 5u) { ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; + } +- v_i += 1u; ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } ++ v_code_length <<= 1u; ++ v_code_length |= (self->private_impl.f_bits >> 31u); ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ v_i += 1u; + } +- return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_under_subscribed); +- } +- v_i = 1u; +- while (v_i <= 15u) { +- v_offsets[v_i] = ((uint16_t)(v_n_symbols)); +- v_count = ((uint32_t)(v_counts[v_i])); +- if (v_n_symbols > (320u - v_count)) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +- v_n_symbols = (v_n_symbols + v_count); +- v_i += 1u; +- } +- if (v_n_symbols > 288u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +- v_i = a_n_codes0; +- while (v_i < a_n_codes1) { +- if (v_i < a_n_codes0) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +- if (self->private_data.f_code_lengths[v_i] != 0u) { +- if (v_offsets[(self->private_data.f_code_lengths[v_i] & 15u)] >= 320u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ v_i = 0u; ++ while (v_i < self->private_impl.f_num_symbols) { ++ while (true) { ++ if ((v_code_length < 1u) || (20u < v_code_length)) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header); ++ goto exit; ++ } ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; ++ } ++ if ((self->private_impl.f_bits >> 31u) == 0u) { ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ break; ++ } ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; ++ } ++ if ((self->private_impl.f_bits >> 31u) == 0u) { ++ v_code_length += 1u; ++ } else { ++ v_code_length -= 1u; ++ } ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; + } +- v_symbols[v_offsets[(self->private_data.f_code_lengths[v_i] & 15u)]] = ((uint16_t)((v_i - a_n_codes0))); +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_offsets[(self->private_data.f_code_lengths[v_i] & 15u)] += 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } +- v_i += 1u; +- } +- v_min_cl = 1u; +- while (true) { +- if (v_counts[v_min_cl] != 0u) { +- break; +- } +- if (v_min_cl >= 9u) { +- return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_minimum_code_length); +- } +- v_min_cl += 1u; +- } +- v_max_cl = 15u; +- while (true) { +- if (v_counts[v_max_cl] != 0u) { +- break; +- } +- if (v_max_cl <= 1u) { +- return wuffs_base__make_status(wuffs_deflate__error__no_huffman_codes); ++ self->private_impl.f_code_lengths_bitmask |= (((uint32_t)(1u)) << (v_code_length & 31u)); ++ self->private_data.f_bwt[v_i] = v_code_length; ++ v_i += 1u; + } +- v_max_cl -= 1u; +- } +- if (v_max_cl <= 9u) { +- self->private_impl.f_n_huffs_bits[a_which] = v_max_cl; +- } else { +- self->private_impl.f_n_huffs_bits[a_which] = 9u; +- } +- v_i = 0u; +- if ((v_n_symbols != ((uint32_t)(v_offsets[v_max_cl]))) || (v_n_symbols != ((uint32_t)(v_offsets[15u])))) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +- if ((a_n_codes0 + ((uint32_t)(v_symbols[0u]))) >= 320u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ ++ goto ok; ++ ok: ++ self->private_impl.p_read_code_lengths = 0; ++ goto exit; + } +- v_initial_high_bits = 512u; +- if (v_max_cl < 9u) { +- v_initial_high_bits = (((uint32_t)(1u)) << v_max_cl); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_read_code_lengths = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_read_code_lengths.v_i = v_i; ++ self->private_data.s_read_code_lengths.v_code_length = v_code_length; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- v_prev_cl = ((uint32_t)((self->private_data.f_code_lengths[(a_n_codes0 + ((uint32_t)(v_symbols[0u])))] & 15u))); +- v_prev_redirect_key = 4294967295u; +- v_top = 0u; +- v_next_top = 512u; +- v_code = 0u; +- v_key = 0u; +- v_value = 0u; +- while (true) { +- if ((a_n_codes0 + ((uint32_t)(v_symbols[v_i]))) >= 320u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ ++ return status; ++} ++ ++// -------- func bzip2.decoder.build_huffman_tree ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bzip2__decoder__build_huffman_tree( ++ wuffs_bzip2__decoder* self, ++ uint32_t a_which) { ++ uint32_t v_code_length = 0; ++ uint32_t v_symbol_index = 0; ++ uint32_t v_num_branch_nodes = 0; ++ uint32_t v_stack_height = 0; ++ uint32_t v_stack_values[21] = {0}; ++ uint32_t v_node_index = 0; ++ uint16_t v_leaf_value = 0; ++ ++ self->private_data.f_huffman_trees[a_which][0u][0u] = 0u; ++ self->private_data.f_huffman_trees[a_which][0u][1u] = 0u; ++ v_num_branch_nodes = 1u; ++ v_stack_height = 1u; ++ v_stack_values[0u] = 0u; ++ v_code_length = 1u; ++ while (v_code_length <= 20u) { ++ if ((self->private_impl.f_code_lengths_bitmask & (((uint32_t)(1u)) << v_code_length)) == 0u) { ++ v_code_length += 1u; ++ continue; + } +- v_cl = ((uint32_t)((self->private_data.f_code_lengths[(a_n_codes0 + ((uint32_t)(v_symbols[v_i])))] & 15u))); +- if (v_cl > v_prev_cl) { +- v_code <<= (v_cl - v_prev_cl); +- if (v_code >= 32768u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ v_symbol_index = 0u; ++ while (v_symbol_index < self->private_impl.f_num_symbols) { ++ if (self->private_data.f_bwt[v_symbol_index] != v_code_length) { ++ v_symbol_index += 1u; ++ continue; + } +- } +- v_prev_cl = v_cl; +- v_key = v_code; +- if (v_cl > 9u) { +- v_cl -= 9u; +- v_redirect_key = ((v_key >> v_cl) & 511u); +- v_key = ((v_key) & WUFFS_BASE__LOW_BITS_MASK__U32(v_cl)); +- if (v_prev_redirect_key != v_redirect_key) { +- v_prev_redirect_key = v_redirect_key; +- v_remaining = (((uint32_t)(1u)) << v_cl); +- v_j = v_prev_cl; +- while (v_j <= 15u) { +- if (v_remaining <= ((uint32_t)(v_counts[v_j]))) { +- break; +- } +- v_remaining -= ((uint32_t)(v_counts[v_j])); +- if (v_remaining > 1073741824u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +- v_remaining <<= 1u; +- v_j += 1u; ++ while (true) { ++ if (v_stack_height <= 0u) { ++ return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_over_subscribed); ++ } else if (v_stack_height >= v_code_length) { ++ break; + } +- if ((v_j <= 9u) || (15u < v_j)) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ v_node_index = v_stack_values[(v_stack_height - 1u)]; ++ if (self->private_data.f_huffman_trees[a_which][v_node_index][0u] == 0u) { ++ self->private_data.f_huffman_trees[a_which][v_node_index][0u] = ((uint16_t)(v_num_branch_nodes)); ++ } else { ++ self->private_data.f_huffman_trees[a_which][v_node_index][1u] = ((uint16_t)(v_num_branch_nodes)); + } +- v_j -= 9u; +- v_initial_high_bits = (((uint32_t)(1u)) << v_j); +- v_top = v_next_top; +- if ((v_top + (((uint32_t)(1u)) << v_j)) > 1024u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ if (v_num_branch_nodes >= 257u) { ++ return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_under_subscribed); + } +- v_next_top = (v_top + (((uint32_t)(1u)) << v_j)); +- v_redirect_key = (((uint32_t)(WUFFS_DEFLATE__REVERSE8[(v_redirect_key >> 1u)])) | ((v_redirect_key & 1u) << 8u)); +- self->private_data.f_huffs[a_which][v_redirect_key] = (268435465u | (v_top << 8u) | (v_j << 4u)); ++ v_stack_values[v_stack_height] = v_num_branch_nodes; ++ self->private_data.f_huffman_trees[a_which][v_num_branch_nodes][0u] = 0u; ++ self->private_data.f_huffman_trees[a_which][v_num_branch_nodes][1u] = 0u; ++ v_num_branch_nodes += 1u; ++ v_stack_height += 1u; + } ++ v_node_index = v_stack_values[(v_stack_height - 1u)]; ++ if (v_symbol_index < 2u) { ++ v_leaf_value = ((uint16_t)((769u + v_symbol_index))); ++ } else if ((v_symbol_index + 1u) < self->private_impl.f_num_symbols) { ++ v_leaf_value = ((uint16_t)((511u + v_symbol_index))); ++ } else { ++ v_leaf_value = 768u; ++ } ++ if (self->private_data.f_huffman_trees[a_which][v_node_index][0u] == 0u) { ++ self->private_data.f_huffman_trees[a_which][v_node_index][0u] = v_leaf_value; ++ } else { ++ self->private_data.f_huffman_trees[a_which][v_node_index][1u] = v_leaf_value; ++ v_stack_height -= 1u; ++ while (v_stack_height > 0u) { ++ v_node_index = v_stack_values[(v_stack_height - 1u)]; ++ if (self->private_data.f_huffman_trees[a_which][v_node_index][1u] == 0u) { ++ break; ++ } ++ v_stack_height -= 1u; ++ } ++ } ++ v_symbol_index += 1u; + } +- if ((v_key >= 512u) || (v_counts[v_prev_cl] <= 0u)) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } ++ v_code_length += 1u; ++ } ++ if (v_stack_height != 0u) { ++ return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_under_subscribed); ++ } ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func bzip2.decoder.build_huffman_table ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_bzip2__decoder__build_huffman_table( ++ wuffs_bzip2__decoder* self, ++ uint32_t a_which) { ++ uint32_t v_i = 0; ++ uint32_t v_bits = 0; ++ uint16_t v_n_bits = 0; ++ uint16_t v_child = 0; ++ ++ while (v_i < 256u) { ++ v_bits = (v_i << 24u); ++ v_n_bits = 0u; ++ v_child = 0u; ++ while ((v_child < 257u) && (v_n_bits < 8u)) { ++ v_child = self->private_data.f_huffman_trees[a_which][v_child][(v_bits >> 31u)]; ++ v_bits <<= 1u; + #if defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #endif +- v_counts[v_prev_cl] -= 1u; ++ v_n_bits += 1u; + #if defined(__GNUC__) + #pragma GCC diagnostic pop + #endif +- v_reversed_key = (((uint32_t)(WUFFS_DEFLATE__REVERSE8[(v_key >> 1u)])) | ((v_key & 1u) << 8u)); +- v_reversed_key >>= (9u - v_cl); +- v_symbol = ((uint32_t)(v_symbols[v_i])); +- if (v_symbol == 256u) { +- v_value = (536870912u | v_cl); +- } else if ((v_symbol < 256u) && (a_which == 0u)) { +- v_value = (2147483648u | (v_symbol << 8u) | v_cl); +- } else if (v_symbol >= a_base_symbol) { +- v_symbol -= a_base_symbol; +- if (a_which == 0u) { +- v_value = (WUFFS_DEFLATE__LCODE_MAGIC_NUMBERS[(v_symbol & 31u)] | v_cl); +- } else { +- v_value = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[(v_symbol & 31u)] | v_cl); +- } +- } else { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +- v_high_bits = v_initial_high_bits; +- v_delta = (((uint32_t)(1u)) << v_cl); +- while (v_high_bits >= v_delta) { +- v_high_bits -= v_delta; +- if ((v_top + ((v_high_bits | v_reversed_key) & 511u)) >= 1024u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } +- self->private_data.f_huffs[a_which][(v_top + ((v_high_bits | v_reversed_key) & 511u))] = v_value; + } ++ self->private_data.f_huffman_tables[a_which][v_i] = ((uint16_t)(((uint16_t)(v_child | ((uint16_t)(v_n_bits << 12u)))))); + v_i += 1u; +- if (v_i >= v_n_symbols) { +- break; +- } +- v_code += 1u; +- if (v_code >= 32768u) { +- return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- } + } +- return wuffs_base__make_status(NULL); ++ return wuffs_base__make_empty_struct(); + } + +-// ‼ WUFFS MULTI-FILE SECTION +x86_bmi2 +-// -------- func deflate.decoder.decode_huffman_bmi2 ++// -------- func bzip2.decoder.invert_bwt + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("bmi2") + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_bmi2( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++static wuffs_base__empty_struct ++wuffs_bzip2__decoder__invert_bwt( ++ wuffs_bzip2__decoder* self) { ++ uint32_t v_i = 0; ++ uint32_t v_letter = 0; ++ uint32_t v_sum = 0; ++ uint32_t v_old_sum = 0; + +- uint64_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint32_t v_table_entry = 0; +- uint32_t v_table_entry_n_bits = 0; +- uint64_t v_lmask = 0; +- uint64_t v_dmask = 0; +- uint32_t v_redir_top = 0; +- uint32_t v_redir_mask = 0; +- uint32_t v_length = 0; +- uint32_t v_dist_minus_1 = 0; +- uint32_t v_hlen = 0; +- uint32_t v_hdist = 0; +- uint32_t v_hdist_adjustment = 0; ++ v_sum = 0u; ++ v_i = 0u; ++ while (v_i < 256u) { ++ v_old_sum = v_sum; ++ v_sum += self->private_data.f_letter_counts[v_i]; ++ self->private_data.f_letter_counts[v_i] = v_old_sum; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < self->private_impl.f_block_size) { ++ v_letter = (self->private_data.f_bwt[v_i] & 255u); ++ self->private_data.f_bwt[(self->private_data.f_letter_counts[v_letter] & 1048575u)] |= (v_i << 12u); ++ self->private_data.f_letter_counts[v_letter] += 1u; ++ v_i += 1u; ++ } ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func bzip2.decoder.flush_fast ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_bzip2__decoder__flush_fast( ++ wuffs_bzip2__decoder* self, ++ wuffs_base__io_buffer* a_dst) { ++ uint32_t v_flush_pointer = 0; ++ uint32_t v_flush_repeat_count = 0; ++ uint8_t v_flush_prev = 0; ++ uint32_t v_block_checksum_have = 0; ++ uint32_t v_block_size = 0; ++ uint32_t v_entry = 0; ++ uint8_t v_curr = 0; + + uint8_t* iop_a_dst = NULL; + uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -35435,217 +35252,204 @@ wuffs_deflate__decoder__decode_huffman_bmi2( + io2_a_dst = iop_a_dst; + } + } +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } + +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; +- } +- v_bits = ((uint64_t)(self->private_impl.f_bits)); +- v_n_bits = self->private_impl.f_n_bits; +- v_lmask = ((((uint64_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); +- v_dmask = ((((uint64_t)(1u)) << self->private_impl.f_n_huffs_bits[1u]) - 1u); +- if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0u)) { +- status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position); +- goto exit; ++ v_flush_pointer = self->private_impl.f_flush_pointer; ++ v_flush_repeat_count = self->private_impl.f_flush_repeat_count; ++ v_flush_prev = self->private_impl.f_flush_prev; ++ v_block_checksum_have = self->private_impl.f_block_checksum_have; ++ v_block_size = self->private_impl.f_block_size; ++ while ((v_block_size > 0u) && (((uint64_t)(io2_a_dst - iop_a_dst)) >= 255u)) { ++ if (v_flush_repeat_count < 4u) { ++ v_entry = self->private_data.f_bwt[v_flush_pointer]; ++ v_curr = ((uint8_t)(v_entry)); ++ v_flush_pointer = (v_entry >> 12u); ++ if (v_curr == v_flush_prev) { ++ v_flush_repeat_count += 1u; ++ } else { ++ v_flush_repeat_count = 1u; ++ } ++ v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[((uint8_t)(((uint8_t)((v_block_checksum_have >> 24u))) ^ v_curr))] ^ ((uint32_t)(v_block_checksum_have << 8u))); ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_curr), iop_a_dst += 1); ++ v_flush_prev = v_curr; ++ v_block_size -= 1u; ++ } else { ++ v_entry = self->private_data.f_bwt[v_flush_pointer]; ++ v_curr = ((uint8_t)(v_entry)); ++ v_flush_pointer = (v_entry >> 12u); ++ v_flush_repeat_count = ((uint32_t)(v_curr)); ++ while (v_flush_repeat_count > 0u) { ++ v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[((uint8_t)(((uint8_t)((v_block_checksum_have >> 24u))) ^ v_flush_prev))] ^ ((uint32_t)(v_block_checksum_have << 8u))); ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) > 0u) { ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_flush_prev), iop_a_dst += 1); ++ } ++ v_flush_repeat_count -= 1u; ++ } ++ v_flush_repeat_count = 0u; ++ v_flush_prev = v_curr; ++ v_block_size -= 1u; ++ } + } +- v_hdist_adjustment = ((uint32_t)((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0u)))); +- label__loop__continue:; +- while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 8u)) { +- v_bits |= ((uint64_t)(wuffs_base__peek_u64le__no_bounds_check(iop_a_src) << (v_n_bits & 63u))); +- iop_a_src += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_lmask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 31u) != 0u) { +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); +- continue; +- } else if ((v_table_entry >> 30u) != 0u) { +- } else if ((v_table_entry >> 29u) != 0u) { +- self->private_impl.f_end_of_block = true; +- break; +- } else if ((v_table_entry >> 28u) != 0u) { +- v_redir_top = ((v_table_entry >> 8u) & 65535u); +- v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); +- v_table_entry = self->private_data.f_huffs[0u][((v_redir_top + (((uint32_t)(v_bits)) & v_redir_mask)) & 1023u)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 31u) != 0u) { +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); +- continue; +- } else if ((v_table_entry >> 30u) != 0u) { +- } else if ((v_table_entry >> 29u) != 0u) { +- self->private_impl.f_end_of_block = true; +- break; +- } else if ((v_table_entry >> 28u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } else if ((v_table_entry >> 27u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } +- } else if ((v_table_entry >> 27u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } +- v_length = (((v_table_entry >> 8u) & 255u) + 3u); +- v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); +- if (v_table_entry_n_bits > 0u) { +- v_length = (((v_length + 253u + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 255u) + 3u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- } +- v_table_entry = self->private_data.f_huffs[1u][(v_bits & v_dmask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 28u) == 1u) { +- v_redir_top = ((v_table_entry >> 8u) & 65535u); +- v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); +- v_table_entry = self->private_data.f_huffs[1u][((v_redir_top + (((uint32_t)(v_bits)) & v_redir_mask)) & 1023u)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- } +- if ((v_table_entry >> 24u) != 64u) { +- if ((v_table_entry >> 24u) == 8u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; ++ self->private_impl.f_flush_pointer = v_flush_pointer; ++ self->private_impl.f_flush_repeat_count = v_flush_repeat_count; ++ self->private_impl.f_flush_prev = v_flush_prev; ++ self->private_impl.f_block_checksum_have = v_block_checksum_have; ++ if (v_block_size <= 900000u) { ++ self->private_impl.f_block_size = v_block_size; ++ } ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func bzip2.decoder.flush_slow ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_bzip2__decoder__flush_slow( ++ wuffs_bzip2__decoder* self, ++ wuffs_base__io_buffer* a_dst) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_flush_pointer = 0; ++ uint32_t v_flush_repeat_count = 0; ++ uint8_t v_flush_prev = 0; ++ uint32_t v_block_checksum_have = 0; ++ uint32_t v_block_size = 0; ++ uint32_t v_entry = 0; ++ uint8_t v_curr = 0; ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; + } +- v_dist_minus_1 = ((v_table_entry >> 8u) & 32767u); +- v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); +- v_dist_minus_1 = ((v_dist_minus_1 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 32767u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- do { +- if (((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) { +- v_hlen = 0u; +- v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1u))) - ((uint64_t)(iop_a_dst - io0_a_dst))))); +- if (v_length > v_hdist) { +- v_length -= v_hdist; +- v_hlen = v_hdist; ++ } ++ ++ uint32_t coro_susp_point = self->private_impl.p_flush_slow; ++ if (coro_susp_point) { ++ v_flush_pointer = self->private_data.s_flush_slow.v_flush_pointer; ++ v_flush_repeat_count = self->private_data.s_flush_slow.v_flush_repeat_count; ++ v_flush_prev = self->private_data.s_flush_slow.v_flush_prev; ++ v_block_checksum_have = self->private_data.s_flush_slow.v_block_checksum_have; ++ v_block_size = self->private_data.s_flush_slow.v_block_size; ++ v_curr = self->private_data.s_flush_slow.v_curr; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ v_flush_pointer = self->private_impl.f_flush_pointer; ++ v_flush_repeat_count = self->private_impl.f_flush_repeat_count; ++ v_flush_prev = self->private_impl.f_flush_prev; ++ v_block_checksum_have = self->private_impl.f_block_checksum_have; ++ v_block_size = self->private_impl.f_block_size; ++ while ((v_block_size > 0u) && ! (self->private_impl.p_flush_slow != 0)) { ++ if (v_flush_repeat_count < 4u) { ++ v_entry = self->private_data.f_bwt[v_flush_pointer]; ++ v_curr = ((uint8_t)(v_entry)); ++ v_flush_pointer = (v_entry >> 12u); ++ if (v_curr == v_flush_prev) { ++ v_flush_repeat_count += 1u; + } else { +- v_hlen = v_length; +- v_length = 0u; +- } +- v_hdist += v_hdist_adjustment; +- if (self->private_impl.f_history_index < v_hdist) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_distance); +- goto exit; +- } +- wuffs_base__io_writer__limited_copy_u32_from_slice( +- &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767u), 33025)); +- if (v_length == 0u) { +- goto label__loop__continue; ++ v_flush_repeat_count = 1u; + } +- if ((((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8u))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance); +- goto exit; ++ v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[((uint8_t)(((uint8_t)((v_block_checksum_have >> 24u))) ^ v_curr))] ^ ((uint32_t)(v_block_checksum_have << 8u))); ++ self->private_data.s_flush_slow.scratch = v_curr; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (iop_a_dst == io2_a_dst) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ goto suspend; + } +- } +- if ((v_dist_minus_1 + 1u) >= 8u) { +- wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); +- } else if ((v_dist_minus_1 + 1u) == 1u) { +- wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ *iop_a_dst++ = ((uint8_t)(self->private_data.s_flush_slow.scratch)); ++ v_flush_prev = v_curr; ++ v_block_size -= 1u; + } else { +- wuffs_base__io_writer__limited_copy_u32_from_history_fast( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ v_entry = self->private_data.f_bwt[v_flush_pointer]; ++ v_curr = ((uint8_t)(v_entry)); ++ v_flush_pointer = (v_entry >> 12u); ++ v_flush_repeat_count = ((uint32_t)(v_curr)); ++ while (v_flush_repeat_count > 0u) { ++ v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[((uint8_t)(((uint8_t)((v_block_checksum_have >> 24u))) ^ v_flush_prev))] ^ ((uint32_t)(v_block_checksum_have << 8u))); ++ self->private_data.s_flush_slow.scratch = v_flush_prev; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (iop_a_dst == io2_a_dst) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ goto suspend; ++ } ++ *iop_a_dst++ = ((uint8_t)(self->private_data.s_flush_slow.scratch)); ++ v_flush_repeat_count -= 1u; ++ } ++ v_flush_repeat_count = 0u; ++ v_flush_prev = v_curr; ++ v_block_size -= 1u; + } +- } while (0); +- } +- if (v_n_bits > 63u) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; +- } +- while (v_n_bits >= 8u) { +- v_n_bits -= 8u; +- if (iop_a_src > io1_a_src) { +- iop_a_src--; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o); +- goto exit; + } +- } +- self->private_impl.f_bits = ((uint32_t)((v_bits & ((((uint64_t)(1u)) << v_n_bits) - 1u)))); +- self->private_impl.f_n_bits = v_n_bits; +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ self->private_impl.f_flush_pointer = v_flush_pointer; ++ self->private_impl.f_flush_repeat_count = v_flush_repeat_count; ++ self->private_impl.f_flush_prev = v_flush_prev; ++ self->private_impl.f_block_checksum_have = v_block_checksum_have; ++ if (v_block_size <= 900000u) { ++ self->private_impl.f_block_size = v_block_size; ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_flush_slow = 0; + goto exit; + } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_flush_slow = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_flush_slow.v_flush_pointer = v_flush_pointer; ++ self->private_data.s_flush_slow.v_flush_repeat_count = v_flush_repeat_count; ++ self->private_data.s_flush_slow.v_flush_prev = v_flush_prev; ++ self->private_data.s_flush_slow.v_block_checksum_have = v_block_checksum_have; ++ self->private_data.s_flush_slow.v_block_size = v_block_size; ++ self->private_data.s_flush_slow.v_curr = v_curr; ++ + goto exit; + exit: + if (a_dst && a_dst->data.ptr) { + a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); + } +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } + + return status; + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_bmi2 + +-// -------- func deflate.decoder.decode_huffman_fast32 ++// -------- func bzip2.decoder.decode_huffman_fast + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_fast32( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_bzip2__decoder__decode_huffman_fast( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + + uint32_t v_bits = 0; + uint32_t v_n_bits = 0; +- uint32_t v_table_entry = 0; +- uint32_t v_table_entry_n_bits = 0; +- uint32_t v_lmask = 0; +- uint32_t v_dmask = 0; +- uint32_t v_redir_top = 0; +- uint32_t v_redir_mask = 0; +- uint32_t v_length = 0; +- uint32_t v_dist_minus_1 = 0; +- uint32_t v_hlen = 0; +- uint32_t v_hdist = 0; +- uint32_t v_hdist_adjustment = 0; ++ uint32_t v_block_size = 0; ++ uint8_t v_which = 0; ++ uint32_t v_ticks = 0; ++ uint32_t v_section = 0; ++ uint32_t v_run_shift = 0; ++ uint16_t v_table_entry = 0; ++ uint16_t v_child = 0; ++ uint32_t v_child_ff = 0; ++ uint32_t v_i = 0; ++ uint32_t v_j = 0; ++ uint32_t v_output = 0; ++ uint32_t v_run = 0; ++ uint32_t v_mtft0 = 0; + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -35657,205 +35461,92 @@ wuffs_deflate__decoder__decode_huffman_fast32( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; +- } + v_bits = self->private_impl.f_bits; + v_n_bits = self->private_impl.f_n_bits; +- v_lmask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); +- v_dmask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[1u]) - 1u); +- if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0u)) { +- status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position); +- goto exit; +- } +- v_hdist_adjustment = ((uint32_t)((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0u)))); +- label__loop__continue:; +- while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 12u)) { +- if (v_n_bits < 15u) { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; ++ v_block_size = self->private_impl.f_block_size; ++ v_which = self->private_impl.f_decode_huffman_which; ++ v_ticks = self->private_impl.f_decode_huffman_ticks; ++ v_section = self->private_impl.f_decode_huffman_section; ++ v_run_shift = self->private_impl.f_decode_huffman_run_shift; ++ while (((uint64_t)(io2_a_src - iop_a_src)) >= 4u) { ++ if (v_ticks > 0u) { ++ v_ticks -= 1u; + } else { +- } +- v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_lmask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 31u) != 0u) { +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); +- continue; +- } else if ((v_table_entry >> 30u) != 0u) { +- } else if ((v_table_entry >> 29u) != 0u) { +- self->private_impl.f_end_of_block = true; +- break; +- } else if ((v_table_entry >> 28u) != 0u) { +- if (v_n_bits < 15u) { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- } else { +- } +- v_redir_top = ((v_table_entry >> 8u) & 65535u); +- v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); +- v_table_entry = self->private_data.f_huffs[0u][((v_redir_top + (v_bits & v_redir_mask)) & 1023u)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 31u) != 0u) { +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); +- continue; +- } else if ((v_table_entry >> 30u) != 0u) { +- } else if ((v_table_entry >> 29u) != 0u) { +- self->private_impl.f_end_of_block = true; +- break; +- } else if ((v_table_entry >> 28u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } else if ((v_table_entry >> 27u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ v_ticks = 49u; ++ v_section += 1u; ++ if (v_section >= self->private_impl.f_num_sections) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_number_of_sections); + goto exit; + } +- } else if ((v_table_entry >> 27u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } +- v_length = (((v_table_entry >> 8u) & 255u) + 3u); +- v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); +- if (v_table_entry_n_bits > 0u) { +- if (v_n_bits < 15u) { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- } else { +- } +- v_length = (((v_length + 253u + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 255u) + 3u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- } else { +- } +- if (v_n_bits < 15u) { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- } else { ++ v_which = WUFFS_BZIP2__CLAMP_TO_5[((uint8_t)(self->private_data.f_huffman_selectors[(v_section & 32767u)] & 7u))]; + } +- v_table_entry = self->private_data.f_huffs[1u][(v_bits & v_dmask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 28u) == 1u) { +- if (v_n_bits < 15u) { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- } else { ++ v_bits |= (wuffs_base__peek_u32be__no_bounds_check(iop_a_src) >> v_n_bits); ++ iop_a_src += ((31u - v_n_bits) >> 3u); ++ v_n_bits |= 24u; ++ v_table_entry = self->private_data.f_huffman_tables[v_which][(v_bits >> 24u)]; ++ v_bits <<= ((uint16_t)(v_table_entry >> 12u)); ++ v_n_bits -= ((uint32_t)(((uint16_t)(v_table_entry >> 12u)))); ++ v_child = ((uint16_t)(v_table_entry & 1023u)); ++ while (v_child < 257u) { ++ v_child = self->private_data.f_huffman_trees[v_which][v_child][(v_bits >> 31u)]; ++ v_bits <<= 1u; ++ if (v_n_bits <= 0u) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; + } +- v_redir_top = ((v_table_entry >> 8u) & 65535u); +- v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); +- v_table_entry = self->private_data.f_huffs[1u][((v_redir_top + (v_bits & v_redir_mask)) & 1023u)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- } else { ++ v_n_bits -= 1u; + } +- if ((v_table_entry >> 24u) != 64u) { +- if ((v_table_entry >> 24u) == 8u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ if (v_child < 768u) { ++ v_child_ff = ((uint32_t)(((uint16_t)(v_child & 255u)))); ++ v_output = ((uint32_t)(self->private_data.f_mtft[v_child_ff])); ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1u + v_child_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_child_ff)); ++ self->private_data.f_mtft[0u] = ((uint8_t)(v_output)); ++ self->private_data.f_letter_counts[v_output] += 1u; ++ self->private_data.f_bwt[v_block_size] = v_output; ++ if (v_block_size >= self->private_impl.f_max_incl_block_size) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); + goto exit; + } +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; ++ v_block_size += 1u; ++ v_run_shift = 0u; ++ continue; ++ } else if (v_child == 768u) { ++ self->private_impl.f_decode_huffman_finished = true; ++ break; + } +- v_dist_minus_1 = ((v_table_entry >> 8u) & 32767u); +- v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); +- if (v_n_bits < v_table_entry_n_bits) { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; ++ if (v_run_shift >= 23u) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); ++ goto exit; + } +- v_dist_minus_1 = ((v_dist_minus_1 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 32767u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- do { +- if (((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) { +- v_hlen = 0u; +- v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1u))) - ((uint64_t)(iop_a_dst - io0_a_dst))))); +- if (v_length > v_hdist) { +- v_length -= v_hdist; +- v_hlen = v_hdist; +- } else { +- v_hlen = v_length; +- v_length = 0u; +- } +- v_hdist += v_hdist_adjustment; +- if (self->private_impl.f_history_index < v_hdist) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_distance); +- goto exit; +- } +- wuffs_base__io_writer__limited_copy_u32_from_slice( +- &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767u), 33025)); +- if (v_length == 0u) { +- goto label__loop__continue; +- } +- if ((((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8u))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance); +- goto exit; +- } +- } +- if ((v_dist_minus_1 + 1u) >= 8u) { +- wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); +- } else { +- wuffs_base__io_writer__limited_copy_u32_from_history_fast( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); +- } +- } while (0); +- } +- while (v_n_bits >= 8u) { +- v_n_bits -= 8u; +- if (iop_a_src > io1_a_src) { +- iop_a_src--; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o); ++ v_run = ((((uint32_t)(v_child)) & 3u) << v_run_shift); ++ v_run_shift += 1u; ++ v_i = v_block_size; ++ v_j = (v_run + v_block_size); ++ if (v_j > self->private_impl.f_max_incl_block_size) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); + goto exit; + } ++ v_block_size = v_j; ++ v_mtft0 = ((uint32_t)(self->private_data.f_mtft[0u])); ++ self->private_data.f_letter_counts[v_mtft0] += v_run; ++ while (v_i < v_j) { ++ self->private_data.f_bwt[v_i] = v_mtft0; ++ v_i += 1u; ++ } + } +- self->private_impl.f_bits = (v_bits & ((((uint32_t)(1u)) << v_n_bits) - 1u)); ++ self->private_impl.f_bits = v_bits; + self->private_impl.f_n_bits = v_n_bits; +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; +- } ++ self->private_impl.f_block_size = v_block_size; ++ self->private_impl.f_decode_huffman_which = v_which; ++ self->private_impl.f_decode_huffman_ticks = v_ticks; ++ self->private_impl.f_decode_huffman_section = v_section; ++ self->private_impl.f_decode_huffman_run_shift = v_run_shift; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ ++ ok: + goto exit; + exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -35863,52 +35554,25 @@ wuffs_deflate__decoder__decode_huffman_fast32( + return status; + } + +-// -------- func deflate.decoder.decode_huffman_fast64 ++// -------- func bzip2.decoder.decode_huffman_slow + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_fast64( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_bzip2__decoder__decode_huffman_slow( ++ wuffs_bzip2__decoder* self, + wuffs_base__io_buffer* a_src) { +- return (*self->private_impl.choosy_decode_huffman_fast64)(self, a_dst, a_src); +-} ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_fast64__choosy_default( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint64_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint32_t v_table_entry = 0; +- uint32_t v_table_entry_n_bits = 0; +- uint64_t v_lmask = 0; +- uint64_t v_dmask = 0; +- uint32_t v_redir_top = 0; +- uint32_t v_redir_mask = 0; +- uint32_t v_length = 0; +- uint32_t v_dist_minus_1 = 0; +- uint32_t v_hlen = 0; +- uint32_t v_hdist = 0; +- uint32_t v_hdist_adjustment = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_node_index = 0; ++ uint16_t v_child = 0; ++ uint32_t v_child_ff = 0; ++ uint32_t v_i = 0; ++ uint32_t v_j = 0; ++ uint32_t v_output = 0; ++ uint32_t v_run = 0; ++ uint32_t v_mtft0 = 0; + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -35920,160 +35584,101 @@ wuffs_deflate__decoder__decode_huffman_fast64__choosy_default( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; +- } +- v_bits = ((uint64_t)(self->private_impl.f_bits)); +- v_n_bits = self->private_impl.f_n_bits; +- v_lmask = ((((uint64_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); +- v_dmask = ((((uint64_t)(1u)) << self->private_impl.f_n_huffs_bits[1u]) - 1u); +- if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0u)) { +- status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position); +- goto exit; ++ uint32_t coro_susp_point = self->private_impl.p_decode_huffman_slow; ++ if (coro_susp_point) { ++ v_node_index = self->private_data.s_decode_huffman_slow.v_node_index; + } +- v_hdist_adjustment = ((uint32_t)((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0u)))); +- label__loop__continue:; +- while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 8u)) { +- v_bits |= ((uint64_t)(wuffs_base__peek_u64le__no_bounds_check(iop_a_src) << (v_n_bits & 63u))); +- iop_a_src += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_lmask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 31u) != 0u) { +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); +- continue; +- } else if ((v_table_entry >> 30u) != 0u) { +- } else if ((v_table_entry >> 29u) != 0u) { +- self->private_impl.f_end_of_block = true; +- break; +- } else if ((v_table_entry >> 28u) != 0u) { +- v_redir_top = ((v_table_entry >> 8u) & 65535u); +- v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); +- v_table_entry = self->private_data.f_huffs[0u][((v_redir_top + (((uint32_t)(v_bits)) & v_redir_mask)) & 1023u)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 31u) != 0u) { +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); +- continue; +- } else if ((v_table_entry >> 30u) != 0u) { +- } else if ((v_table_entry >> 29u) != 0u) { +- self->private_impl.f_end_of_block = true; +- break; +- } else if ((v_table_entry >> 28u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } else if ((v_table_entry >> 27u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while ( ! (self->private_impl.p_decode_huffman_slow != 0)) { ++ if (self->private_impl.f_decode_huffman_ticks > 0u) { ++ self->private_impl.f_decode_huffman_ticks -= 1u; + } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } +- } else if ((v_table_entry >> 27u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } +- v_length = (((v_table_entry >> 8u) & 255u) + 3u); +- v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); +- if (v_table_entry_n_bits > 0u) { +- v_length = (((v_length + 253u + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 255u) + 3u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- } +- v_table_entry = self->private_data.f_huffs[1u][(v_bits & v_dmask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- if ((v_table_entry >> 28u) == 1u) { +- v_redir_top = ((v_table_entry >> 8u) & 65535u); +- v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); +- v_table_entry = self->private_data.f_huffs[1u][((v_redir_top + (((uint32_t)(v_bits)) & v_redir_mask)) & 1023u)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- } +- if ((v_table_entry >> 24u) != 64u) { +- if ((v_table_entry >> 24u) == 8u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; ++ self->private_impl.f_decode_huffman_ticks = 49u; ++ self->private_impl.f_decode_huffman_section += 1u; ++ if (self->private_impl.f_decode_huffman_section >= self->private_impl.f_num_sections) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_number_of_sections); ++ goto exit; ++ } ++ self->private_impl.f_decode_huffman_which = WUFFS_BZIP2__CLAMP_TO_5[((uint8_t)(self->private_data.f_huffman_selectors[(self->private_impl.f_decode_huffman_section & 32767u)] & 7u))]; + } +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } +- v_dist_minus_1 = ((v_table_entry >> 8u) & 32767u); +- v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); +- v_dist_minus_1 = ((v_dist_minus_1 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 32767u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- do { +- if (((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) { +- v_hlen = 0u; +- v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1u))) - ((uint64_t)(iop_a_dst - io0_a_dst))))); +- if (v_length > v_hdist) { +- v_length -= v_hdist; +- v_hlen = v_hdist; +- } else { +- v_hlen = v_length; +- v_length = 0u; ++ v_node_index = 0u; ++ while (true) { ++ if (self->private_impl.f_n_bits <= 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ self->private_impl.f_bits = (((uint32_t)(v_c8)) << 24u); ++ self->private_impl.f_n_bits = 8u; + } +- v_hdist += v_hdist_adjustment; +- if (self->private_impl.f_history_index < v_hdist) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_distance); +- goto exit; ++ v_child = self->private_data.f_huffman_trees[self->private_impl.f_decode_huffman_which][v_node_index][(self->private_impl.f_bits >> 31u)]; ++ self->private_impl.f_bits <<= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ if (v_child < 257u) { ++ v_node_index = ((uint32_t)(v_child)); ++ continue; ++ } else if (v_child < 768u) { ++ v_child_ff = ((uint32_t)(((uint16_t)(v_child & 255u)))); ++ v_output = ((uint32_t)(self->private_data.f_mtft[v_child_ff])); ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1u + v_child_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_child_ff)); ++ self->private_data.f_mtft[0u] = ((uint8_t)(v_output)); ++ self->private_data.f_letter_counts[v_output] += 1u; ++ self->private_data.f_bwt[self->private_impl.f_block_size] = v_output; ++ if (self->private_impl.f_block_size >= self->private_impl.f_max_incl_block_size) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); ++ goto exit; ++ } ++ self->private_impl.f_block_size += 1u; ++ self->private_impl.f_decode_huffman_run_shift = 0u; ++ break; ++ } else if (v_child == 768u) { ++ self->private_impl.f_decode_huffman_finished = true; ++ goto label__outer__break; + } +- wuffs_base__io_writer__limited_copy_u32_from_slice( +- &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767u), 33025)); +- if (v_length == 0u) { +- goto label__loop__continue; ++ if (self->private_impl.f_decode_huffman_run_shift >= 23u) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); ++ goto exit; + } +- if ((((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8u))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance); ++ v_run = ((((uint32_t)(v_child)) & 3u) << self->private_impl.f_decode_huffman_run_shift); ++ self->private_impl.f_decode_huffman_run_shift += 1u; ++ v_i = self->private_impl.f_block_size; ++ v_j = (v_run + self->private_impl.f_block_size); ++ if (v_j > self->private_impl.f_max_incl_block_size) { ++ status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length); + goto exit; + } ++ self->private_impl.f_block_size = v_j; ++ v_mtft0 = ((uint32_t)(self->private_data.f_mtft[0u])); ++ self->private_data.f_letter_counts[v_mtft0] += v_run; ++ while (v_i < v_j) { ++ self->private_data.f_bwt[v_i] = v_mtft0; ++ v_i += 1u; ++ } ++ break; + } +- if ((v_dist_minus_1 + 1u) >= 8u) { +- wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); +- } else if ((v_dist_minus_1 + 1u) == 1u) { +- wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); +- } else { +- wuffs_base__io_writer__limited_copy_u32_from_history_fast( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); +- } +- } while (0); +- } +- if (v_n_bits > 63u) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; +- } +- while (v_n_bits >= 8u) { +- v_n_bits -= 8u; +- if (iop_a_src > io1_a_src) { +- iop_a_src--; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o); +- goto exit; + } +- } +- self->private_impl.f_bits = ((uint32_t)((v_bits & ((((uint64_t)(1u)) << v_n_bits) - 1u)))); +- self->private_impl.f_n_bits = v_n_bits; +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ label__outer__break:; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_huffman_slow = 0; + goto exit; + } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_huffman_slow = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_huffman_slow.v_node_index = v_node_index; ++ + goto exit; + exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -36081,40 +35686,229 @@ wuffs_deflate__decoder__decode_huffman_fast64__choosy_default( + return status; + } + +-// -------- func deflate.decoder.decode_huffman_slow ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BZIP2) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_cbor__error__bad_input[] = "#cbor: bad input"; ++const char wuffs_cbor__error__unsupported_recursion_depth[] = "#cbor: unsupported recursion depth"; ++const char wuffs_cbor__error__internal_error_inconsistent_i_o[] = "#cbor: internal error: inconsistent I/O"; ++const char wuffs_cbor__error__internal_error_inconsistent_token_length[] = "#cbor: internal error: inconsistent token length"; ++ ++// ---------------- Private Consts ++ ++static const uint32_t ++WUFFS_CBOR__LITERALS[4] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 8388612u, 8388616u, 8388610u, 8388609u, ++}; ++ ++static const uint8_t ++WUFFS_CBOR__TOKEN_LENGTHS[32] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, ++ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, ++ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, ++ 2u, 3u, 5u, 9u, 0u, 0u, 0u, 1u, ++}; ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++// ---------------- VTables ++ ++const wuffs_base__token_decoder__func_ptrs ++wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__token_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_cbor__decoder__decode_tokens), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_cbor__decoder__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_cbor__decoder__set_quirk), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_cbor__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_cbor__decoder__initialize( ++ wuffs_cbor__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name = ++ wuffs_base__token_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers = ++ (const void*)(&wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_cbor__decoder* ++wuffs_cbor__decoder__alloc(void) { ++ wuffs_cbor__decoder* x = ++ (wuffs_cbor__decoder*)(calloc(1, sizeof(wuffs_cbor__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_cbor__decoder__initialize( ++ x, sizeof(wuffs_cbor__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_cbor__decoder(void) { ++ return sizeof(wuffs_cbor__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func cbor.decoder.get_quirk + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_deflate__decoder__decode_huffman_slow( +- wuffs_deflate__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src) { ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_cbor__decoder__get_quirk( ++ const wuffs_cbor__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func cbor.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_cbor__decoder__set_quirk( ++ wuffs_cbor__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func cbor.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_cbor__decoder__workbuf_len( ++ const wuffs_cbor__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__empty_range_ii_u64(); ++} ++ ++// -------- func cbor.decoder.decode_tokens ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_cbor__decoder__decode_tokens( ++ wuffs_cbor__decoder* self, ++ wuffs_base__token_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint32_t v_table_entry = 0; +- uint32_t v_table_entry_n_bits = 0; +- uint32_t v_lmask = 0; +- uint32_t v_dmask = 0; +- uint32_t v_b0 = 0; +- uint32_t v_redir_top = 0; +- uint32_t v_redir_mask = 0; +- uint32_t v_b1 = 0; +- uint32_t v_length = 0; +- uint32_t v_b2 = 0; +- uint32_t v_b3 = 0; +- uint32_t v_b4 = 0; +- uint32_t v_dist_minus_1 = 0; +- uint32_t v_b5 = 0; +- uint32_t v_n_copied = 0; +- uint32_t v_hlen = 0; +- uint32_t v_hdist = 0; ++ uint64_t v_string_length = 0; ++ uint64_t v_n64 = 0; ++ uint32_t v_depth = 0; ++ uint32_t v_stack_byte = 0; ++ uint32_t v_stack_bit = 0; ++ uint32_t v_stack_val = 0; ++ uint32_t v_token_length = 0; ++ uint32_t v_vminor = 0; ++ uint32_t v_vminor_alt = 0; ++ uint32_t v_continued = 0; ++ uint8_t v_c8 = 0; ++ uint8_t v_c_major = 0; ++ uint8_t v_c_minor = 0; ++ bool v_tagged = false; ++ uint8_t v_indefinite_string_major_type = 0; + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ 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 && a_dst->data.ptr) { + io0_a_dst = a_dst->data.ptr; + io1_a_dst = io0_a_dst + a_dst->meta.wi; +@@ -36135,269 +35929,513 @@ wuffs_deflate__decoder__decode_huffman_slow( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_huffman_slow[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_tokens; + if (coro_susp_point) { +- v_bits = self->private_data.s_decode_huffman_slow[0].v_bits; +- v_n_bits = self->private_data.s_decode_huffman_slow[0].v_n_bits; +- v_table_entry_n_bits = self->private_data.s_decode_huffman_slow[0].v_table_entry_n_bits; +- v_lmask = self->private_data.s_decode_huffman_slow[0].v_lmask; +- v_dmask = self->private_data.s_decode_huffman_slow[0].v_dmask; +- v_redir_top = self->private_data.s_decode_huffman_slow[0].v_redir_top; +- v_redir_mask = self->private_data.s_decode_huffman_slow[0].v_redir_mask; +- v_length = self->private_data.s_decode_huffman_slow[0].v_length; +- v_dist_minus_1 = self->private_data.s_decode_huffman_slow[0].v_dist_minus_1; ++ v_string_length = self->private_data.s_decode_tokens.v_string_length; ++ v_depth = self->private_data.s_decode_tokens.v_depth; ++ v_tagged = self->private_data.s_decode_tokens.v_tagged; ++ v_indefinite_string_major_type = self->private_data.s_decode_tokens.v_indefinite_string_major_type; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; ++ if (self->private_impl.f_end_of_data) { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; + } +- v_bits = self->private_impl.f_bits; +- v_n_bits = self->private_impl.f_n_bits; +- v_lmask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); +- v_dmask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[1u]) - 1u); +- label__loop__continue:; +- while ( ! (self->private_impl.p_decode_huffman_slow[0] != 0)) { ++ label__outer__continue:; ++ while (true) { + while (true) { +- v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_lmask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- if (v_n_bits >= v_table_entry_n_bits) { +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- break; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ do { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ goto label__outer__continue; + } +- uint32_t t_0 = *iop_a_src++; +- v_b0 = t_0; +- } +- v_bits |= (v_b0 << v_n_bits); +- v_n_bits += 8u; +- } +- if ((v_table_entry >> 31u) != 0u) { +- self->private_data.s_decode_huffman_slow[0].scratch = ((uint8_t)((v_table_entry >> 8u))); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (iop_a_dst == io2_a_dst) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- goto suspend; +- } +- *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_huffman_slow[0].scratch)); +- continue; +- } else if ((v_table_entry >> 30u) != 0u) { +- } else if ((v_table_entry >> 29u) != 0u) { +- self->private_impl.f_end_of_block = true; +- break; +- } else if ((v_table_entry >> 28u) != 0u) { +- v_redir_top = ((v_table_entry >> 8u) & 65535u); +- v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); +- while (true) { +- v_table_entry = self->private_data.f_huffs[0u][((v_redir_top + (v_bits & v_redir_mask)) & 1023u)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- if (v_n_bits >= v_table_entry_n_bits) { +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- break; ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_cbor__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ goto label__outer__continue; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if ((v_indefinite_string_major_type != 0u) && (v_indefinite_string_major_type != ((uint8_t)(v_c8 >> 5u)))) { ++ if (v_c8 != 255u) { ++ status = wuffs_base__make_status(wuffs_cbor__error__bad_input); ++ goto exit; + } +- uint32_t t_1 = *iop_a_src++; +- v_b1 = t_1; ++ v_vminor = 4194560u; ++ if (v_indefinite_string_major_type == 3u) { ++ v_vminor |= 19u; ++ } ++ v_indefinite_string_major_type = 0u; ++ iop_a_src += 1u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; + } +- v_bits |= (v_b1 << v_n_bits); +- v_n_bits += 8u; +- } +- if ((v_table_entry >> 31u) != 0u) { +- self->private_data.s_decode_huffman_slow[0].scratch = ((uint8_t)((v_table_entry >> 8u))); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (iop_a_dst == io2_a_dst) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- goto suspend; ++ iop_a_src += 1u; ++ v_c_major = ((uint8_t)(((uint8_t)(v_c8 >> 5u)))); ++ v_c_minor = ((uint8_t)(v_c8 & 31u)); ++ if (v_c_minor < 24u) { ++ v_string_length = ((uint64_t)(v_c_minor)); ++ } else { ++ while (true) { ++ if (v_c_minor == 24u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= 1u) { ++ v_string_length = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))); ++ iop_a_src += 1u; ++ break; ++ } ++ } else if (v_c_minor == 25u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= 2u) { ++ v_string_length = ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2u; ++ break; ++ } ++ } else if (v_c_minor == 26u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= 4u) { ++ v_string_length = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4u; ++ break; ++ } ++ } else if (v_c_minor == 27u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= 8u) { ++ v_string_length = wuffs_base__peek_u64be__no_bounds_check(iop_a_src); ++ iop_a_src += 8u; ++ break; ++ } ++ } else { ++ v_string_length = 0u; ++ break; ++ } ++ if (iop_a_src > io1_a_src) { ++ iop_a_src--; ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_cbor__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ goto label__outer__continue; ++ } ++ status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } + } +- *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_huffman_slow[0].scratch)); +- continue; +- } else if ((v_table_entry >> 30u) != 0u) { +- } else if ((v_table_entry >> 29u) != 0u) { +- self->private_impl.f_end_of_block = true; +- break; +- } else if ((v_table_entry >> 28u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } else if ((v_table_entry >> 27u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ if (v_c_major == 0u) { ++ if (v_c_minor < 26u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((14680064u | ((uint32_t)((v_string_length & 65535u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } else if (v_c_minor < 28u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((14680064u | ((uint32_t)((v_string_length >> 46u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ *iop_a_dst++ = wuffs_base__make_token( ++ (~(v_string_length & 70368744177663u) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ } else if (v_c_major == 1u) { ++ if (v_c_minor < 26u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((12582912u | (2097151u - ((uint32_t)((v_string_length & 65535u))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } else if (v_c_minor < 28u) { ++ if (v_string_length < 9223372036854775808u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((12582912u | (2097151u - ((uint32_t)((v_string_length >> 46u))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ *iop_a_dst++ = wuffs_base__make_token( ++ (~((18446744073709551615u - v_string_length) & 70368744177663u) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } else { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | ++ (((uint64_t)(16777216u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(9u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ } else if (v_c_major == 2u) { ++ if (v_c_minor < 28u) { ++ if (v_string_length == 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194560u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194560u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } else if (v_c_minor == 31u) { ++ if (v_indefinite_string_major_type != 0u) { ++ break; ++ } ++ v_indefinite_string_major_type = 2u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194560u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__outer__continue; ++ } else { ++ break; ++ } ++ while (true) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ continue; ++ } ++ v_n64 = wuffs_base__u64__min(v_string_length, ((uint64_t)(io2_a_src - iop_a_src))); ++ v_token_length = ((uint32_t)((v_n64 & 65535u))); ++ if (v_n64 > 65535u) { ++ v_token_length = 65535u; ++ } else if (v_token_length <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_cbor__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ continue; ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) { ++ status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length); ++ goto exit; ++ } ++ v_string_length -= ((uint64_t)(v_token_length)); ++ v_continued = 0u; ++ if ((v_string_length > 0u) || (v_indefinite_string_major_type > 0u)) { ++ v_continued = 1u; ++ } ++ iop_a_src += v_token_length; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194816u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (v_string_length > 0u) { ++ continue; ++ } else if (v_indefinite_string_major_type > 0u) { ++ goto label__outer__continue; ++ } ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ } else if (v_c_major == 3u) { ++ if (v_c_minor < 28u) { ++ if (v_string_length == 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } else if (v_c_minor == 31u) { ++ if (v_indefinite_string_major_type != 0u) { ++ break; ++ } ++ v_indefinite_string_major_type = 3u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__outer__continue; ++ } else { ++ break; ++ } ++ while (true) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); ++ continue; ++ } ++ v_n64 = wuffs_base__u64__min(v_string_length, 65535u); ++ v_n64 = ((uint64_t)(wuffs_base__utf_8__longest_valid_prefix(iop_a_src, ++ ((size_t)(wuffs_base__u64__min(((uint64_t)(io2_a_src - iop_a_src)), v_n64)))))); ++ v_token_length = ((uint32_t)((v_n64 & 65535u))); ++ if (v_token_length <= 0u) { ++ if ((a_src && a_src->meta.closed) || (((uint64_t)(io2_a_src - iop_a_src)) >= 4u)) { ++ status = wuffs_base__make_status(wuffs_cbor__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); ++ continue; ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) { ++ status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length); ++ goto exit; ++ } ++ v_string_length -= ((uint64_t)(v_token_length)); ++ v_continued = 0u; ++ if ((v_string_length > 0u) || (v_indefinite_string_major_type > 0u)) { ++ v_continued = 1u; ++ } ++ iop_a_src += v_token_length; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (v_string_length > 0u) { ++ continue; ++ } else if (v_indefinite_string_major_type > 0u) { ++ goto label__outer__continue; ++ } ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ } else if (v_c_major == 4u) { ++ if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0u) { ++ break; ++ } else if (v_depth >= 1024u) { ++ v_token_length = ((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])); ++ while ((v_token_length > 0u) && (iop_a_src > io1_a_src)) { ++ iop_a_src--; ++ v_token_length -= 1u; ++ } ++ status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth); ++ goto exit; ++ } ++ v_vminor = 2105361u; ++ v_vminor_alt = 2101282u; ++ if (v_depth > 0u) { ++ v_stack_byte = ((v_depth - 1u) / 16u); ++ v_stack_bit = (((v_depth - 1u) & 15u) * 2u); ++ if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { ++ v_vminor = 2105377u; ++ v_vminor_alt = 2105378u; ++ } else { ++ v_vminor = 2105409u; ++ v_vminor_alt = 2113570u; ++ } ++ } ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (v_c_minor == 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ v_stack_byte = (v_depth / 16u); ++ v_stack_bit = ((v_depth & 15u) * 2u); ++ self->private_data.f_stack[v_stack_byte] &= (4294967295u ^ (((uint32_t)(3u)) << v_stack_bit)); ++ self->private_data.f_container_num_remaining[v_depth] = v_string_length; ++ v_depth += 1u; ++ v_tagged = false; ++ goto label__outer__continue; ++ } else if (v_c_major == 5u) { ++ if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0u) { ++ break; ++ } else if (v_depth >= 1024u) { ++ v_token_length = ((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])); ++ while ((v_token_length > 0u) && (iop_a_src > io1_a_src)) { ++ iop_a_src--; ++ v_token_length -= 1u; ++ } ++ status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth); ++ goto exit; ++ } ++ v_vminor = 2113553u; ++ v_vminor_alt = 2101314u; ++ if (v_depth > 0u) { ++ v_stack_byte = ((v_depth - 1u) / 16u); ++ v_stack_bit = (((v_depth - 1u) & 15u) * 2u); ++ if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { ++ v_vminor = 2113569u; ++ v_vminor_alt = 2105410u; ++ } else { ++ v_vminor = 2113601u; ++ v_vminor_alt = 2113602u; ++ } ++ } ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (v_c_minor == 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ v_stack_byte = (v_depth / 16u); ++ v_stack_bit = ((v_depth & 15u) * 2u); ++ self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(3u)) << v_stack_bit); ++ self->private_data.f_container_num_remaining[v_depth] = v_string_length; ++ v_depth += 1u; ++ v_tagged = false; ++ goto label__outer__continue; ++ } else if (v_c_major == 6u) { ++ if (v_c_minor >= 28u) { ++ break; ++ } ++ if (v_string_length < 262144u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | ++ (((uint64_t)((4194304u | ((uint32_t)(v_string_length))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } else { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | ++ (((uint64_t)((4194304u | ((uint32_t)((v_string_length >> 46u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ *iop_a_dst++ = wuffs_base__make_token( ++ (~(v_string_length & 70368744177663u) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } ++ v_tagged = true; ++ goto label__outer__continue; ++ } else if (v_c_major == 7u) { ++ if (v_c_minor < 20u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | ++ (((uint64_t)((8388608u | ((uint32_t)((v_string_length & 255u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } else if (v_c_minor < 24u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(WUFFS_CBOR__LITERALS[((uint8_t)(v_c_minor & 3u))])) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } else if (v_c_minor == 24u) { ++ if (v_string_length < 24u) { ++ if ( ! (iop_a_src > io1_a_src)) { ++ status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ iop_a_src--; ++ break; ++ } ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(787997u)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | ++ (((uint64_t)((8388608u | ((uint32_t)((v_string_length & 255u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } else if (v_c_minor < 28u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(10490113u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } else if (v_c_minor == 31u) { ++ if (v_tagged || (v_depth <= 0u)) { ++ break; ++ } ++ v_depth -= 1u; ++ if (self->private_data.f_container_num_remaining[v_depth] != 0u) { ++ break; ++ } ++ v_stack_byte = (v_depth / 16u); ++ v_stack_bit = ((v_depth & 15u) * 2u); ++ v_stack_val = (3u & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit)); ++ if (v_stack_val == 1u) { ++ break; ++ } ++ if (v_stack_val != 3u) { ++ v_vminor_alt = 2097186u; ++ } else { ++ v_vminor_alt = 2097218u; ++ } ++ if (v_depth <= 0u) { ++ v_vminor_alt |= 4096u; ++ } else { ++ v_stack_byte = ((v_depth - 1u) / 16u); ++ v_stack_bit = (((v_depth - 1u) & 15u) * 2u); ++ if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { ++ v_vminor_alt |= 8192u; ++ } else { ++ v_vminor_alt |= 16384u; ++ } ++ } ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__goto_parsed_a_leaf_value__break; ++ } ++ } ++ } while (0); ++ if (iop_a_src > io1_a_src) { ++ iop_a_src--; ++ status = wuffs_base__make_status(wuffs_cbor__error__bad_input); + goto exit; + } +- } else if ((v_table_entry >> 27u) != 0u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o); + goto exit; + } +- v_length = (((v_table_entry >> 8u) & 255u) + 3u); +- v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); +- if (v_table_entry_n_bits > 0u) { +- while (v_n_bits < v_table_entry_n_bits) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint32_t t_2 = *iop_a_src++; +- v_b2 = t_2; +- } +- v_bits |= (v_b2 << v_n_bits); +- v_n_bits += 8u; ++ label__goto_parsed_a_leaf_value__break:; ++ v_tagged = false; ++ while (v_depth > 0u) { ++ v_stack_byte = ((v_depth - 1u) / 16u); ++ v_stack_bit = (((v_depth - 1u) & 15u) * 2u); ++ self->private_data.f_stack[v_stack_byte] ^= (((uint32_t)(1u)) << (v_stack_bit + 1u)); ++ if (1u == (3u & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit))) { ++ goto label__outer__continue; + } +- v_length = (((v_length + 253u + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 255u) + 3u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- } +- while (true) { +- v_table_entry = self->private_data.f_huffs[1u][(v_bits & v_dmask)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- if (v_n_bits >= v_table_entry_n_bits) { +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- break; ++ if (self->private_data.f_container_num_remaining[(v_depth - 1u)] <= 0u) { ++ goto label__outer__continue; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint32_t t_3 = *iop_a_src++; +- v_b3 = t_3; +- } +- v_bits |= (v_b3 << v_n_bits); +- v_n_bits += 8u; +- } +- if ((v_table_entry >> 28u) == 1u) { +- v_redir_top = ((v_table_entry >> 8u) & 65535u); +- v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); +- while (true) { +- v_table_entry = self->private_data.f_huffs[1u][((v_redir_top + (v_bits & v_redir_mask)) & 1023u)]; +- v_table_entry_n_bits = (v_table_entry & 15u); +- if (v_n_bits >= v_table_entry_n_bits) { +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- break; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint32_t t_4 = *iop_a_src++; +- v_b4 = t_4; +- } +- v_bits |= (v_b4 << v_n_bits); +- v_n_bits += 8u; ++ self->private_data.f_container_num_remaining[(v_depth - 1u)] -= 1u; ++ if (self->private_data.f_container_num_remaining[(v_depth - 1u)] > 0u) { ++ goto label__outer__continue; + } +- } +- if ((v_table_entry >> 24u) != 64u) { +- if ((v_table_entry >> 24u) == 8u) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); +- goto exit; ++ while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); ++ continue; + } +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); +- goto exit; +- } +- v_dist_minus_1 = ((v_table_entry >> 8u) & 32767u); +- v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); +- if (v_table_entry_n_bits > 0u) { +- while (v_n_bits < v_table_entry_n_bits) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint32_t t_5 = *iop_a_src++; +- v_b5 = t_5; +- } +- v_bits |= (v_b5 << v_n_bits); +- v_n_bits += 8u; ++ v_depth -= 1u; ++ v_stack_byte = (v_depth / 16u); ++ v_stack_bit = ((v_depth & 15u) * 2u); ++ if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { ++ v_vminor_alt = 2097186u; ++ } else { ++ v_vminor_alt = 2097218u; + } +- v_dist_minus_1 = ((v_dist_minus_1 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 32767u); +- v_bits >>= v_table_entry_n_bits; +- v_n_bits -= v_table_entry_n_bits; +- } +- while (true) { +- if (((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) { +- v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1u))) - ((uint64_t)(iop_a_dst - io0_a_dst))))); +- if (v_hdist < v_length) { +- v_hlen = v_hdist; ++ if (v_depth <= 0u) { ++ v_vminor_alt |= 4096u; ++ } else { ++ v_stack_byte = ((v_depth - 1u) / 16u); ++ v_stack_bit = (((v_depth - 1u) & 15u) * 2u); ++ if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { ++ v_vminor_alt |= 8192u; + } else { +- v_hlen = v_length; +- } +- v_hdist += ((uint32_t)(((uint64_t)(self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0u))))); +- if (self->private_impl.f_history_index < v_hdist) { +- status = wuffs_base__make_status(wuffs_deflate__error__bad_distance); +- goto exit; +- } +- v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_slice( +- &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767u), 33025)); +- if (v_n_copied < v_hlen) { +- v_length -= v_n_copied; +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); +- continue; +- } +- v_length -= v_hlen; +- if (v_length == 0u) { +- goto label__loop__continue; ++ v_vminor_alt |= 16384u; + } + } +- v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_history( +- &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); +- if (v_length <= v_n_copied) { +- goto label__loop__continue; +- } +- v_length -= v_n_copied; +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); + } ++ break; + } +- self->private_impl.f_bits = v_bits; +- self->private_impl.f_n_bits = v_n_bits; +- if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { +- status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); +- goto exit; +- } ++ self->private_impl.f_end_of_data = true; + + ok: +- self->private_impl.p_decode_huffman_slow[0] = 0; ++ self->private_impl.p_decode_tokens = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_huffman_slow[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_huffman_slow[0].v_bits = v_bits; +- self->private_data.s_decode_huffman_slow[0].v_n_bits = v_n_bits; +- self->private_data.s_decode_huffman_slow[0].v_table_entry_n_bits = v_table_entry_n_bits; +- self->private_data.s_decode_huffman_slow[0].v_lmask = v_lmask; +- self->private_data.s_decode_huffman_slow[0].v_dmask = v_dmask; +- self->private_data.s_decode_huffman_slow[0].v_redir_top = v_redir_top; +- self->private_data.s_decode_huffman_slow[0].v_redir_mask = v_redir_mask; +- self->private_data.s_decode_huffman_slow[0].v_length = v_length; +- self->private_data.s_decode_huffman_slow[0].v_dist_minus_1 = v_dist_minus_1; ++ self->private_impl.p_decode_tokens = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ self->private_data.s_decode_tokens.v_string_length = v_string_length; ++ self->private_data.s_decode_tokens.v_depth = v_depth; ++ self->private_data.s_decode_tokens.v_tagged = v_tagged; ++ self->private_data.s_decode_tokens.v_indefinite_string_major_type = v_indefinite_string_major_type; + + goto exit; + exit: +@@ -36408,243 +36446,607 @@ wuffs_deflate__decoder__decode_huffman_slow( + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } + return status; + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32) + + // ---------------- Status Codes Implementations + +-const char wuffs_gif__error__bad_lzw_code[] = "#gif: bad LZW code"; +-const char wuffs_gif__error__bad_extension_label[] = "#gif: bad extension label"; +-const char wuffs_gif__error__bad_frame_size[] = "#gif: bad frame size"; +-const char wuffs_gif__error__bad_graphic_control[] = "#gif: bad graphic control"; +-const char wuffs_gif__error__bad_header[] = "#gif: bad header"; +-const char wuffs_gif__error__bad_literal_width[] = "#gif: bad literal width"; +-const char wuffs_gif__error__bad_palette[] = "#gif: bad palette"; +-const char wuffs_gif__error__truncated_input[] = "#gif: truncated input"; +-const char wuffs_gif__error__internal_error_inconsistent_i_o[] = "#gif: internal error: inconsistent I/O"; +- + // ---------------- Private Consts + + static const uint32_t +-WUFFS_GIF__INTERLACE_START[5] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 4294967295, 1, 2, 4, 0, +-}; +- +-static const uint8_t +-WUFFS_GIF__INTERLACE_DELTA[5] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 1, 2, 4, 8, 8, +-}; +- +-static const uint8_t +-WUFFS_GIF__INTERLACE_COUNT[5] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 1, 2, 4, 8, +-}; +- +-static const uint8_t +-WUFFS_GIF__ANIMEXTS1DOT0[11] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 65, 78, 73, 77, 69, 88, 84, 83, +- 49, 46, 48, +-}; +- +-static const uint8_t +-WUFFS_GIF__NETSCAPE2DOT0[11] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 78, 69, 84, 83, 67, 65, 80, 69, +- 50, 46, 48, +-}; +- +-static const uint8_t +-WUFFS_GIF__ICCRGBG1012[11] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 73, 67, 67, 82, 71, 66, 71, 49, +- 48, 49, 50, +-}; +- +-static const uint8_t +-WUFFS_GIF__XMPDATAXMP[11] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 88, 77, 80, 32, 68, 97, 116, 97, +- 88, 77, 80, ++WUFFS_CRC32__IEEE_TABLE[16][256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ { ++ 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u, ++ 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u, ++ 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u, ++ 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u, ++ 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u, ++ 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u, ++ 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u, ++ 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u, ++ 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u, ++ 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u, ++ 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u, ++ 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u, ++ 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u, ++ 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u, ++ 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u, ++ 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u, ++ 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u, ++ 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u, ++ 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u, ++ 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u, ++ 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u, ++ 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u, ++ 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u, ++ 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u, ++ 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u, ++ 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u, ++ 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u, ++ 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u, ++ 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u, ++ 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u, ++ 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u, ++ 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u, ++ }, { ++ 0u, 421212481u, 842424962u, 724390851u, 1684849924u, 2105013317u, 1448781702u, 1329698503u, ++ 3369699848u, 3519200073u, 4210026634u, 3824474571u, 2897563404u, 3048111693u, 2659397006u, 2274893007u, ++ 1254232657u, 1406739216u, 2029285587u, 1643069842u, 783210325u, 934667796u, 479770071u, 92505238u, ++ 2182846553u, 2600511768u, 2955803355u, 2838940570u, 3866582365u, 4285295644u, 3561045983u, 3445231262u, ++ 2508465314u, 2359236067u, 2813478432u, 3198777185u, 4058571174u, 3908292839u, 3286139684u, 3670389349u, ++ 1566420650u, 1145479147u, 1869335592u, 1987116393u, 959540142u, 539646703u, 185010476u, 303839341u, ++ 3745920755u, 3327985586u, 3983561841u, 4100678960u, 3140154359u, 2721170102u, 2300350837u, 2416418868u, ++ 396344571u, 243568058u, 631889529u, 1018359608u, 1945336319u, 1793607870u, 1103436669u, 1490954812u, ++ 4034481925u, 3915546180u, 3259968903u, 3679722694u, 2484439553u, 2366552896u, 2787371139u, 3208174018u, ++ 950060301u, 565965900u, 177645455u, 328046286u, 1556873225u, 1171730760u, 1861902987u, 2011255754u, ++ 3132841300u, 2745199637u, 2290958294u, 2442530455u, 3738671184u, 3352078609u, 3974232786u, 4126854035u, ++ 1919080284u, 1803150877u, 1079293406u, 1498383519u, 370020952u, 253043481u, 607678682u, 1025720731u, ++ 1711106983u, 2095471334u, 1472923941u, 1322268772u, 26324643u, 411738082u, 866634785u, 717028704u, ++ 2904875439u, 3024081134u, 2668790573u, 2248782444u, 3376948395u, 3495106026u, 4219356713u, 3798300520u, ++ 792689142u, 908347575u, 487136116u, 68299317u, 1263779058u, 1380486579u, 2036719216u, 1618931505u, ++ 3890672638u, 4278043327u, 3587215740u, 3435896893u, 2206873338u, 2593195963u, 2981909624u, 2829542713u, ++ 998479947u, 580430090u, 162921161u, 279890824u, 1609522511u, 1190423566u, 1842954189u, 1958874764u, ++ 4082766403u, 3930137346u, 3245109441u, 3631694208u, 2536953671u, 2385372678u, 2768287173u, 3155920004u, ++ 1900120602u, 1750776667u, 1131931800u, 1517083097u, 355290910u, 204897887u, 656092572u, 1040194781u, ++ 3113746450u, 2692952403u, 2343461520u, 2461357009u, 3723805974u, 3304059991u, 4022511508u, 4141455061u, ++ 2919742697u, 3072101800u, 2620513899u, 2234183466u, 3396041197u, 3547351212u, 4166851439u, 3779471918u, ++ 1725839073u, 2143618976u, 1424512099u, 1307796770u, 45282277u, 464110244u, 813994343u, 698327078u, ++ 3838160568u, 4259225593u, 3606301754u, 3488152955u, 2158586812u, 2578602749u, 2996767038u, 2877569151u, ++ 740041904u, 889656817u, 506086962u, 120682355u, 1215357364u, 1366020341u, 2051441462u, 1667084919u, ++ 3422213966u, 3538019855u, 4190942668u, 3772220557u, 2945847882u, 3062702859u, 2644537544u, 2226864521u, ++ 52649286u, 439905287u, 823476164u, 672009861u, 1733269570u, 2119477507u, 1434057408u, 1281543041u, ++ 2167981343u, 2552493150u, 3004082077u, 2853541596u, 3847487515u, 4233048410u, 3613549209u, 3464057816u, ++ 1239502615u, 1358593622u, 2077699477u, 1657543892u, 764250643u, 882293586u, 532408465u, 111204816u, ++ 1585378284u, 1197851309u, 1816695150u, 1968414767u, 974272232u, 587794345u, 136598634u, 289367339u, ++ 2527558116u, 2411481253u, 2760973158u, 3179948583u, 4073438432u, 3956313505u, 3237863010u, 3655790371u, ++ 347922877u, 229101820u, 646611775u, 1066513022u, 1892689081u, 1774917112u, 1122387515u, 1543337850u, ++ 3697634229u, 3313392372u, 3998419255u, 4148705398u, 3087642289u, 2702352368u, 2319436851u, 2468674930u, ++ }, { ++ 0u, 29518391u, 59036782u, 38190681u, 118073564u, 114017003u, 76381362u, 89069189u, ++ 236147128u, 265370511u, 228034006u, 206958561u, 152762724u, 148411219u, 178138378u, 190596925u, ++ 472294256u, 501532999u, 530741022u, 509615401u, 456068012u, 451764635u, 413917122u, 426358261u, ++ 305525448u, 334993663u, 296822438u, 275991697u, 356276756u, 352202787u, 381193850u, 393929805u, ++ 944588512u, 965684439u, 1003065998u, 973863097u, 1061482044u, 1049003019u, 1019230802u, 1023561829u, ++ 912136024u, 933002607u, 903529270u, 874031361u, 827834244u, 815125939u, 852716522u, 856752605u, ++ 611050896u, 631869351u, 669987326u, 640506825u, 593644876u, 580921211u, 551983394u, 556069653u, ++ 712553512u, 733666847u, 704405574u, 675154545u, 762387700u, 749958851u, 787859610u, 792175277u, ++ 1889177024u, 1901651959u, 1931368878u, 1927033753u, 2006131996u, 1985040171u, 1947726194u, 1976933189u, ++ 2122964088u, 2135668303u, 2098006038u, 2093965857u, 2038461604u, 2017599123u, 2047123658u, 2076625661u, ++ 1824272048u, 1836991623u, 1866005214u, 1861914857u, 1807058540u, 1786244187u, 1748062722u, 1777547317u, ++ 1655668488u, 1668093247u, 1630251878u, 1625932113u, 1705433044u, 1684323811u, 1713505210u, 1742760333u, ++ 1222101792u, 1226154263u, 1263738702u, 1251046777u, 1339974652u, 1310460363u, 1281013650u, 1301863845u, ++ 1187289752u, 1191637167u, 1161842422u, 1149379777u, 1103966788u, 1074747507u, 1112139306u, 1133218845u, ++ 1425107024u, 1429406311u, 1467333694u, 1454888457u, 1408811148u, 1379576507u, 1350309090u, 1371438805u, ++ 1524775400u, 1528845279u, 1499917702u, 1487177649u, 1575719220u, 1546255107u, 1584350554u, 1605185389u, ++ 3778354048u, 3774312887u, 3803303918u, 3816007129u, 3862737756u, 3892238699u, 3854067506u, 3833203973u, ++ 4012263992u, 4007927823u, 3970080342u, 3982554209u, 3895452388u, 3924658387u, 3953866378u, 3932773565u, ++ 4245928176u, 4241609415u, 4271336606u, 4283762345u, 4196012076u, 4225268251u, 4187931714u, 4166823541u, ++ 4076923208u, 4072833919u, 4035198246u, 4047918865u, 4094247316u, 4123732899u, 4153251322u, 4132437965u, ++ 3648544096u, 3636082519u, 3673983246u, 3678331705u, 3732010428u, 3753090955u, 3723829714u, 3694611429u, ++ 3614117080u, 3601426159u, 3572488374u, 3576541825u, 3496125444u, 3516976691u, 3555094634u, 3525581405u, ++ 3311336976u, 3298595879u, 3336186494u, 3340255305u, 3260503756u, 3281337595u, 3251864226u, 3222399125u, ++ 3410866088u, 3398419871u, 3368647622u, 3372945905u, 3427010420u, 3448139075u, 3485520666u, 3456284973u, ++ 2444203584u, 2423127159u, 2452308526u, 2481530905u, 2527477404u, 2539934891u, 2502093554u, 2497740997u, ++ 2679949304u, 2659102159u, 2620920726u, 2650438049u, 2562027300u, 2574714131u, 2603727690u, 2599670141u, ++ 2374579504u, 2353749767u, 2383274334u, 2412743529u, 2323684844u, 2336421851u, 2298759554u, 2294686645u, ++ 2207933576u, 2186809023u, 2149495014u, 2178734801u, 2224278612u, 2236720739u, 2266437690u, 2262135309u, ++ 2850214048u, 2820717207u, 2858812622u, 2879680249u, 2934667388u, 2938704459u, 2909776914u, 2897069605u, ++ 2817622296u, 2788420399u, 2759153014u, 2780249921u, 2700618180u, 2704950259u, 2742877610u, 2730399645u, ++ 3049550800u, 3020298727u, 3057690558u, 3078802825u, 2999835404u, 3004150075u, 2974355298u, 2961925461u, ++ 3151438440u, 3121956959u, 3092510214u, 3113327665u, 3168701108u, 3172786307u, 3210370778u, 3197646061u, ++ }, { ++ 0u, 3099354981u, 2852767883u, 313896942u, 2405603159u, 937357362u, 627793884u, 2648127673u, ++ 3316918511u, 2097696650u, 1874714724u, 3607201537u, 1255587768u, 4067088605u, 3772741427u, 1482887254u, ++ 1343838111u, 3903140090u, 4195393300u, 1118632049u, 3749429448u, 1741137837u, 1970407491u, 3452858150u, ++ 2511175536u, 756094997u, 1067759611u, 2266550430u, 449832999u, 2725482306u, 2965774508u, 142231497u, ++ 2687676222u, 412010587u, 171665333u, 2995192016u, 793786473u, 2548850444u, 2237264098u, 1038456711u, ++ 1703315409u, 3711623348u, 3482275674u, 1999841343u, 3940814982u, 1381529571u, 1089329165u, 4166106984u, ++ 4029413537u, 1217896388u, 1512189994u, 3802027855u, 2135519222u, 3354724499u, 3577784189u, 1845280792u, ++ 899665998u, 2367928107u, 2677414085u, 657096608u, 3137160985u, 37822588u, 284462994u, 2823350519u, ++ 2601801789u, 598228824u, 824021174u, 2309093331u, 343330666u, 2898962447u, 3195996129u, 113467524u, ++ 1587572946u, 3860600759u, 4104763481u, 1276501820u, 3519211397u, 1769898208u, 2076913422u, 3279374443u, ++ 3406630818u, 1941006535u, 1627703081u, 3652755532u, 1148164341u, 4241751952u, 3999682686u, 1457141531u, ++ 247015245u, 3053797416u, 2763059142u, 470583459u, 2178658330u, 963106687u, 735213713u, 2473467892u, ++ 992409347u, 2207944806u, 2435792776u, 697522413u, 3024379988u, 217581361u, 508405983u, 2800865210u, ++ 4271038444u, 1177467017u, 1419450215u, 3962007554u, 1911572667u, 3377213406u, 3690561584u, 1665525589u, ++ 1799331996u, 3548628985u, 3241568279u, 2039091058u, 3831314379u, 1558270126u, 1314193216u, 4142438437u, ++ 2928380019u, 372764438u, 75645176u, 3158189981u, 568925988u, 2572515393u, 2346768303u, 861712586u, ++ 3982079547u, 1441124702u, 1196457648u, 4293663189u, 1648042348u, 3666298377u, 3358779879u, 1888390786u, ++ 686661332u, 2421291441u, 2196002399u, 978858298u, 2811169155u, 523464422u, 226935048u, 3040519789u, ++ 3175145892u, 100435649u, 390670639u, 2952089162u, 841119475u, 2325614998u, 2553003640u, 546822429u, ++ 2029308235u, 3225988654u, 3539796416u, 1782671013u, 4153826844u, 1328167289u, 1570739863u, 3844338162u, ++ 1298864389u, 4124540512u, 3882013070u, 1608431339u, 3255406162u, 2058742071u, 1744848601u, 3501990332u, ++ 2296328682u, 811816591u, 584513889u, 2590678532u, 129869501u, 3204563416u, 2914283062u, 352848211u, ++ 494030490u, 2781751807u, 3078325777u, 264757620u, 2450577869u, 715964072u, 941166918u, 2158327331u, ++ 3636881013u, 1618608400u, 1926213374u, 3396585883u, 1470427426u, 4011365959u, 4255988137u, 1158766284u, ++ 1984818694u, 3471935843u, 3695453837u, 1693991400u, 4180638033u, 1100160564u, 1395044826u, 3952793279u, ++ 3019491049u, 189112716u, 435162722u, 2706139399u, 1016811966u, 2217162459u, 2526189877u, 774831696u, ++ 643086745u, 2666061564u, 2354934034u, 887166583u, 2838900430u, 294275499u, 54519365u, 3145957664u, ++ 3823145334u, 1532818963u, 1240029693u, 4048895640u, 1820460577u, 3560857924u, 3331051178u, 2117577167u, ++ 3598663992u, 1858283101u, 2088143283u, 3301633750u, 1495127663u, 3785470218u, 4078182116u, 1269332353u, ++ 332098007u, 2876706482u, 3116540252u, 25085497u, 2628386432u, 605395429u, 916469259u, 2384220526u, ++ 2254837415u, 1054503362u, 745528876u, 2496903497u, 151290352u, 2981684885u, 2735556987u, 464596510u, ++ 1137851976u, 4218313005u, 3923506883u, 1365741990u, 3434129695u, 1946996346u, 1723425172u, 3724871409u, ++ }, { ++ 0u, 1029712304u, 2059424608u, 1201699536u, 4118849216u, 3370159984u, 2403399072u, 2988497936u, ++ 812665793u, 219177585u, 1253054625u, 2010132753u, 3320900865u, 4170237105u, 3207642721u, 2186319825u, ++ 1625331586u, 1568718386u, 438355170u, 658566482u, 2506109250u, 2818578674u, 4020265506u, 3535817618u, ++ 1351670851u, 1844508147u, 709922595u, 389064339u, 2769320579u, 2557498163u, 3754961379u, 3803185235u, ++ 3250663172u, 4238411444u, 3137436772u, 2254525908u, 876710340u, 153198708u, 1317132964u, 1944187668u, ++ 4054934725u, 3436268917u, 2339452837u, 3054575125u, 70369797u, 961670069u, 2129760613u, 1133623509u, ++ 2703341702u, 2621542710u, 3689016294u, 3867263574u, 1419845190u, 1774270454u, 778128678u, 318858390u, ++ 2438067015u, 2888948471u, 3952189479u, 3606153623u, 1691440519u, 1504803895u, 504432359u, 594620247u, ++ 1492342857u, 1704161785u, 573770537u, 525542041u, 2910060169u, 2417219385u, 3618876905u, 3939730521u, ++ 1753420680u, 1440954936u, 306397416u, 790849880u, 2634265928u, 2690882808u, 3888375336u, 3668168600u, ++ 940822475u, 91481723u, 1121164459u, 2142483739u, 3448989963u, 4042473659u, 3075684971u, 2318603227u, ++ 140739594u, 889433530u, 1923340138u, 1338244826u, 4259521226u, 3229813626u, 2267247018u, 3124975642u, ++ 2570221389u, 2756861693u, 3824297005u, 3734113693u, 1823658381u, 1372780605u, 376603373u, 722643805u, ++ 2839690380u, 2485261628u, 3548540908u, 4007806556u, 1556257356u, 1638052860u, 637716780u, 459464860u, ++ 4191346895u, 3300051327u, 2199040943u, 3195181599u, 206718479u, 825388991u, 1989285231u, 1274166495u, ++ 3382881038u, 4106388158u, 3009607790u, 2382549470u, 1008864718u, 21111934u, 1189240494u, 2072147742u, ++ 2984685714u, 2357631266u, 3408323570u, 4131834434u, 1147541074u, 2030452706u, 1051084082u, 63335554u, ++ 2174155603u, 3170292451u, 4216760371u, 3325460867u, 1947622803u, 1232499747u, 248909555u, 867575619u, ++ 3506841360u, 3966111392u, 2881909872u, 2527485376u, 612794832u, 434546784u, 1581699760u, 1663499008u, ++ 3782634705u, 3692447073u, 2612412337u, 2799048193u, 351717905u, 697754529u, 1849071985u, 1398190273u, ++ 1881644950u, 1296545318u, 182963446u, 931652934u, 2242328918u, 3100053734u, 4284967478u, 3255255942u, ++ 1079497815u, 2100821479u, 983009079u, 133672583u, 3050795671u, 2293717799u, 3474399735u, 4067887175u, ++ 281479188u, 765927844u, 1778867060u, 1466397380u, 3846680276u, 3626469220u, 2676489652u, 2733102084u, ++ 548881365u, 500656741u, 1517752501u, 1729575173u, 3577210133u, 3898068133u, 2952246901u, 2459410373u, ++ 3910527195u, 3564487019u, 2480257979u, 2931134987u, 479546907u, 569730987u, 1716854139u, 1530213579u, ++ 3647316762u, 3825568426u, 2745561210u, 2663766474u, 753206746u, 293940330u, 1445287610u, 1799716618u, ++ 2314567513u, 3029685993u, 4080348217u, 3461678473u, 2088098201u, 1091956777u, 112560889u, 1003856713u, ++ 3112514712u, 2229607720u, 3276105720u, 4263857736u, 1275433560u, 1902492648u, 918929720u, 195422344u, ++ 685033439u, 364179055u, 1377080511u, 1869921551u, 3713294623u, 3761522863u, 2811507327u, 2599689167u, ++ 413436958u, 633644462u, 1650777982u, 1594160846u, 3978570462u, 3494118254u, 2548332990u, 2860797966u, ++ 1211387997u, 1968470509u, 854852413u, 261368461u, 3182753437u, 2161434413u, 3346310653u, 4195650637u, ++ 2017729436u, 1160000044u, 42223868u, 1071931724u, 2378480988u, 2963576044u, 4144295484u, 3395602316u, ++ }, { ++ 0u, 3411858341u, 1304994059u, 2257875630u, 2609988118u, 1355649459u, 3596215069u, 486879416u, ++ 3964895853u, 655315400u, 2711298918u, 1791488195u, 2009251963u, 3164476382u, 973758832u, 4048990933u, ++ 64357019u, 3364540734u, 1310630800u, 2235723829u, 2554806413u, 1394316072u, 3582976390u, 517157411u, ++ 4018503926u, 618222419u, 2722963965u, 1762783832u, 1947517664u, 3209171269u, 970744811u, 4068520014u, ++ 128714038u, 3438335635u, 1248109629u, 2167961496u, 2621261600u, 1466012805u, 3522553387u, 447296910u, ++ 3959392091u, 547575038u, 2788632144u, 1835791861u, 1886307661u, 3140622056u, 1034314822u, 4143626211u, ++ 75106221u, 3475428360u, 1236444838u, 2196665603u, 2682996155u, 1421317662u, 3525567664u, 427767573u, ++ 3895035328u, 594892389u, 2782995659u, 1857943406u, 1941489622u, 3101955187u, 1047553757u, 4113347960u, ++ 257428076u, 3288652233u, 1116777319u, 2311878850u, 2496219258u, 1603640287u, 3640781169u, 308099796u, ++ 3809183745u, 676813732u, 2932025610u, 1704983215u, 2023410199u, 3016104370u, 894593820u, 4262377657u, ++ 210634999u, 3352484690u, 1095150076u, 2316991065u, 2535410401u, 1547934020u, 3671583722u, 294336591u, ++ 3772615322u, 729897279u, 2903845777u, 1716123700u, 2068629644u, 2953845545u, 914647431u, 4258839074u, ++ 150212442u, 3282623743u, 1161604689u, 2388688372u, 2472889676u, 1480171241u, 3735940167u, 368132066u, ++ 3836185911u, 805002898u, 2842635324u, 1647574937u, 2134298401u, 3026852996u, 855535146u, 4188192143u, ++ 186781121u, 3229539940u, 1189784778u, 2377547631u, 2427670487u, 1542429810u, 3715886812u, 371670393u, ++ 3882979244u, 741170185u, 2864262823u, 1642462466u, 2095107514u, 3082559007u, 824732849u, 4201955092u, ++ 514856152u, 3589064573u, 1400419795u, 2552522358u, 2233554638u, 1316849003u, 3370776517u, 62202976u, ++ 4075001525u, 968836368u, 3207280574u, 1954014235u, 1769133219u, 2720925446u, 616199592u, 4024870413u, ++ 493229635u, 3594175974u, 1353627464u, 2616354029u, 2264355925u, 1303087088u, 3409966430u, 6498043u, ++ 4046820398u, 979978123u, 3170710821u, 2007099008u, 1789187640u, 2717386141u, 661419827u, 3962610838u, ++ 421269998u, 3527459403u, 1423225061u, 2676515648u, 2190300152u, 1238466653u, 3477467891u, 68755798u, ++ 4115633027u, 1041448998u, 3095868040u, 1943789869u, 1860096405u, 2776760880u, 588673182u, 3897205563u, ++ 449450869u, 3516317904u, 1459794558u, 2623431131u, 2170245475u, 1242006214u, 3432247400u, 131015629u, ++ 4137259288u, 1036337853u, 3142660115u, 1879958454u, 1829294862u, 2790523051u, 549483013u, 3952910752u, ++ 300424884u, 3669282065u, 1545650111u, 2541513754u, 2323209378u, 1092980487u, 3350330793u, 216870412u, ++ 4256931033u, 921128828u, 2960342482u, 2066738807u, 1714085583u, 2910195050u, 736264132u, 3770592353u, ++ 306060335u, 3647131530u, 1610005796u, 2494197377u, 2309971513u, 1123257756u, 3295149874u, 255536279u, ++ 4268596802u, 892423655u, 3013951305u, 2029645036u, 1711070292u, 2929725425u, 674528607u, 3815288570u, ++ 373562242u, 3709388839u, 1535949449u, 2429577516u, 2379569556u, 1183418929u, 3223189663u, 188820282u, ++ 4195850735u, 827017802u, 3084859620u, 2089020225u, 1636228089u, 2866415708u, 743340786u, 3876759895u, ++ 361896217u, 3738094268u, 1482340370u, 2466671543u, 2382584591u, 1163888810u, 3284924932u, 144124321u, ++ 4190215028u, 849168593u, 3020503679u, 2136336858u, 1649465698u, 2836138695u, 798521449u, 3838094284u, ++ }, { ++ 0u, 2792819636u, 2543784233u, 837294749u, 4098827283u, 1379413927u, 1674589498u, 3316072078u, ++ 871321191u, 2509784531u, 2758827854u, 34034938u, 3349178996u, 1641505216u, 1346337629u, 4131942633u, ++ 1742642382u, 3249117050u, 4030828007u, 1446413907u, 2475800797u, 904311657u, 68069876u, 2725880384u, ++ 1412551337u, 4064729373u, 3283010432u, 1708771380u, 2692675258u, 101317902u, 937551763u, 2442587175u, ++ 3485284764u, 1774858792u, 1478633653u, 4266992385u, 1005723023u, 2642744891u, 2892827814u, 169477906u, ++ 4233263099u, 1512406095u, 1808623314u, 3451546982u, 136139752u, 2926205020u, 2676114113u, 972376437u, ++ 2825102674u, 236236518u, 1073525883u, 2576072655u, 1546420545u, 4200303349u, 3417542760u, 1841601500u, ++ 2609703733u, 1039917185u, 202635804u, 2858742184u, 1875103526u, 3384067218u, 4166835727u, 1579931067u, ++ 1141601657u, 3799809741u, 3549717584u, 1977839588u, 2957267306u, 372464350u, 668680259u, 2175552503u, ++ 2011446046u, 3516084394u, 3766168119u, 1175200131u, 2209029901u, 635180217u, 338955812u, 2990736784u, ++ 601221559u, 2242044419u, 3024812190u, 306049834u, 3617246628u, 1911408144u, 1074125965u, 3866285881u, ++ 272279504u, 3058543716u, 2275784441u, 567459149u, 3832906691u, 1107462263u, 1944752874u, 3583875422u, ++ 2343980261u, 767641425u, 472473036u, 3126744696u, 2147051766u, 3649987394u, 3899029983u, 1309766251u, ++ 3092841090u, 506333494u, 801510315u, 2310084639u, 1276520081u, 3932237093u, 3683203000u, 2113813516u, ++ 3966292011u, 1243601823u, 2079834370u, 3716205238u, 405271608u, 3192979340u, 2411259153u, 701492901u, ++ 3750207052u, 2045810168u, 1209569125u, 4000285905u, 734575199u, 2378150379u, 3159862134u, 438345922u, ++ 2283203314u, 778166598u, 529136603u, 3120492655u, 2086260449u, 3660498261u, 3955679176u, 1303499900u, ++ 3153699989u, 495890209u, 744928700u, 2316418568u, 1337360518u, 3921775410u, 3626602927u, 2120129051u, ++ 4022892092u, 1237286280u, 2018993941u, 3726666913u, 461853231u, 3186645403u, 2350400262u, 711936178u, ++ 3693557851u, 2052076527u, 1270360434u, 3989775046u, 677911624u, 2384402428u, 3220639073u, 427820757u, ++ 1202443118u, 3789347034u, 3493118535u, 1984154099u, 3018127229u, 362020041u, 612099668u, 2181885408u, ++ 1950653705u, 3526596285u, 3822816288u, 1168934804u, 2148251930u, 645706414u, 395618355u, 2984485767u, ++ 544559008u, 2248295444u, 3085590153u, 295523645u, 3560598451u, 1917673479u, 1134918298u, 3855773998u, ++ 328860103u, 3052210803u, 2214924526u, 577903450u, 3889505748u, 1101147744u, 1883911421u, 3594338121u, ++ 3424493451u, 1785369663u, 1535282850u, 4260726038u, 944946072u, 2653270060u, 2949491377u, 163225861u, ++ 4294103532u, 1501944408u, 1752023237u, 3457862513u, 196998655u, 2915761739u, 2619532502u, 978710370u, ++ 2881684293u, 229902577u, 1012666988u, 2586515928u, 1603020630u, 4193987810u, 3356702335u, 1852063179u, ++ 2553040162u, 1046169238u, 263412747u, 2848217023u, 1818454321u, 3390333573u, 4227627032u, 1569420204u, ++ 60859927u, 2782375331u, 2487203646u, 843627658u, 4159668740u, 1368951216u, 1617990445u, 3322386585u, ++ 810543216u, 2520310724u, 2815490393u, 27783917u, 3288386659u, 1652017111u, 1402985802u, 4125677310u, ++ 1685994201u, 3255382381u, 4091620336u, 1435902020u, 2419138250u, 910562686u, 128847843u, 2715354199u, ++ 1469150398u, 4058414858u, 3222168983u, 1719234083u, 2749255853u, 94984985u, 876691844u, 2453031472u, ++ }, { ++ 0u, 3433693342u, 1109723005u, 2391738339u, 2219446010u, 1222643300u, 3329165703u, 180685081u, ++ 3555007413u, 525277995u, 2445286600u, 1567235158u, 1471092047u, 2600801745u, 361370162u, 3642757804u, ++ 2092642603u, 2953916853u, 1050555990u, 4063508168u, 4176560081u, 878395215u, 3134470316u, 1987983410u, ++ 2942184094u, 1676945920u, 3984272867u, 567356797u, 722740324u, 3887998202u, 1764827929u, 2778407815u, ++ 4185285206u, 903635656u, 3142804779u, 2012833205u, 2101111980u, 2979425330u, 1058630609u, 4088621903u, ++ 714308067u, 3862526333u, 1756790430u, 2753330688u, 2933487385u, 1651734407u, 3975966820u, 542535930u, ++ 2244825981u, 1231508451u, 3353891840u, 188896414u, 25648519u, 3442302233u, 1134713594u, 2399689316u, ++ 1445480648u, 2592229462u, 336416693u, 3634843435u, 3529655858u, 516441772u, 2420588879u, 1559052753u, ++ 698204909u, 3845636723u, 1807271312u, 2803025166u, 2916600855u, 1635634313u, 4025666410u, 593021940u, ++ 4202223960u, 919787974u, 3093159461u, 1962401467u, 2117261218u, 2996361020u, 1008193759u, 4038971457u, ++ 1428616134u, 2576151384u, 386135227u, 3685348389u, 3513580860u, 499580322u, 2471098945u, 1608776415u, ++ 2260985971u, 1248454893u, 3303468814u, 139259792u, 42591881u, 3458459159u, 1085071860u, 2349261162u, ++ 3505103035u, 474062885u, 2463016902u, 1583654744u, 1419882049u, 2550902495u, 377792828u, 3660491170u, ++ 51297038u, 3483679632u, 1093385331u, 2374089965u, 2269427188u, 1273935210u, 3311514249u, 164344343u, ++ 2890961296u, 1627033870u, 4000683757u, 585078387u, 672833386u, 3836780532u, 1782552599u, 2794821769u, ++ 2142603813u, 3005188795u, 1032883544u, 4047146438u, 4227826911u, 928351297u, 3118105506u, 1970307900u, ++ 1396409818u, 2677114180u, 287212199u, 3719594553u, 3614542624u, 467372990u, 2505346141u, 1509854403u, ++ 2162073199u, 1282711281u, 3271268626u, 240228748u, 76845205u, 3359543307u, 1186043880u, 2317064054u, ++ 796964081u, 3811226735u, 1839575948u, 2702160658u, 2882189835u, 1734392469u, 3924802934u, 625327592u, ++ 4234522436u, 818917338u, 3191908409u, 1927981223u, 2016387518u, 3028656416u, 973776579u, 4137723485u, ++ 2857232268u, 1726474002u, 3899187441u, 616751215u, 772270454u, 3803048424u, 1814228491u, 2693328533u, ++ 2041117753u, 3036871847u, 999160644u, 4146592730u, 4259508931u, 826864221u, 3217552830u, 1936586016u, ++ 3606501031u, 442291769u, 2496909786u, 1484378436u, 1388107869u, 2652297411u, 278519584u, 3694387134u, ++ 85183762u, 3384397196u, 1194773103u, 2342308593u, 2170143720u, 1307820918u, 3279733909u, 265733131u, ++ 2057717559u, 3054258089u, 948125770u, 4096344276u, 4276898253u, 843467091u, 3167309488u, 1885556270u, ++ 2839764098u, 1709792284u, 3949353983u, 667704161u, 755585656u, 3785577190u, 1865176325u, 2743489947u, ++ 102594076u, 3401021058u, 1144549729u, 2291298815u, 2186770662u, 1325234296u, 3228729243u, 215514885u, ++ 3589828009u, 424832311u, 2547870420u, 1534552650u, 1370645331u, 2635621325u, 328688686u, 3745342640u, ++ 2211456353u, 1333405183u, 3254067740u, 224338562u, 127544219u, 3408931589u, 1170156774u, 2299866232u, ++ 1345666772u, 2627681866u, 303053225u, 3736746295u, 3565105198u, 416624816u, 2522494803u, 1525692365u, ++ 4285207626u, 868291796u, 3176010551u, 1910772649u, 2065767088u, 3079346734u, 956571085u, 4121828691u, ++ 747507711u, 3760459617u, 1856702594u, 2717976604u, 2831417605u, 1684930971u, 3940615800u, 642451174u, ++ }, ++ { ++ 0u, 393942083u, 787884166u, 965557445u, 1575768332u, 1251427663u, 1931114890u, 1684106697u, ++ 3151536664u, 2896410203u, 2502855326u, 2186649309u, 3862229780u, 4048545623u, 3368213394u, 3753496529u, ++ 2898281073u, 3149616690u, 2184604407u, 2504883892u, 4046197629u, 3864463166u, 3755621371u, 3366006712u, ++ 387506281u, 6550570u, 971950319u, 781573292u, 1257550181u, 1569695014u, 1677892067u, 1937345952u, ++ 2196865699u, 2508887776u, 2886183461u, 3145514598u, 3743273903u, 3362179052u, 4058774313u, 3868258154u, ++ 958996667u, 777139448u, 400492605u, 10755198u, 1690661303u, 1941857780u, 1244879153u, 1565019506u, ++ 775012562u, 961205393u, 13101140u, 398261271u, 1943900638u, 1688634781u, 1563146584u, 1246801179u, ++ 2515100362u, 2190636681u, 3139390028u, 2892258831u, 3355784134u, 3749586821u, 3874691904u, 4052225795u, ++ 3734110983u, 3387496260u, 4033096577u, 3877584834u, 2206093835u, 2483373640u, 2911402637u, 3136515790u, ++ 1699389727u, 1915860316u, 1270647193u, 1556585946u, 950464531u, 803071056u, 374397077u, 19647702u, ++ 1917993334u, 1697207605u, 1554278896u, 1272937907u, 800985210u, 952435769u, 21510396u, 372452543u, ++ 3381322606u, 3740399405u, 3883715560u, 4027047851u, 2489758306u, 2199758369u, 3130039012u, 2917895847u, ++ 1550025124u, 1259902439u, 1922410786u, 1710144865u, 26202280u, 385139947u, 796522542u, 939715693u, ++ 3887801276u, 4039129087u, 3377269562u, 3728088953u, 3126293168u, 2905368307u, 2493602358u, 2212122229u, ++ 4037264341u, 3889747862u, 3730172755u, 3375300368u, 2907673305u, 3124004506u, 2209987167u, 2495786524u, ++ 1266377165u, 1543533966u, 1703758155u, 1928748296u, 379007169u, 32253058u, 945887303u, 790236164u, ++ 1716846671u, 1898845196u, 1218652361u, 1608006794u, 1002000707u, 750929152u, 357530053u, 36990342u, ++ 3717046871u, 3405166100u, 4084959953u, 3825245842u, 2153902939u, 2535122712u, 2929187805u, 3119304606u, ++ 3398779454u, 3723384445u, 3831720632u, 4078468859u, 2541294386u, 2147616625u, 3113171892u, 2935238647u, ++ 1900929062u, 1714877541u, 1606142112u, 1220599011u, 748794154u, 1004184937u, 39295404u, 355241455u, ++ 3835986668u, 4091516591u, 3394415210u, 3710500393u, 3108557792u, 2922629027u, 2545875814u, 2160455461u, ++ 1601970420u, 1208431799u, 1904871538u, 1727077425u, 43020792u, 367748539u, 744905086u, 991776061u, ++ 1214562461u, 1595921630u, 1720903707u, 1911159896u, 361271697u, 49513938u, 998160663u, 738569556u, ++ 4089209477u, 3838277318u, 3712633347u, 3392233024u, 2924491657u, 3106613194u, 2158369551u, 2547846988u, ++ 3100050248u, 2948339467u, 2519804878u, 2169126797u, 3844821572u, 4065347079u, 3420289730u, 3701894785u, ++ 52404560u, 342144275u, 770279894u, 982687125u, 1593045084u, 1233708063u, 1879431386u, 1736363161u, ++ 336019769u, 58479994u, 988899775u, 764050940u, 1240141877u, 1586496630u, 1729968307u, 1885744368u, ++ 2950685473u, 3097818978u, 2166999975u, 2522013668u, 4063474221u, 3846743662u, 3703937707u, 3418263272u, ++ 976650731u, 760059304u, 348170605u, 62635310u, 1742393575u, 1889649828u, 1227683937u, 1582820386u, ++ 2179867635u, 2526361520u, 2937588597u, 3093503798u, 3691148031u, 3413731004u, 4076100217u, 3851374138u, ++ 2532754330u, 2173556697u, 3087067932u, 2944139103u, 3407516310u, 3697379029u, 3857496592u, 4070026835u, ++ 758014338u, 978679233u, 64506116u, 346250567u, 1891774606u, 1740186829u, 1580472328u, 1229917259u, ++ }, { ++ 0u, 4022496062u, 83218493u, 3946298115u, 166436986u, 3861498692u, 220098631u, 3806075769u, ++ 332873972u, 4229245898u, 388141257u, 4175494135u, 440197262u, 4127099824u, 516501683u, 4044053389u, ++ 665747944u, 3362581206u, 593187285u, 3432594155u, 776282514u, 3246869164u, 716239279u, 3312622225u, ++ 880394524u, 3686509090u, 814485793u, 3746462239u, 1033003366u, 3528460888u, 963096923u, 3601193573u, ++ 1331495888u, 2694801646u, 1269355501u, 2758457555u, 1186374570u, 2843003028u, 1111716759u, 2910918825u, ++ 1552565028u, 3007850522u, 1484755737u, 3082680359u, 1432478558u, 3131279456u, 1368666979u, 3193329757u, ++ 1760789048u, 2268195078u, 1812353541u, 2210675003u, 1628971586u, 2396670332u, 1710092927u, 2318375233u, ++ 2066006732u, 2498144754u, 2144408305u, 2417195471u, 1926193846u, 2634877320u, 1983558283u, 2583222709u, ++ 2662991776u, 1903717534u, 2588923805u, 1972223139u, 2538711002u, 2022952164u, 2477029351u, 2087066841u, ++ 2372749140u, 1655647338u, 2308478825u, 1717238871u, 2223433518u, 1799654416u, 2155034387u, 1873894445u, ++ 3105130056u, 1456926070u, 3185661557u, 1378041163u, 2969511474u, 1597852940u, 3020617231u, 1539874097u, ++ 2864957116u, 1157737858u, 2922780289u, 1106542015u, 2737333958u, 1290407416u, 2816325371u, 1210047941u, ++ 3521578096u, 1042640718u, 3574781005u, 986759027u, 3624707082u, 936300340u, 3707335735u, 859512585u, ++ 3257943172u, 770846650u, 3334837433u, 688390023u, 3420185854u, 605654976u, 3475911875u, 552361981u, ++ 4132013464u, 428600998u, 4072428965u, 494812827u, 4288816610u, 274747100u, 4216845791u, 345349857u, ++ 3852387692u, 173846098u, 3781891409u, 245988975u, 3967116566u, 62328360u, 3900749099u, 121822741u, ++ 3859089665u, 164061759u, 3807435068u, 221426178u, 4025395579u, 2933317u, 3944446278u, 81334904u, ++ 4124199413u, 437265099u, 4045904328u, 518386422u, 4231653775u, 335250097u, 4174133682u, 386814604u, ++ 3249244393u, 778691543u, 3311294676u, 714879978u, 3359647891u, 662848429u, 3434477742u, 595039120u, ++ 3531393053u, 1035903779u, 3599308832u, 961245982u, 3684132967u, 877986649u, 3747788890u, 815846244u, ++ 2841119441u, 1184522735u, 2913852140u, 1114616274u, 2696129195u, 1332855189u, 2756082326u, 1266946472u, ++ 3129952805u, 1431118107u, 3195705880u, 1371074854u, 3009735263u, 1554415969u, 3079748194u, 1481855324u, ++ 2398522169u, 1630855175u, 2315475716u, 1707159610u, 2266835779u, 1759461501u, 2213084030u, 1814728768u, ++ 2636237773u, 1927520499u, 2580814832u, 1981182158u, 2496293815u, 2064121993u, 2420095882u, 2147340468u, ++ 2025787041u, 2541577631u, 2085281436u, 2475210146u, 1901375195u, 2660681189u, 1973518054u, 2590184920u, ++ 1801997909u, 2225743211u, 1872600680u, 2153772374u, 1652813359u, 2369881361u, 1719025170u, 2310296876u, ++ 1594986313u, 2966676599u, 1541693300u, 3022402634u, 1459236659u, 3107472397u, 1376780046u, 3184366640u, ++ 1288097725u, 2734990467u, 1211309952u, 2817619134u, 1160605639u, 2867791097u, 1104723962u, 2920993988u, ++ 937561457u, 3626001999u, 857201996u, 3704993394u, 1040821515u, 3519792693u, 989625654u, 3577615880u, ++ 607473029u, 3421972155u, 549494200u, 3473077894u, 769584639u, 3256649409u, 690699714u, 3337180924u, ++ 273452185u, 4287555495u, 347692196u, 4219156378u, 430386403u, 4133832669u, 491977950u, 4069562336u, ++ 60542061u, 3965298515u, 124656720u, 3903616878u, 175139863u, 3853649705u, 243645482u, 3779581716u, ++ }, { ++ 0u, 3247366080u, 1483520449u, 2581751297u, 2967040898u, 1901571138u, 3904227907u, 691737987u, ++ 3133399365u, 2068659845u, 3803142276u, 589399876u, 169513671u, 3415493895u, 1383475974u, 2482566342u, ++ 2935407819u, 1870142219u, 4137319690u, 924099274u, 506443593u, 3751897225u, 1178799752u, 2278412616u, ++ 339027342u, 3585866318u, 1280941135u, 2379694991u, 2766951948u, 1700956620u, 4236308429u, 1024339981u, ++ 2258407383u, 1192382487u, 3740284438u, 528411094u, 910556245u, 4157285269u, 1848198548u, 2946996820u, ++ 1012887186u, 4258378066u, 1681119059u, 2780629139u, 2357599504u, 1292419792u, 3572147409u, 358906641u, ++ 678054684u, 3924071644u, 1879503581u, 2978491677u, 2561882270u, 1497229150u, 3235873119u, 22109855u, ++ 2460592729u, 1395094937u, 3401913240u, 189516888u, 577821147u, 3825075739u, 2048679962u, 3146956762u, ++ 3595049455u, 398902831u, 2384764974u, 1336573934u, 1720805997u, 2803873197u, 1056822188u, 4285729900u, ++ 1821112490u, 2902796138u, 887570795u, 4117339819u, 3696397096u, 500978920u, 2218668777u, 1169222953u, ++ 2025774372u, 3106931428u, 550659301u, 3780950821u, 3362238118u, 166293862u, 2416645991u, 1367722151u, ++ 3262987361u, 66315169u, 2584839584u, 1537170016u, 1923370979u, 3005911075u, 717813282u, 3947244002u, ++ 1356109368u, 2438613496u, 146288633u, 3375820857u, 3759007162u, 562248314u, 3093388411u, 2045739963u, ++ 3927406461u, 731490493u, 2994458300u, 1945440636u, 1523451135u, 2604718911u, 44219710u, 3274466046u, ++ 4263662323u, 1068272947u, 2790189874u, 1740649714u, 1325080945u, 2406874801u, 379033776u, 3608758128u, ++ 1155642294u, 2238671990u, 479005303u, 3708016055u, 4097359924u, 901128180u, 2891217397u, 1843045941u, ++ 2011248031u, 3060787807u, 797805662u, 3993195422u, 3342353949u, 112630237u, 2673147868u, 1591353372u, ++ 3441611994u, 212601626u, 2504944923u, 1421914843u, 2113644376u, 3161815192u, 630660761u, 3826893145u, ++ 3642224980u, 412692116u, 2172340373u, 1089836885u, 1775141590u, 2822790422u, 832715543u, 4029474007u, ++ 1674842129u, 2723860433u, 1001957840u, 4197873168u, 3540870035u, 310623315u, 2338445906u, 1257178514u, ++ 4051548744u, 821257608u, 2836464521u, 1755307081u, 1101318602u, 2150241802u, 432566283u, 3628511179u, ++ 1270766349u, 2318435533u, 332587724u, 3529260300u, 4217841807u, 988411727u, 2735444302u, 1652903566u, ++ 1602977411u, 2651169091u, 132630338u, 3328776322u, 4015131905u, 786223809u, 3074340032u, 1991273216u, ++ 3846741958u, 616972294u, 3173262855u, 2091579847u, 1435626564u, 2485072772u, 234706309u, 3430124101u, ++ 2712218736u, 1613231024u, 4190475697u, 944458353u, 292577266u, 3506339890u, 1226630707u, 2291284467u, ++ 459984181u, 3672380149u, 1124496628u, 2189994804u, 2880683703u, 1782407543u, 4091479926u, 844224694u, ++ 257943739u, 3469817723u, 1462980986u, 2529005242u, 3213269817u, 2114471161u, 3890881272u, 644152632u, ++ 3046902270u, 1947391550u, 3991973951u, 746483711u, 88439420u, 3301680572u, 1563018173u, 2628197501u, ++ 657826727u, 3871046759u, 2136545894u, 3201811878u, 2548879397u, 1449267173u, 3481299428u, 235845156u, ++ 2650161890u, 1551408418u, 3315268387u, 68429027u, 758067552u, 3970035360u, 1967360161u, 3033356129u, ++ 2311284588u, 1213053100u, 3517963949u, 270598509u, 958010606u, 4170500910u, 1635167535u, 2700636911u, ++ 855672361u, 4069415401u, 1802256360u, 2866995240u, 2212099499u, 1113008747u, 3686091882u, 440112042u, ++ }, { ++ 0u, 2611301487u, 3963330207u, 2006897392u, 50740095u, 2560849680u, 4013794784u, 1956178319u, ++ 101480190u, 2645113489u, 3929532513u, 1905435662u, 84561281u, 2662269422u, 3912356638u, 1922342769u, ++ 202960380u, 2545787283u, 3760419683u, 2072395532u, 253679235u, 2495322860u, 3810871324u, 2021655667u, ++ 169122562u, 2444351341u, 3861841309u, 2106214898u, 152215677u, 2461527058u, 3844685538u, 2123133581u, ++ 405920760u, 2207553431u, 4094313831u, 1873742088u, 456646791u, 2157096168u, 4144791064u, 1823027831u, ++ 507358470u, 2241388905u, 4060492697u, 1772322806u, 490444409u, 2258557462u, 4043311334u, 1789215881u, ++ 338245124u, 2408348267u, 4161972379u, 1672996084u, 388959611u, 2357870868u, 4212429796u, 1622269835u, ++ 304431354u, 2306870421u, 4263435877u, 1706791434u, 287538053u, 2324051946u, 4246267162u, 1723705717u, ++ 811841520u, 2881944479u, 3696765295u, 1207788800u, 862293135u, 2831204576u, 3747484176u, 1157324415u, ++ 913293582u, 2915732833u, 3662962577u, 1106318334u, 896137841u, 2932651550u, 3646055662u, 1123494017u, ++ 1014716940u, 2816349795u, 3493905555u, 1273334012u, 1065181555u, 2765630748u, 3544645612u, 1222882179u, ++ 980888818u, 2714919069u, 3595350637u, 1307180546u, 963712909u, 2731826146u, 3578431762u, 1324336509u, ++ 676490248u, 3019317351u, 3295277719u, 1607253752u, 726947703u, 2968591128u, 3345992168u, 1556776327u, ++ 777919222u, 3053147801u, 3261432937u, 1505806342u, 760750473u, 3070062054u, 3244539670u, 1522987897u, ++ 608862708u, 3220163995u, 3362856811u, 1406423812u, 659339915u, 3169449700u, 3413582868u, 1355966587u, ++ 575076106u, 3118709605u, 3464325525u, 1440228858u, 557894773u, 3135602714u, 3447411434u, 1457397381u, ++ 1623683040u, 4217512847u, 2365387135u, 391757072u, 1673614495u, 4167309552u, 2415577600u, 341804655u, ++ 1724586270u, 4251866481u, 2331019137u, 290835438u, 1707942497u, 4268256782u, 2314648830u, 307490961u, ++ 1826587164u, 4152020595u, 2162433155u, 457265388u, 1876539747u, 4101829900u, 2212636668u, 407333779u, ++ 1792275682u, 4051089549u, 2263378557u, 491595282u, 1775619997u, 4067460082u, 2246988034u, 508239213u, ++ 2029433880u, 3813931127u, 2496473735u, 258500328u, 2079362919u, 3763716872u, 2546668024u, 208559511u, ++ 2130363110u, 3848244873u, 2462145657u, 157552662u, 2113730969u, 3864638966u, 2445764358u, 174205801u, ++ 1961777636u, 4014675339u, 2564147067u, 57707284u, 2011718299u, 3964481268u, 2614361092u, 7778411u, ++ 1927425818u, 3913769845u, 2665066885u, 92077546u, 1910772837u, 3930150922u, 2648673018u, 108709525u, ++ 1352980496u, 3405878399u, 3164554895u, 658115296u, 1403183983u, 3355946752u, 3214507504u, 607924639u, ++ 1453895406u, 3440239233u, 3130208369u, 557218846u, 1437504913u, 3456883198u, 3113552654u, 573589345u, ++ 1555838444u, 3340335491u, 2961681267u, 723707676u, 1606028947u, 3290383100u, 3011612684u, 673504355u, ++ 1521500946u, 3239382909u, 3062619533u, 758026722u, 1505130605u, 3256038402u, 3045975794u, 774417053u, ++ 1217725416u, 3543158663u, 2762906999u, 1057739032u, 1267939479u, 3493229816u, 2812847624u, 1007544935u, ++ 1318679830u, 3577493881u, 2728586121u, 956803046u, 1302285929u, 3594125830u, 2711933174u, 973184153u, ++ 1150152212u, 3743982203u, 2830528651u, 856898788u, 1200346475u, 3694041348u, 2880457716u, 806684571u, ++ 1115789546u, 3643069573u, 2931426933u, 891243034u, 1099408277u, 3659722746u, 2914794762u, 907637093u, ++ }, { ++ 0u, 3717650821u, 1616688459u, 3184159950u, 3233376918u, 489665299u, 2699419613u, 2104690264u, ++ 1510200173u, 2274691816u, 979330598u, 3888758691u, 2595928571u, 1194090622u, 4209380528u, 661706037u, ++ 3020400346u, 1771143007u, 3562738577u, 164481556u, 1958661196u, 2837976521u, 350386439u, 3379863682u, ++ 3993269687u, 865250354u, 2388181244u, 1406015865u, 784146209u, 4079732388u, 1323412074u, 2474079215u, ++ 3011398645u, 1860735600u, 3542286014u, 246687547u, 1942430051u, 2924607718u, 328963112u, 3456978349u, ++ 3917322392u, 887832861u, 2300653011u, 1421341782u, 700772878u, 4099025803u, 1234716485u, 2483986112u, ++ 125431087u, 3673109674u, 1730500708u, 3132326369u, 3351283641u, 441867836u, 2812031730u, 2047535991u, ++ 1568292418u, 2163009479u, 1025936137u, 3769651852u, 2646824148u, 1079348561u, 4255113631u, 537475098u, ++ 3180171691u, 1612400686u, 3721471200u, 4717925u, 2100624189u, 2694980280u, 493375094u, 3237910515u, ++ 3884860102u, 974691139u, 2278750093u, 1514417672u, 657926224u, 4204917205u, 1198234907u, 2600289438u, ++ 160053105u, 3558665972u, 1775665722u, 3024116671u, 3375586791u, 346391650u, 2842683564u, 1962488105u, ++ 1401545756u, 2384412057u, 869618007u, 3997403346u, 2469432970u, 1319524111u, 4083956673u, 788193860u, ++ 250862174u, 3546612699u, 1856990997u, 3006903952u, 3461001416u, 333211981u, 2920678787u, 1937824774u, ++ 1425017139u, 2305216694u, 883735672u, 3912918525u, 2487837605u, 1239398944u, 4095071982u, 696455019u, ++ 3136584836u, 1734518017u, 3668494799u, 121507914u, 2051872274u, 2816200599u, 437363545u, 3347544796u, ++ 3774328809u, 1029797484u, 2158697122u, 1564328743u, 542033279u, 4258798842u, 1074950196u, 2642717105u, ++ 2691310871u, 2113731730u, 3224801372u, 497043929u, 1624461185u, 3175454212u, 9435850u, 3709412175u, ++ 4201248378u, 671035391u, 2587181873u, 1201904308u, 986750188u, 3880142185u, 1519135143u, 2266689570u, ++ 342721485u, 3388693064u, 1949382278u, 2846355203u, 3570723163u, 155332830u, 3028835344u, 1763607957u, ++ 1315852448u, 2482538789u, 775087595u, 4087626862u, 2396469814u, 1396827059u, 4002123645u, 857560824u, ++ 320106210u, 3464673127u, 1934154665u, 2933785132u, 3551331444u, 238804465u, 3018961215u, 1852270778u, ++ 1226292623u, 2491507722u, 692783300u, 4108177729u, 2309936921u, 1412959900u, 3924976210u, 879016919u, ++ 2803091512u, 2055541181u, 3343875443u, 450471158u, 1739236014u, 3124525867u, 133568485u, 3663777376u, ++ 4245691221u, 545702608u, 2639048222u, 1088059291u, 1034514883u, 3762268230u, 1576387720u, 2153979149u, ++ 501724348u, 3228659001u, 2109407735u, 2687359090u, 3713981994u, 13109167u, 3171052385u, 1620357860u, ++ 1206151121u, 2591211092u, 666423962u, 4197321503u, 2271022407u, 1523307714u, 3875649548u, 982999433u, ++ 2850034278u, 1953942499u, 3384583981u, 338329256u, 1767471344u, 3033506165u, 151375291u, 3566408766u, ++ 4091789579u, 779425934u, 2478797888u, 1311354309u, 861580189u, 4006375960u, 1392910038u, 2391852883u, ++ 2929327945u, 1930372812u, 3469036034u, 324244359u, 1847629279u, 3015068762u, 243015828u, 3555391761u, ++ 4103744548u, 688715169u, 2496043375u, 1229996266u, 874727090u, 3920994103u, 1417671673u, 2313759356u, ++ 446585235u, 3339223062u, 2059594968u, 2807313757u, 3660002053u, 129100416u, 3128657486u, 1743609803u, ++ 1084066558u, 2634765179u, 549535669u, 4250396208u, 2149900392u, 1571961325u, 3765982499u, 1039043750u, ++ }, { ++ 0u, 2635063670u, 3782132909u, 2086741467u, 430739227u, 2225303149u, 4173482934u, 1707977408u, ++ 861478454u, 2924937024u, 3526875803u, 1329085421u, 720736557u, 3086643291u, 3415954816u, 1452586230u, ++ 1722956908u, 4223524122u, 2279405761u, 450042295u, 2132718455u, 3792785921u, 2658170842u, 58693292u, ++ 1441473114u, 3370435372u, 3028674295u, 696911745u, 1279765825u, 3511176247u, 2905172460u, 807831706u, ++ 3445913816u, 1349228974u, 738901109u, 2969918723u, 3569940419u, 1237784245u, 900084590u, 2829701656u, ++ 4265436910u, 1664255896u, 525574723u, 2187084597u, 3885099509u, 2057177219u, 117386584u, 2616249390u, ++ 2882946228u, 920233410u, 1253605401u, 3619119471u, 2994391983u, 796207833u, 1393823490u, 3457937012u, ++ 2559531650u, 92322804u, 2044829231u, 3840835417u, 2166609305u, 472659183u, 1615663412u, 4249022530u, ++ 1102706673u, 3702920839u, 2698457948u, 1037619754u, 1477802218u, 3306854812u, 3111894087u, 611605809u, ++ 1927342535u, 4025419953u, 2475568490u, 243387420u, 1800169180u, 4131620778u, 2317525617u, 388842247u, ++ 655084445u, 3120835307u, 3328511792u, 1533734470u, 1051149446u, 2745738736u, 3754524715u, 1120297309u, ++ 340972971u, 2304586973u, 4114354438u, 1748234352u, 234773168u, 2431761350u, 3968900637u, 1906278251u, ++ 2363330345u, 299003487u, 1840466820u, 4038896370u, 2507210802u, 142532932u, 1948239007u, 3910149609u, ++ 3213136159u, 579563625u, 1592415666u, 3286611140u, 2787646980u, 992477042u, 1195825833u, 3662232543u, ++ 3933188933u, 2002801203u, 184645608u, 2517538462u, 4089658462u, 1858919720u, 313391347u, 2409765253u, ++ 3644239219u, 1144605701u, 945318366u, 2773977256u, 3231326824u, 1570095902u, 569697989u, 3170568115u, ++ 2205413346u, 511446676u, 1646078799u, 4279421497u, 2598330617u, 131105167u, 2075239508u, 3871229218u, ++ 2955604436u, 757403810u, 1363424633u, 3427521551u, 2844163791u, 881434553u, 1223211618u, 3588709140u, ++ 3854685070u, 2026779384u, 78583587u, 2577462869u, 4235025557u, 1633861091u, 486774840u, 2148301134u, ++ 3600338360u, 1268198606u, 938871061u, 2868504675u, 3476308643u, 1379640277u, 777684494u, 3008718712u, ++ 1310168890u, 3541595724u, 2943964055u, 846639841u, 1471879201u, 3400857943u, 3067468940u, 735723002u, ++ 2102298892u, 3762382970u, 2619362721u, 19901655u, 1692534295u, 4193118049u, 2240594618u, 411247564u, ++ 681945942u, 3047836192u, 3385552891u, 1422167693u, 822682701u, 2886124859u, 3496468704u, 1298661782u, ++ 469546336u, 2264093718u, 4203901389u, 1738379451u, 38812283u, 2673859341u, 3812556502u, 2117148576u, ++ 3268024339u, 1606809957u, 598006974u, 3198893512u, 3680933640u, 1181316734u, 973624229u, 2802299603u, ++ 4052944421u, 1822222163u, 285065864u, 2381456382u, 3896478014u, 1966106696u, 156323219u, 2489232613u, ++ 2759337087u, 964150537u, 1159127250u, 3625517476u, 3184831332u, 551242258u, 1555722185u, 3249901247u, ++ 2535537225u, 170842943u, 1984954084u, 3946848146u, 2391651666u, 327308324u, 1877176831u, 4075589769u, ++ 263086283u, 2460058045u, 4005602406u, 1942963472u, 369291216u, 2332888742u, 4151061373u, 1784924683u, ++ 1022852861u, 2717425547u, 3717839440u, 1083595558u, 626782694u, 3092517008u, 3291821387u, 1497027645u, ++ 1763466407u, 4094934481u, 2289211402u, 360544636u, 1890636732u, 3988730570u, 2447251217u, 215086695u, ++ 1514488465u, 3343557607u, 3140191804u, 639919946u, 1139395978u, 3739626748u, 2726758695u, 1065936977u, ++ }, { ++ 0u, 3120290792u, 2827399569u, 293431929u, 2323408227u, 864534155u, 586863858u, 2600537882u, ++ 3481914503u, 1987188591u, 1729068310u, 3740575486u, 1173727716u, 4228805132u, 3983743093u, 1418249117u, ++ 1147313999u, 4254680231u, 3974377182u, 1428157750u, 3458136620u, 2011505092u, 1721256893u, 3747844181u, ++ 2347455432u, 839944224u, 594403929u, 2593536433u, 26687147u, 3094146371u, 2836498234u, 283794642u, ++ 2294627998u, 826205558u, 541298447u, 2578994407u, 45702141u, 3141697557u, 2856315500u, 331624836u, ++ 1196225049u, 4273416689u, 4023010184u, 1446090848u, 3442513786u, 1959480466u, 1706436331u, 3696098563u, ++ 3433538001u, 1968994873u, 1679888448u, 3722103720u, 1188807858u, 4280295258u, 3999102243u, 1470541515u, ++ 53374294u, 3134568126u, 2879970503u, 307431215u, 2303854645u, 816436189u, 567589284u, 2553242188u, ++ 3405478781u, 1929420949u, 1652411116u, 3682996484u, 1082596894u, 4185703926u, 3892424591u, 1375368295u, ++ 91404282u, 3163122706u, 2918450795u, 336584067u, 2400113305u, 922028401u, 663249672u, 2658384096u, ++ 2392450098u, 929185754u, 639587747u, 2682555979u, 82149713u, 3172883129u, 2892181696u, 362343208u, ++ 1091578037u, 4176212829u, 3918960932u, 1349337804u, 3412872662u, 1922537022u, 1676344391u, 3658557359u, ++ 1111377379u, 4224032267u, 3937989746u, 1396912026u, 3359776896u, 1908013928u, 1623494929u, 3644803833u, ++ 2377615716u, 877417100u, 623982837u, 2630542109u, 130804743u, 3190831087u, 2941083030u, 381060734u, ++ 106748588u, 3215393092u, 2933549885u, 388083925u, 2350956495u, 903570471u, 614862430u, 2640172470u, ++ 3386185259u, 1882115523u, 1632872378u, 3634920530u, 1135178568u, 4199721120u, 3945775833u, 1389631793u, ++ 1317531835u, 4152109907u, 3858841898u, 1610259138u, 3304822232u, 2097172016u, 1820140617u, 3582394273u, ++ 2165193788u, 955639764u, 696815021u, 2423477829u, 192043359u, 2995356343u, 2750736590u, 437203750u, ++ 182808564u, 3005133852u, 2724453989u, 462947725u, 2157513367u, 962777471u, 673168134u, 2447663342u, ++ 3312231283u, 2090301595u, 1844056802u, 3557935370u, 1326499344u, 4142603768u, 3885397889u, 1584245865u, ++ 3326266917u, 2142836173u, 1858371508u, 3611272284u, 1279175494u, 4123357358u, 3837270743u, 1564721471u, ++ 164299426u, 2955991370u, 2706223923u, 414607579u, 2209834945u, 978107433u, 724686416u, 2462715320u, ++ 2183156074u, 1004243586u, 715579643u, 2472360723u, 140260361u, 2980573153u, 2698675608u, 421617264u, ++ 1302961645u, 4099032581u, 3845074044u, 1557460884u, 3352688782u, 2116952934u, 1867729183u, 3601371895u, ++ 2222754758u, 1032278062u, 754596439u, 2499928511u, 234942117u, 3086693709u, 2793824052u, 528319708u, ++ 1274365761u, 4061043881u, 3816027856u, 1518873912u, 3246989858u, 2020800970u, 1762628531u, 3505670235u, ++ 3223196809u, 2045103969u, 1754834200u, 3512958704u, 1247965674u, 4086934018u, 3806642299u, 1528765331u, ++ 261609486u, 3060532198u, 2802936223u, 518697591u, 2246819181u, 1007707781u, 762121468u, 2492913428u, ++ 213497176u, 3041029808u, 2755593417u, 499441441u, 2261110843u, 1061030867u, 776167850u, 2545465922u, ++ 3274734047u, 2060165687u, 1807140942u, 3528266662u, 1229724860u, 4038575956u, 3788156205u, 1479636677u, ++ 1222322711u, 4045468159u, 3764231046u, 1504067694u, 3265744756u, 2069664924u, 1780612837u, 3554288909u, ++ 2270357136u, 1051278712u, 802445057u, 2519698665u, 221152243u, 3033880603u, 2779263586u, 475261322u, ++ }, { ++ 0u, 2926088593u, 2275419491u, 701019378u, 3560000647u, 2052709654u, 1402038756u, 4261017717u, ++ 1930665807u, 3715829470u, 4105419308u, 1524313021u, 2804077512u, 155861593u, 545453739u, 2397726522u, ++ 3861331614u, 1213181711u, 1636244477u, 3488582252u, 840331801u, 2625561480u, 3048626042u, 467584747u, ++ 2503254481u, 995897408u, 311723186u, 3170637091u, 1090907478u, 4016929991u, 3332753461u, 1758288292u, ++ 390036349u, 3109546732u, 2426363422u, 1056427919u, 3272488954u, 1835443819u, 1152258713u, 3938878216u, ++ 1680663602u, 3393484195u, 3817652561u, 1306808512u, 2954733749u, 510998820u, 935169494u, 2580880455u, ++ 4044899811u, 1601229938u, 1991794816u, 3637571857u, 623446372u, 2336332021u, 2726898695u, 216120726u, ++ 2181814956u, 744704829u, 95158223u, 2881711710u, 1446680107u, 4166125498u, 3516576584u, 2146575065u, ++ 780072698u, 2148951915u, 2849952665u, 129384968u, 4199529085u, 1411853292u, 2112855838u, 3548843663u, ++ 1567451573u, 4077254692u, 3670887638u, 1957027143u, 2304517426u, 657765539u, 251396177u, 2694091200u, ++ 3361327204u, 1714510325u, 1341779207u, 3784408214u, 476611811u, 2986349938u, 2613617024u, 899690513u, ++ 3142211371u, 354600634u, 1021997640u, 2458051545u, 1870338988u, 3239283261u, 3906682575u, 1186180958u, ++ 960597383u, 2536053782u, 3202459876u, 277428597u, 3983589632u, 1125666961u, 1792074851u, 3300423154u, ++ 1246892744u, 3829039961u, 3455203243u, 1671079482u, 2657312335u, 806080478u, 432241452u, 3081497277u, ++ 3748049689u, 1896751752u, 1489409658u, 4138600427u, 190316446u, 2772397583u, 2365053693u, 580864876u, ++ 2893360214u, 35503559u, 735381813u, 2243795108u, 2017747153u, 3593269568u, 4293150130u, 1368183843u, ++ 1560145396u, 4069882981u, 3680356503u, 1966430470u, 2295112051u, 648294626u, 258769936u, 2701399425u, ++ 804156091u, 2173100842u, 2823706584u, 103204425u, 4225711676u, 1438101421u, 2088704863u, 3524758222u, ++ 3134903146u, 347226875u, 1031468553u, 2467456920u, 1860935661u, 3229814396u, 3914054286u, 1193487135u, ++ 3385412645u, 1738661300u, 1315531078u, 3758225623u, 502792354u, 3012596019u, 2589468097u, 875607120u, ++ 1271043721u, 3853125400u, 3429020650u, 1644831355u, 2683558414u, 832261023u, 408158061u, 3057348348u, ++ 953223622u, 2528745559u, 3211865253u, 286899508u, 3974120769u, 1116263632u, 1799381026u, 3307794867u, ++ 2917509143u, 59586950u, 709201268u, 2217549029u, 2043995280u, 3619452161u, 4269064691u, 1344032866u, ++ 3740677976u, 1889445577u, 1498812987u, 4148069290u, 180845535u, 2762992206u, 2372361916u, 588238637u, ++ 1921194766u, 3706423967u, 4112727661u, 1531686908u, 2796705673u, 148555288u, 554857194u, 2407195515u, ++ 26248257u, 2952271312u, 2251333922u, 676868275u, 3584149702u, 2076793175u, 1375858085u, 4234771508u, ++ 2493785488u, 986493953u, 319029491u, 3178008930u, 1083533591u, 4009621638u, 3342158964u, 1767759333u, ++ 3887577823u, 1239362382u, 1612160956u, 3464433197u, 864482904u, 2649647049u, 3022443323u, 441336490u, ++ 1706844275u, 3419730402u, 3793503504u, 1282724993u, 2978819316u, 535149925u, 908921239u, 2554697734u, ++ 380632892u, 3100077741u, 2433735263u, 1063734222u, 3265180603u, 1828069930u, 1161729752u, 3948283721u, ++ 2207997677u, 770953084u, 71007118u, 2857626143u, 1470763626u, 4190274555u, 3490330377u, 2120394392u, ++ 4035494306u, 1591758899u, 1999168705u, 3644880208u, 616140069u, 2328960180u, 2736367686u, 225524183u, ++ }, + }; + +-#define WUFFS_GIF__QUIRKS_BASE 1041635328 +- +-#define WUFFS_GIF__QUIRKS_COUNT 7 +- + // ---------------- Private Initializer Prototypes + + // ---------------- Private Function Prototypes + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__do_decode_image_config( +- wuffs_gif__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__do_tell_me_more( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__do_decode_frame_config( +- wuffs_gif__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__skip_frame( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__do_decode_frame( +- wuffs_gif__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); +- + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_gif__decoder__reset_gc( +- wuffs_gif__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_up_to_id_part1( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_header( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_lsd( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_extension( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__skip_blocks( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_ae( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_gc( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_id_part0( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_id_part1( +- wuffs_gif__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__decode_id_part2( +- wuffs_gif__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf); ++wuffs_crc32__ieee_hasher__up( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x); + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__copy_to_image_buffer( +- wuffs_gif__decoder* self, +- wuffs_base__pixel_buffer* a_pb, +- wuffs_base__slice_u8 a_src); ++static wuffs_base__empty_struct ++wuffs_crc32__ieee_hasher__up__choosy_default( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x); + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32) + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_gif__decoder__lzw_init( +- wuffs_gif__decoder* self); ++wuffs_crc32__ieee_hasher__up_arm_crc32( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32) + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_gif__decoder__lzw_read_from( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src); ++wuffs_crc32__ieee_hasher__up_x86_sse42( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) + + // ---------------- VTables + +-const wuffs_base__image_decoder__func_ptrs +-wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__pixel_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__pixel_blend, +- wuffs_base__slice_u8, +- wuffs_base__decode_frame_options*))(&wuffs_gif__decoder__decode_frame), +- (wuffs_base__status(*)(void*, +- wuffs_base__frame_config*, +- wuffs_base__io_buffer*))(&wuffs_gif__decoder__decode_frame_config), +- (wuffs_base__status(*)(void*, +- wuffs_base__image_config*, +- wuffs_base__io_buffer*))(&wuffs_gif__decoder__decode_image_config), +- (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_gif__decoder__frame_dirty_rect), ++const wuffs_base__hasher_u32__func_ptrs ++wuffs_crc32__ieee_hasher__func_ptrs_for__wuffs_base__hasher_u32 = { ++ (uint32_t(*)(const void*))(&wuffs_crc32__ieee_hasher__checksum_u32), + (uint64_t(*)(const void*, +- uint32_t))(&wuffs_gif__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_gif__decoder__history_retain_length), +- (uint32_t(*)(const void*))(&wuffs_gif__decoder__num_animation_loops), +- (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frame_configs), +- (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frames), +- (wuffs_base__status(*)(void*, +- uint64_t, +- uint64_t))(&wuffs_gif__decoder__restart_frame), ++ uint32_t))(&wuffs_crc32__ieee_hasher__get_quirk), + (wuffs_base__status(*)(void*, + uint32_t, +- uint64_t))(&wuffs_gif__decoder__set_quirk), ++ uint64_t))(&wuffs_crc32__ieee_hasher__set_quirk), + (wuffs_base__empty_struct(*)(void*, +- uint32_t, +- bool))(&wuffs_gif__decoder__set_report_metadata), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__more_information*, +- wuffs_base__io_buffer*))(&wuffs_gif__decoder__tell_me_more), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_gif__decoder__workbuf_len), ++ wuffs_base__slice_u8))(&wuffs_crc32__ieee_hasher__update), ++ (uint32_t(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_crc32__ieee_hasher__update_u32), + }; + + // ---------------- Initializer Implementations + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_gif__decoder__initialize( +- wuffs_gif__decoder* self, ++wuffs_crc32__ieee_hasher__initialize( ++ wuffs_crc32__ieee_hasher* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options){ +@@ -36681,23 +37083,25 @@ wuffs_gif__decoder__initialize( + } + } + ++ self->private_impl.choosy_up = &wuffs_crc32__ieee_hasher__up__choosy_default; ++ + self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = +- wuffs_base__image_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = +- (const void*)(&wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name = ++ wuffs_base__hasher_u32__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers = ++ (const void*)(&wuffs_crc32__ieee_hasher__func_ptrs_for__wuffs_base__hasher_u32); + return wuffs_base__make_status(NULL); + } + +-wuffs_gif__decoder* +-wuffs_gif__decoder__alloc(void) { +- wuffs_gif__decoder* x = +- (wuffs_gif__decoder*)(calloc(sizeof(wuffs_gif__decoder), 1)); ++wuffs_crc32__ieee_hasher* ++wuffs_crc32__ieee_hasher__alloc(void) { ++ wuffs_crc32__ieee_hasher* x = ++ (wuffs_crc32__ieee_hasher*)(calloc(1, sizeof(wuffs_crc32__ieee_hasher))); + if (!x) { + return NULL; + } +- if (wuffs_gif__decoder__initialize( +- x, sizeof(wuffs_gif__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ if (wuffs_crc32__ieee_hasher__initialize( ++ x, sizeof(wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { + free(x); + return NULL; + } +@@ -36705,18 +37109,18 @@ wuffs_gif__decoder__alloc(void) { + } + + size_t +-sizeof__wuffs_gif__decoder(void) { +- return sizeof(wuffs_gif__decoder); ++sizeof__wuffs_crc32__ieee_hasher(void) { ++ return sizeof(wuffs_crc32__ieee_hasher); + } + + // ---------------- Function Implementations + +-// -------- func gif.decoder.get_quirk ++// -------- func crc32.ieee_hasher.get_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_gif__decoder__get_quirk( +- const wuffs_gif__decoder* self, ++wuffs_crc32__ieee_hasher__get_quirk( ++ const wuffs_crc32__ieee_hasher* self, + uint32_t a_key) { + if (!self) { + return 0; +@@ -36726,25 +37130,15 @@ wuffs_gif__decoder__get_quirk( + return 0; + } + +- uint32_t v_key = 0; +- +- if (a_key >= 1041635328u) { +- v_key = (a_key - 1041635328u); +- if (v_key < 7u) { +- if (self->private_impl.f_quirks[v_key]) { +- return 1u; +- } +- } +- } + return 0u; + } + +-// -------- func gif.decoder.set_quirk ++// -------- func crc32.ieee_hasher.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_gif__decoder__set_quirk( +- wuffs_gif__decoder* self, ++wuffs_crc32__ieee_hasher__set_quirk( ++ wuffs_crc32__ieee_hasher* self, + uint32_t a_key, + uint64_t a_value) { + if (!self) { +@@ -36757,377 +37151,812 @@ wuffs_gif__decoder__set_quirk( + : wuffs_base__error__initialize_not_called); + } + +- if ((self->private_impl.f_call_sequence == 0u) && (a_key >= 1041635328u)) { +- a_key -= 1041635328u; +- if (a_key < 7u) { +- self->private_impl.f_quirks[a_key] = (a_value > 0u); +- return wuffs_base__make_status(NULL); +- } +- } + return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func gif.decoder.decode_image_config ++// -------- func crc32.ieee_hasher.update + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_gif__decoder__decode_image_config( +- wuffs_gif__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_crc32__ieee_hasher__update( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x) { + if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ return wuffs_base__make_empty_struct(); + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ return wuffs_base__make_empty_struct(); + } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_gif__decoder__do_decode_image_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_gif__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } + +- ok: +- self->private_impl.p_decode_image_config[0] = 0; +- goto exit; ++ if (self->private_impl.f_state == 0u) { ++ self->private_impl.choosy_up = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32) ++ wuffs_base__cpu_arch__have_arm_crc32() ? &wuffs_crc32__ieee_hasher__up_arm_crc32 : ++#endif ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_crc32__ieee_hasher__up_x86_sse42 : ++#endif ++ self->private_impl.choosy_up); + } ++ wuffs_crc32__ieee_hasher__up(self, a_x); ++ return wuffs_base__make_empty_struct(); ++} + +- goto suspend; +- suspend: +- self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++// -------- func crc32.ieee_hasher.update_u32 + +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_crc32__ieee_hasher__update_u32( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return 0; + } +- return status; ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return 0; ++ } ++ ++ wuffs_crc32__ieee_hasher__update(self, a_x); ++ return self->private_impl.f_state; + } + +-// -------- func gif.decoder.do_decode_image_config ++// -------- func crc32.ieee_hasher.up + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__do_decode_image_config( +- wuffs_gif__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- bool v_ffio = false; ++static wuffs_base__empty_struct ++wuffs_crc32__ieee_hasher__up( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ return (*self->private_impl.choosy_up)(self, a_x); ++} + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_crc32__ieee_hasher__up__choosy_default( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint32_t v_s = 0; ++ wuffs_base__slice_u8 v_p = {0}; + +- if (self->private_impl.f_call_sequence != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } else if ( ! self->private_impl.f_seen_header) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_gif__decoder__decode_header(self, a_src); +- if (status.repr) { +- goto suspend; +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- status = wuffs_gif__decoder__decode_lsd(self, a_src); +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_header = true; +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src); +- if (status.repr) { +- goto suspend; +- } +- v_ffio = ! self->private_impl.f_gc_has_transparent_index; +- if ( ! self->private_impl.f_quirks[2u]) { +- v_ffio = (v_ffio && +- (self->private_impl.f_frame_rect_x0 == 0u) && +- (self->private_impl.f_frame_rect_y0 == 0u) && +- (self->private_impl.f_frame_rect_x1 == self->private_impl.f_width) && +- (self->private_impl.f_frame_rect_y1 == self->private_impl.f_height)); +- } else if (v_ffio) { +- self->private_impl.f_black_color_u32_argb_premul = 4278190080u; +- } +- if (self->private_impl.f_background_color_u32_argb_premul == 77u) { +- self->private_impl.f_background_color_u32_argb_premul = self->private_impl.f_black_color_u32_argb_premul; ++ v_s = (4294967295u ^ self->private_impl.f_state); ++ { ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 16; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32)); ++ while (v_p.ptr < i_end0_p) { ++ v_s ^= ((((uint32_t)(v_p.ptr[0u])) << 0u) | ++ (((uint32_t)(v_p.ptr[1u])) << 8u) | ++ (((uint32_t)(v_p.ptr[2u])) << 16u) | ++ (((uint32_t)(v_p.ptr[3u])) << 24u)); ++ v_s = (WUFFS_CRC32__IEEE_TABLE[0u][v_p.ptr[15u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[1u][v_p.ptr[14u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[2u][v_p.ptr[13u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[3u][v_p.ptr[12u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[4u][v_p.ptr[11u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[5u][v_p.ptr[10u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[6u][v_p.ptr[9u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[7u][v_p.ptr[8u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[8u][v_p.ptr[7u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[9u][v_p.ptr[6u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[10u][v_p.ptr[5u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[11u][v_p.ptr[4u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[12u][(255u & (v_s >> 24u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[13u][(255u & (v_s >> 16u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[14u][(255u & (v_s >> 8u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[15u][(255u & (v_s >> 0u))]); ++ v_p.ptr += 16; ++ v_s ^= ((((uint32_t)(v_p.ptr[0u])) << 0u) | ++ (((uint32_t)(v_p.ptr[1u])) << 8u) | ++ (((uint32_t)(v_p.ptr[2u])) << 16u) | ++ (((uint32_t)(v_p.ptr[3u])) << 24u)); ++ v_s = (WUFFS_CRC32__IEEE_TABLE[0u][v_p.ptr[15u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[1u][v_p.ptr[14u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[2u][v_p.ptr[13u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[3u][v_p.ptr[12u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[4u][v_p.ptr[11u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[5u][v_p.ptr[10u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[6u][v_p.ptr[9u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[7u][v_p.ptr[8u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[8u][v_p.ptr[7u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[9u][v_p.ptr[6u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[10u][v_p.ptr[5u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[11u][v_p.ptr[4u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[12u][(255u & (v_s >> 24u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[13u][(255u & (v_s >> 16u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[14u][(255u & (v_s >> 8u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[15u][(255u & (v_s >> 0u))]); ++ v_p.ptr += 16; + } +- if (a_dst != NULL) { +- wuffs_base__image_config__set( +- a_dst, +- 2198077448u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height, +- self->private_impl.f_frame_config_io_position, +- v_ffio); ++ v_p.len = 16; ++ const uint8_t* i_end1_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 16) * 16)); ++ while (v_p.ptr < i_end1_p) { ++ v_s ^= ((((uint32_t)(v_p.ptr[0u])) << 0u) | ++ (((uint32_t)(v_p.ptr[1u])) << 8u) | ++ (((uint32_t)(v_p.ptr[2u])) << 16u) | ++ (((uint32_t)(v_p.ptr[3u])) << 24u)); ++ v_s = (WUFFS_CRC32__IEEE_TABLE[0u][v_p.ptr[15u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[1u][v_p.ptr[14u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[2u][v_p.ptr[13u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[3u][v_p.ptr[12u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[4u][v_p.ptr[11u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[5u][v_p.ptr[10u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[6u][v_p.ptr[9u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[7u][v_p.ptr[8u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[8u][v_p.ptr[7u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[9u][v_p.ptr[6u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[10u][v_p.ptr[5u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[11u][v_p.ptr[4u]] ^ ++ WUFFS_CRC32__IEEE_TABLE[12u][(255u & (v_s >> 24u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[13u][(255u & (v_s >> 16u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[14u][(255u & (v_s >> 8u))] ^ ++ WUFFS_CRC32__IEEE_TABLE[15u][(255u & (v_s >> 0u))]); ++ v_p.ptr += 16; + } +- if (self->private_impl.f_call_sequence == 0u) { +- self->private_impl.f_call_sequence = 32u; ++ v_p.len = 1; ++ const uint8_t* i_end2_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end2_p) { ++ v_s = (WUFFS_CRC32__IEEE_TABLE[0u][((uint8_t)(((uint8_t)(v_s)) ^ v_p.ptr[0u]))] ^ (v_s >> 8u)); ++ v_p.ptr += 1; + } +- +- goto ok; +- ok: +- self->private_impl.p_do_decode_image_config[0] = 0; +- goto exit; ++ v_p.len = 0; + } +- +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- return status; ++ self->private_impl.f_state = (4294967295u ^ v_s); ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func gif.decoder.set_report_metadata ++// -------- func crc32.ieee_hasher.checksum_u32 + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_gif__decoder__set_report_metadata( +- wuffs_gif__decoder* self, +- uint32_t a_fourcc, +- bool a_report) { ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_crc32__ieee_hasher__checksum_u32( ++ const wuffs_crc32__ieee_hasher* self) { + if (!self) { +- return wuffs_base__make_empty_struct(); ++ return 0; + } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } + +- if (a_fourcc == 1229144912u) { +- self->private_impl.f_report_metadata_iccp = a_report; +- } else if (a_fourcc == 1481461792u) { +- self->private_impl.f_report_metadata_xmp = a_report; ++ return self->private_impl.f_state; ++} ++ ++// ‼ WUFFS MULTI-FILE SECTION +arm_crc32 ++// -------- func crc32.ieee_hasher.up_arm_crc32 ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_crc32__ieee_hasher__up_arm_crc32( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ wuffs_base__slice_u8 v_p = {0}; ++ uint32_t v_s = 0; ++ ++ v_s = (4294967295u ^ self->private_impl.f_state); ++ while ((((uint64_t)(a_x.len)) > 0u) && ((15u & ((uint32_t)(0xFFFu & (uintptr_t)(a_x.ptr)))) != 0u)) { ++ v_s = __crc32b(v_s, a_x.ptr[0u]); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); ++ } ++ { ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 8; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 128) * 128)); ++ while (v_p.ptr < i_end0_p) { ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ } ++ v_p.len = 8; ++ const uint8_t* i_end1_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8)); ++ while (v_p.ptr < i_end1_p) { ++ v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr)); ++ v_p.ptr += 8; ++ } ++ v_p.len = 1; ++ const uint8_t* i_end2_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end2_p) { ++ v_s = __crc32b(v_s, v_p.ptr[0u]); ++ v_p.ptr += 1; ++ } ++ v_p.len = 0; + } ++ self->private_impl.f_state = (4294967295u ^ v_s); + return wuffs_base__make_empty_struct(); + } ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_CRC32) ++// ‼ WUFFS MULTI-FILE SECTION -arm_crc32 + +-// -------- func gif.decoder.tell_me_more ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++// -------- func crc32.ieee_hasher.up_x86_sse42 + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_gif__decoder__tell_me_more( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++static wuffs_base__empty_struct ++wuffs_crc32__ieee_hasher__up_x86_sse42( ++ wuffs_crc32__ieee_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint32_t v_s = 0; ++ __m128i v_kk = {0}; ++ __m128i v_x0 = {0}; ++ __m128i v_x1 = {0}; ++ __m128i v_x2 = {0}; ++ __m128i v_x3 = {0}; ++ __m128i v_x4 = {0}; ++ __m128i v_x5 = {0}; ++ __m128i v_x6 = {0}; ++ __m128i v_x7 = {0}; ++ __m128i v_y0 = {0}; ++ __m128i v_y1 = {0}; ++ __m128i v_y2 = {0}; ++ __m128i v_y3 = {0}; ++ __m128i v_y4 = {0}; ++ __m128i v_y5 = {0}; ++ __m128i v_y6 = {0}; ++ __m128i v_y7 = {0}; ++ ++ v_s = (4294967295u ^ self->private_impl.f_state); ++ while ((((uint64_t)(a_x.len)) > 0u) && ((15u & ((uint32_t)(0xFFFu & (uintptr_t)(a_x.ptr)))) != 0u)) { ++ v_s = (WUFFS_CRC32__IEEE_TABLE[0u][((uint8_t)(((uint8_t)(v_s)) ^ a_x.ptr[0u]))] ^ (v_s >> 8u)); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); + } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ if (((uint64_t)(a_x.len)) >= 128u) { ++ v_x0 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u)); ++ v_x1 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u)); ++ v_x2 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32u)); ++ v_x3 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48u)); ++ v_x4 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 64u)); ++ v_x5 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 80u)); ++ v_x6 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 96u)); ++ v_x7 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 112u)); ++ v_kk = _mm_set_epi32((int32_t)(0u), (int32_t)(2433674945u), (int32_t)(0u), (int32_t)(872412467u)); ++ v_x0 = _mm_xor_si128(v_x0, _mm_cvtsi32_si128((int32_t)(v_s))); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 128u); ++ while (((uint64_t)(a_x.len)) >= 128u) { ++ v_y0 = _mm_clmulepi64_si128(v_x0, v_kk, (int32_t)(0u)); ++ v_x0 = _mm_clmulepi64_si128(v_x0, v_kk, (int32_t)(17u)); ++ v_y1 = _mm_clmulepi64_si128(v_x1, v_kk, (int32_t)(0u)); ++ v_x1 = _mm_clmulepi64_si128(v_x1, v_kk, (int32_t)(17u)); ++ v_y2 = _mm_clmulepi64_si128(v_x2, v_kk, (int32_t)(0u)); ++ v_x2 = _mm_clmulepi64_si128(v_x2, v_kk, (int32_t)(17u)); ++ v_y3 = _mm_clmulepi64_si128(v_x3, v_kk, (int32_t)(0u)); ++ v_x3 = _mm_clmulepi64_si128(v_x3, v_kk, (int32_t)(17u)); ++ v_y4 = _mm_clmulepi64_si128(v_x4, v_kk, (int32_t)(0u)); ++ v_x4 = _mm_clmulepi64_si128(v_x4, v_kk, (int32_t)(17u)); ++ v_y5 = _mm_clmulepi64_si128(v_x5, v_kk, (int32_t)(0u)); ++ v_x5 = _mm_clmulepi64_si128(v_x5, v_kk, (int32_t)(17u)); ++ v_y6 = _mm_clmulepi64_si128(v_x6, v_kk, (int32_t)(0u)); ++ v_x6 = _mm_clmulepi64_si128(v_x6, v_kk, (int32_t)(17u)); ++ v_y7 = _mm_clmulepi64_si128(v_x7, v_kk, (int32_t)(0u)); ++ v_x7 = _mm_clmulepi64_si128(v_x7, v_kk, (int32_t)(17u)); ++ v_y0 = _mm_xor_si128(v_y0, _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u))); ++ v_x0 = _mm_xor_si128(v_x0, v_y0); ++ v_y1 = _mm_xor_si128(v_y1, _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u))); ++ v_x1 = _mm_xor_si128(v_x1, v_y1); ++ v_y2 = _mm_xor_si128(v_y2, _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32u))); ++ v_x2 = _mm_xor_si128(v_x2, v_y2); ++ v_y3 = _mm_xor_si128(v_y3, _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48u))); ++ v_x3 = _mm_xor_si128(v_x3, v_y3); ++ v_y4 = _mm_xor_si128(v_y4, _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 64u))); ++ v_x4 = _mm_xor_si128(v_x4, v_y4); ++ v_y5 = _mm_xor_si128(v_y5, _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 80u))); ++ v_x5 = _mm_xor_si128(v_x5, v_y5); ++ v_y6 = _mm_xor_si128(v_y6, _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 96u))); ++ v_x6 = _mm_xor_si128(v_x6, v_y6); ++ v_y7 = _mm_xor_si128(v_y7, _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 112u))); ++ v_x7 = _mm_xor_si128(v_x7, v_y7); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 128u); ++ } ++ v_kk = _mm_set_epi32((int32_t)(0u), (int32_t)(3433693342u), (int32_t)(0u), (int32_t)(2926088593u)); ++ v_y0 = _mm_clmulepi64_si128(v_x0, v_kk, (int32_t)(0u)); ++ v_x0 = _mm_clmulepi64_si128(v_x0, v_kk, (int32_t)(17u)); ++ v_y2 = _mm_clmulepi64_si128(v_x2, v_kk, (int32_t)(0u)); ++ v_x2 = _mm_clmulepi64_si128(v_x2, v_kk, (int32_t)(17u)); ++ v_y4 = _mm_clmulepi64_si128(v_x4, v_kk, (int32_t)(0u)); ++ v_x4 = _mm_clmulepi64_si128(v_x4, v_kk, (int32_t)(17u)); ++ v_y6 = _mm_clmulepi64_si128(v_x6, v_kk, (int32_t)(0u)); ++ v_x6 = _mm_clmulepi64_si128(v_x6, v_kk, (int32_t)(17u)); ++ v_y0 = _mm_xor_si128(v_y0, v_x1); ++ v_x0 = _mm_xor_si128(v_x0, v_y0); ++ v_y2 = _mm_xor_si128(v_y2, v_x3); ++ v_x2 = _mm_xor_si128(v_x2, v_y2); ++ v_y4 = _mm_xor_si128(v_y4, v_x5); ++ v_x4 = _mm_xor_si128(v_x4, v_y4); ++ v_y6 = _mm_xor_si128(v_y6, v_x7); ++ v_x6 = _mm_xor_si128(v_x6, v_y6); ++ v_kk = _mm_set_epi32((int32_t)(0u), (int32_t)(2166711591u), (int32_t)(0u), (int32_t)(4057597354u)); ++ v_y0 = _mm_clmulepi64_si128(v_x0, v_kk, (int32_t)(0u)); ++ v_x0 = _mm_clmulepi64_si128(v_x0, v_kk, (int32_t)(17u)); ++ v_y4 = _mm_clmulepi64_si128(v_x4, v_kk, (int32_t)(0u)); ++ v_x4 = _mm_clmulepi64_si128(v_x4, v_kk, (int32_t)(17u)); ++ v_y0 = _mm_xor_si128(v_y0, v_x2); ++ v_x0 = _mm_xor_si128(v_x0, v_y0); ++ v_y4 = _mm_xor_si128(v_y4, v_x6); ++ v_x4 = _mm_xor_si128(v_x4, v_y4); ++ v_kk = _mm_set_epi32((int32_t)(0u), (int32_t)(496309207u), (int32_t)(0u), (int32_t)(2402626965u)); ++ v_y0 = _mm_clmulepi64_si128(v_x0, v_kk, (int32_t)(0u)); ++ v_x0 = _mm_clmulepi64_si128(v_x0, v_kk, (int32_t)(17u)); ++ v_y0 = _mm_xor_si128(v_y0, v_x4); ++ v_x0 = _mm_xor_si128(v_x0, v_y0); ++ v_kk = _mm_set_epi32((int32_t)(1u), (int32_t)(3681617473u), (int32_t)(3034951717u), (int32_t)(4144043585u)); ++ v_s = ((uint32_t)(_mm_extract_epi32(_mm_clmulepi64_si128(_mm_clmulepi64_si128(_mm_cvtsi64_si128((int64_t)(((uint64_t)(_mm_extract_epi64(v_x0, (int32_t)(0u)))))), v_kk, (int32_t)(0u)), v_kk, (int32_t)(16u)), (int32_t)(2u)))); ++ v_kk = _mm_set_epi32((int32_t)(1u), (int32_t)(3681617473u), (int32_t)(3034951717u), (int32_t)(4144043585u)); ++ v_s = ((uint32_t)(_mm_extract_epi32(_mm_clmulepi64_si128(_mm_clmulepi64_si128(_mm_cvtsi64_si128((int64_t)((((uint64_t)(_mm_extract_epi64(v_x0, (int32_t)(1u)))) ^ ((uint64_t)(v_s))))), v_kk, (int32_t)(0u)), v_kk, (int32_t)(16u)), (int32_t)(2u)))); ++ } ++ while (((uint64_t)(a_x.len)) >= 8u) { ++ v_kk = _mm_set_epi32((int32_t)(1u), (int32_t)(3681617473u), (int32_t)(3034951717u), (int32_t)(4144043585u)); ++ v_s = ((uint32_t)(_mm_extract_epi32(_mm_clmulepi64_si128(_mm_clmulepi64_si128(_mm_cvtsi64_si128((int64_t)((wuffs_base__peek_u64le__no_bounds_check(a_x.ptr) ^ ((uint64_t)(v_s))))), v_kk, (int32_t)(0u)), v_kk, (int32_t)(16u)), (int32_t)(2u)))); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 8u); + } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 2)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ while (((uint64_t)(a_x.len)) > 0u) { ++ v_s = (WUFFS_CRC32__IEEE_TABLE[0u][((uint8_t)(((uint8_t)(v_s)) ^ a_x.ptr[0u]))] ^ (v_s >> 8u)); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); + } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ self->private_impl.f_state = (4294967295u ^ v_s); ++ return wuffs_base__make_empty_struct(); ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32) + +- uint32_t coro_susp_point = self->private_impl.p_tell_me_more[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC64) + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_gif__decoder__do_tell_me_more(self, a_dst, a_minfo, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_gif__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++// ---------------- Status Codes Implementations + +- ok: +- self->private_impl.p_tell_me_more[0] = 0; +- goto exit; +- } ++// ---------------- Private Consts + +- goto suspend; +- suspend: +- self->private_impl.p_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++static const uint64_t ++WUFFS_CRC64__ECMA_TABLE[8][256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ { ++ 0u, 12911341560706588527u, 17619267392293085275u, 5164075066763771700u, 8921845837811637811u, 14483170935171449180u, 10328150133527543400u, 4357999468653093127u, ++ 17843691675623275622u, 4940391307328217865u, 226782375002905661u, 12685511915359257426u, 10119945210068853333u, 4566377562367245626u, 8715998937306186254u, 14689403211693301089u, ++ 9051005139383707209u, 14895072503764629798u, 9880782614656435730u, 4193374422961527165u, 453564750005811322u, 13070904082541799189u, 17496296445768931361u, 4747102235666401102u, ++ 9960315520700766767u, 4113029525020509504u, 9132755124734491252u, 14812441257301386523u, 17431997874612372508u, 4811156168024382323u, 391483189436228679u, 13132671735097031464u, ++ 18102010278767414418u, 5195199925788447741u, 1131375642422963401u, 13591081480414639014u, 9288535643022529185u, 3731739485546663374u, 8386748845923054330u, 14361410892855143829u, ++ 907129500011622644u, 13814943346342178715u, 17875617253995106479u, 5421418680781082560u, 8594564625313771207u, 14152643483341451688u, 9494204471332802204u, 3525329033817543155u, ++ 9704381199536204507u, 3855837706121835956u, 8226059050041019008u, 13908973417437222383u, 18265510249468982504u, 5643692520190618503u, 718348998302913715u, 13463047253836762076u, ++ 8146277531524994749u, 13989069943491807698u, 9622312336048764646u, 3938150108875254153u, 782966378872457358u, 13399312233903888353u, 18327840216347633877u, 5582173445676054458u, ++ 7257036000092981153u, 15535280666427316430u, 10390399851576895482u, 2529986302517213333u, 2262751284845926802u, 12414353723947190013u, 16997392145760156105u, 6398650419759490726u, ++ 10599130201908394951u, 2322133910755632296u, 7463478971093326748u, 15329644185724306675u, 16773497691846108660u, 6622864283287239323u, 2036569382881248687u, 12640783567252986560u, ++ 1814259000023245288u, 12250853444207230599u, 17125426475222188467u, 6811676960462675676u, 7132938157145702363u, 15119434731753103540u, 10842837361562165120u, 2690676064372932847u, ++ 17189129250627542414u, 6747026957542163169u, 1875814858707893717u, 12188560364711551674u, 10762704257491731389u, 2770420489343360210u, 7050658067635086310u, 15201536148867841161u, ++ 11493583972846619443u, 3219832958944941148u, 7711675412243671912u, 15576564987190227975u, 16452118100082038016u, 6305011443818121839u, 1213047649942025563u, 11816267669673208372u, ++ 7503259434831574869u, 15784731923736995898u, 11287385040381237006u, 3425713581329221729u, 1436697996605827430u, 11591809733187859977u, 16677985422973077821u, 6078267261889762898u, ++ 16292555063049989498u, 5851447209550246421u, 1630020308903038241u, 11939238787801010766u, 11081681957373440841u, 3090674103720225830u, 7876300217750508306u, 16023932746787097725u, ++ 1565932757744914716u, 12003503911822413427u, 16230825569204842823u, 5913566482019610152u, 7956607163135676207u, 15944361922680361024u, 11164346891352108916u, 3008957496780927003u, ++ 14514072000185962306u, 8809633696146542637u, 4460922918905818905u, 10287960411460399222u, 12879331835779764593u, 113391187501452830u, 5059972605034426666u, 17660565739912801861u, ++ 4525502569691853604u, 10224187249629523019u, 14576435430675780479u, 8748148222884465680u, 4980157760350383383u, 17740628527280140920u, 12797300839518981452u, 195741594718114339u, ++ 13040162471224305931u, 565687821211481700u, 4644267821511264592u, 17536326748496696895u, 14926957942186653496u, 8937808626997553239u, 4297282312656885603u, 9839608450464401420u, ++ 4852190599768102253u, 17327666750234135042u, 13245728566574478646u, 359174499151456857u, 4073138765762497374u, 10063573324157604913u, 14700457781105076997u, 9163920108173816938u, ++ 3628518000046490576u, 9328460452529085631u, 14330211790445699979u, 8498696072880078052u, 5299565100954197475u, 18061012165519327884u, 13623353920925351352u, 1018284691440624343u, ++ 14265876314291404726u, 8562713237611094233u, 3566469078572851181u, 9390260331795218562u, 13702854325316886917u, 937907429353946858u, 5381352128745865694u, 17978417549248290481u, ++ 5746791986423309721u, 18225777846762470134u, 13494053915084326338u, 606523824971012781u, 3751629717415787434u, 9745292510640121029u, 13876787882151992305u, 8338992711486538910u, ++ 13285957365033343487u, 815010154451519120u, 5540840978686720420u, 18431906428167644875u, 14101316135270172620u, 8115412784602421411u, 3978303581567838103u, 9519354766961195256u, ++ 12527462061959317731u, 2230461459452909452u, 6439665917889882296u, 16893009583564617687u, 15423350824487343824u, 7288217715337890239u, 2490078880175191691u, 10493603952060017124u, ++ 6520081235612152965u, 16813546994155744234u, 12610022887636243678u, 2148641156328442801u, 2426095299884051126u, 10557972909709735385u, 15361512820870335213u, 7350228890552538498u, ++ 15006518869663149738u, 7165105895222849989u, 2649782550477098737u, 10947027550912647582u, 12362696414880903321u, 1783234539286425590u, 6851427162658443458u, 17022309211647725485u, ++ 2873395993211654860u, 10722532847870938531u, 15232418832718623383u, 6938393941075996152u, 6642978682516671743u, 17230443782969840528u, 12156534523779525796u, 1989151790783919051u, ++ 6263731030979658865u, 16556202624882645790u, 11702894419100492842u, 1245039440087595845u, 3260040617806076482u, 11390642587947386157u, 15688795063501830681u, 7680756410435167606u, ++ 11622868312827688983u, 1324891275238549368u, 6181348207440451660u, 16638201170595874595u, 15752600435501016612u, 7616209416359311691u, 3321489341258335871u, 11328242235714328848u, ++ 3131865515489829432u, 10977756817953029463u, 16137146508898304611u, 7844397531750915340u, 5811434156413844491u, 16395372229761246052u, 11827132964039220304u, 1660744670629167935u, ++ 15913214326271352414u, 8068573254449152305u, 2905717078206922245u, 11204220263579804010u, 12035829987123708013u, 1452858539103461122u, 6017914993561854006u, 16189773752444600153u, ++ }, { ++ 0u, 6118555238288912653u, 12237110476577825306u, 18247330833359770391u, 13942380710360636081u, 10778293617712507836u, 7543452712389327019u, 4343374206906190246u, ++ 1162559746622204903u, 4957131115480832746u, 13398436261328603645u, 17084888254066768112u, 15086905424778654038u, 9634902877839851611u, 8686748413812380492u, 3198961161184305729u, ++ 2325119493244409806u, 8407378615347160771u, 9914262230961665492u, 15960741045388068057u, 16229058527915052415u, 13101053971319389298u, 5254506258681524069u, 2018377927885299304u, ++ 3487552142959377449u, 7246080283574668580u, 11075676491871100467u, 14798208821638459198u, 17373496827624760984u, 11957750539307177877u, 6397922322368611458u, 873845550624159119u, ++ 4650238986488819612u, 1468611264581623441u, 16814757230694321542u, 13669406796222545035u, 9364600845881799981u, 15356367945216001056u, 2893367039927949111u, 8993183146101597754u, ++ 5812680741028562043u, 307286854339917174u, 17976181078471403105u, 12506848973898782572u, 10509012517363048138u, 14213073068277772231u, 4036755855770598608u, 7848658706446142941u, ++ 6975104285918754898u, 3757679901787621727u, 14492160567149337160u, 11382574084698991429u, 11651310343450272483u, 17679087685142107118u, 604386294999662841u, 6668229816820511220u, ++ 8137636784695169973u, 2596263716583940792u, 15653459723670892975u, 10220140060479144098u, 12795844644737222916u, 16535671346696648713u, 1747691101248318238u, 5523790692630174227u, ++ 9300477972977639224u, 15418239225476001333u, 2937222529163246882u, 8947075512310451247u, 4642267913777087881u, 1478833794519692420u, 16842993350473770899u, 13643422681269376670u, ++ 10462937938231096543u, 14256895642581861842u, 4098594218943518405u, 7784568886045304776u, 5786734079855898222u, 335485660068962147u, 17986366292203195508u, 12498915352811683193u, ++ 11625361482057124086u, 17707288688936286715u, 614573708679834348u, 6660293997941431265u, 6929031904881267271u, 3801500275841901386u, 14553996732492558429u, 11318486464284246352u, ++ 12787875770090627857u, 16545891676414235164u, 1775925023235784971u, 5497808777625382918u, 8073511711541197216u, 2658137194938402989u, 15697317412892285882u, 10174030228858301111u, ++ 13950208571837509796u, 10768213751408296361u, 7515359803575243454u, 4369215658492879795u, 64266086328445461u, 6056541296517372696u, 12193111774187735055u, 18293581128395077890u, ++ 15112713823828466499u, 9606842886146402894u, 8676701462472931673u, 3206755967968430164u, 1208772589999325682u, 4913169729330573567u, 13336459633641022440u, 17149116886581154533u, ++ 16275273569390339946u, 13057090384914568807u, 5192527433167881584u, 2082608760381092989u, 2350925692077440475u, 8379320821714095318u, 9904217479574233025u, 15968533654375526092u, ++ 17437760713698643085u, 11895738795633802624u, 6353925819959930519u, 920093647833407386u, 3495382202496636476u, 7235998217053677361u, 11047581385260348454u, 14824052473177163051u, ++ 10447068876609200373u, 14128364157388739064u, 4118967294799201007u, 7908597456515216354u, 5874445058326493764u, 391603411424480073u, 17894151024620902494u, 12447300791057279315u, ++ 9284535827554175762u, 15289779793358354975u, 2957667589039384840u, 9071030930460645381u, 4729911307347480995u, 1535020299074674862u, 16750846767572792249u, 13591740465559749300u, ++ 12735909365018523451u, 16453465302197274166u, 1832394617641637153u, 5585730863000118316u, 8197188437887036810u, 2678299164963691655u, 15569137772090609552u, 10158372272797335197u, ++ 11573468159711796444u, 17614790262716542417u, 670971320137924294u, 6748289234561093579u, 7052776217202099821u, 3821593491595032416u, 14425748405936874615u, 11302896163253294458u, ++ 15020497008676966249u, 9555230900528283236u, 8764415362900159859u, 3262871967819308158u, 1229147417359668696u, 5037195377843840213u, 13320587995882862530u, 17020586948957226703u, ++ 13858063809762534542u, 10716528681989657987u, 7603000551683802772u, 4425403642365261721u, 84709666887204415u, 6180499360129388338u, 12177172482473303077u, 18165119875451415848u, ++ 17309582619392432295u, 11880078264510294442u, 6477599625422879421u, 940257368289594288u, 3551850046471569942u, 7323923223311315739u, 10995617555250765836u, 14731624552464748801u, ++ 16147023423082394432u, 13041502936518885965u, 5316274389876805978u, 2102700497890566231u, 2407324781779167729u, 8467313413945678076u, 9852321304593615851u, 15876037047908055782u, ++ 1291018766690942925u, 4973072573440528064u, 13274480430592564695u, 17064442507263798490u, 15030719607150486908u, 9547259896855319665u, 8738431316985759590u, 3291108156134209131u, ++ 128532172656890922u, 6134424711959717159u, 12113082593034745392u, 18226958170089932605u, 13886262546419256987u, 10690581952315096982u, 7595066862094806145u, 4435588787024731532u, ++ 3580050981226981379u, 7297974293382715662u, 10987681667836234265u, 14741811897106152212u, 17353402924945863346u, 11834005814401532863u, 6413511935936860328u, 1002093465131966885u, ++ 2417545179998651364u, 8459344608371405545u, 9826339458661147134u, 15904271038397419763u, 16208896970474576213u, 12977377931899316312u, 5270164626790366031u, 2146558256149678658u, ++ 5864365122984562769u, 399431204366950748u, 17919992407673188939u, 12419207813205476166u, 10385054866335763168u, 14192630174644861933u, 4165217520762185978u, 7864598685623228919u, ++ 4701851384154880950u, 1560828767195761339u, 16758641643428190636u, 13581693582721149089u, 9240574510442684679u, 15335992705270927370u, 3021896290089222941u, 9009054371811832336u, ++ 8153224920554538911u, 2724514274940876434u, 15633368673088300421u, 10096393516356015240u, 12707851639919861038u, 16479271570068024355u, 1840187295666814772u, 5575686180147088953u, ++ 6990764404993272952u, 3885857308630146421u, 14471996434107354722u, 11258899592309161839u, 11563386024119531209u, 17622620253752952772u, 696814903175779539u, 6720194058879067614u, ++ }, { ++ 0u, 4542972359516777931u, 9085944719033555862u, 4691664355513513565u, 18171889438067111724u, 14061474303606774503u, 9383328711027027130u, 13633424072306524529u, ++ 7676286055365832925u, 6164376987427609878u, 1481798532234586955u, 3142253189322229376u, 10855962452864321521u, 12223826156538735162u, 16771372852738792551u, 15543052108730888620u, ++ 15352572110731665850u, 16862791698018765937u, 12328753974855219756u, 10669987536837040103u, 2963597064469173910u, 1597421751597874013u, 6284506378644458752u, 7511137813735006411u, ++ 13801544397233820007u, 9260261528098962604u, 13951919735851666161u, 18344511890033026874u, 4874982405016790603u, 8983709158270585728u, 4445237816650825181u, 196831773885239318u, ++ 4091022007653359089u, 562346998784700474u, 5103132815620245095u, 8780357948041161644u, 14189083196432476893u, 18150173592266475286u, 13474345022262784331u, 9652793049543924864u, ++ 5927194128938347820u, 7875246409875505383u, 3194843503195748026u, 1395478681687169905u, 12569012757288917504u, 10477056948030502859u, 15022275627470012822u, 17253916197967211613u, ++ 17134349580696108107u, 15186860751721288064u, 10655150290339489757u, 12453952663903504918u, 1289987737384422247u, 3381381201708377772u, 8066289525279445233u, 5835212509754572090u, ++ 9749964810033581206u, 13278076374523191645u, 17967418316541171456u, 14290755639648123595u, 8890475633301650362u, 4929947589851190897u, 393663547770478636u, 4214651972966108647u, ++ 8182044015306718178u, 5658655167774316073u, 1124693997569400948u, 3499391957275839935u, 10206265631240490190u, 12873559114121502981u, 17560715896082323288u, 14753743294414502547u, ++ 1948880861322201919u, 2594127930539943668u, 7285718382500778153u, 6491924633276939618u, 16655531858934856723u, 15577868310755742168u, 11039333611388512133u, 11977453108914408014u, ++ 11854388257876695640u, 11207451878732806035u, 15750492819751010766u, 16545974958769302533u, 6389687006391496052u, 7469038772501250239u, 2790957363374339810u, 1851148384058628905u, ++ 14845159798643632773u, 17370237963685480270u, 12687582131971748115u, 10311195790054169816u, 3615017233668480425u, 946035540305899618u, 5493509258033841727u, 8302171348940565492u, ++ 5281120895271462419u, 8521283507583323096u, 3989500891288354181u, 600787064567550030u, 13071075951463747903u, 9974957613568212212u, 14659789384177486505u, 17616368207971182434u, ++ 2579975474768844494u, 2073357103652371205u, 6762762403416755544u, 7120694423275413651u, 16132579050558890466u, 16206641305794825257u, 11670425019509144180u, 11456679111066785727u, ++ 11260412520859862953u, 11767594448091671138u, 16308316081471249471u, 15949821717821010420u, 6947506857025941637u, 6872882154850049358u, 2196985003345963795u, 2411294364755134168u, ++ 17780951266603300724u, 14540225107906894527u, 9859895179702381794u, 13249171359945539881u, 787327095540957272u, 3884007889973030291u, 8429303945932217294u, 5472161678768272901u, ++ 16364088030613436356u, 15858029804260760079u, 11317310335548632146u, 11674676600264311193u, 2249387995138801896u, 2322888996435045667u, 6998783914551679870u, 6785602652076537525u, ++ 9916730820443375385u, 13156333278251739858u, 17836661041797717135u, 14448512960480194884u, 8480501340405739573u, 5384944246861192702u, 839650424281590691u, 3795664592519366248u, ++ 3897761722644403838u, 656471011406904245u, 5188255861079887336u, 8578093388688728099u, 14571436765001556306u, 17668683201823263897u, 12983849266553879236u, 10026146741872662287u, ++ 6669836397870376611u, 7177582867921406824u, 2488175334770097461u, 2129119614032302334u, 11583119667977343375u, 11507929313807383620u, 16044147764761037337u, 16259017374083049426u, ++ 15843330937415051829u, 16489139217633298430u, 11946100509993103779u, 11151742071862860904u, 2878174689517968665u, 1799951022334374098u, 6478030266801178255u, 7416715545229372228u, ++ 12779374012782992104u, 10255423946675697443u, 14938077545002500478u, 17313340186040954037u, 5581914726748679620u, 8249768321177223183u, 3702296768117257810u, 894758378090191769u, ++ 1067805515879173007u, 3592318064290702916u, 8126281399163064345u, 5750455340522077650u, 17509465798031703203u, 14841048614271029608u, 10153889598922762037u, 12961990299524614910u, ++ 7230034467336960850u, 6583663697231173273u, 1892071080611799236u, 2686992928761285903u, 10987018516067683454u, 12065805765134311861u, 16604342697881130984u, 15665095101429070371u, ++ 10562241790542924838u, 12510858718452294125u, 17042567015166646192u, 15242640940723501691u, 7979001782576708362u, 5886480219318720193u, 1201574129135100060u, 3433774845539634519u, ++ 17875696825445760251u, 14346457162030502192u, 9657117384671061869u, 13334903762452155046u, 305328503063841751u, 4266984645440464412u, 8803266454141587521u, 4981154328058445194u, ++ 5159950949537688988u, 8687502257518297175u, 4146714207304742410u, 470617173809470401u, 13525524806833511088u, 9565558111887030139u, 14241388846550827302u, 18061812720343526637u, ++ 3250597773715660097u, 1303669193657626762u, 5984074333724313303u, 7782311056298339100u, 15074661043719826029u, 17165493152098584486u, 12620272307991097851u, 10389759836427934768u, ++ 12273052416502600151u, 10761709128327461916u, 15295744618112993857u, 16955639155056813962u, 6232173811933554427u, 7599472825692375856u, 2912390363305901421u, 1684630829289181350u, ++ 13895013714051883274u, 18437420284065877185u, 13745764309700098716u, 9352044056584181591u, 4393970006691927590u, 284119552558480365u, 4822588729510268336u, 9072122871209877627u, ++ 9177754244107333741u, 4635909983525117350u, 92935459340889083u, 4486092121981797936u, 9471751652205676353u, 13581038687731985034u, 18259186513699183831u, 14010214853299335452u, ++ 1574654191081914544u, 3085435160094502267u, 7768015779946060582u, 6108684823746459373u, 16858607891864434588u, 15491872287116188247u, 10944323357536545802u, 12171520400656925121u, ++ }, { ++ 0u, 2156813408461955548u, 4313626816923911096u, 2752718492472304228u, 8627253633847822192u, 7661928252530632364u, 5505436984944608456u, 5875429064940414228u, ++ 17254507267695644384u, 17481523150583344956u, 15323856505061264728u, 14503785508944014468u, 11010873969889216912u, 9592933115173218380u, 11750858129880828456u, 13762408288327199732u, ++ 5489899806547772229u, 5899293950881604249u, 8641596751236382973u, 7639112309309301025u, 4290280838231655477u, 2766522915734824425u, 24548853041579917u, 2141951263632483921u, ++ 11764625126767791525u, 13739024951972572281u, 10995904098661322269u, 9617374173086412737u, 15347829100153899733u, 14488356108428585737u, 17231728733602892141u, 17495903608387299505u, ++ 10979799613095544458u, 9623805157521532758u, 11798587901763208498u, 13714458609834648814u, 17283193502472765946u, 17452775347443867686u, 15278224618618602050u, 14549338234851124126u, ++ 8580561676463310954u, 7708699370463537590u, 5533045831469648850u, 5847881786764880398u, 49097706083159834u, 2107935609010204358u, 4283902527264967842u, 2782645096555375998u, ++ 15298762408106657231u, 14537220494637179923u, 17261466032775972471u, 17465946411177207723u, 11811312492909331135u, 13692276008895521635u, 10968273481005252871u, 9644925621600215259u, ++ 4261616546501692207u, 2795266376586341107u, 70185227798988951u, 2096376465831291211u, 5520961050865536095u, 5868452604588535171u, 8593836137267777511u, 7687075229128879675u, ++ 11680230827506930577u, 13832259058284016205u, 11080421551794245673u, 9523735455073038837u, 15394057194608301281u, 14432953972299937085u, 17185658977434064729u, 17550865948466574981u, ++ 5579070418531851633u, 5801301123735731373u, 8552830750928559817u, 7736981982542757653u, 4239857041646656001u, 2826138345940532189u, 75412445699561913u, 2082177495183685733u, ++ 17161123352926621908u, 17565732457015587080u, 15417398740927075180u, 14419136389292487344u, 11066091662939297700u, 9546555762013386360u, 11695763573529760796u, 13808381012597372352u, ++ 98195412166319668u, 2067810197125185512u, 4215871218020408716u, 2841563382736944208u, 8567805054529935684u, 7712554084374493336u, 5565290193110751996u, 5824680096370817824u, ++ 4213277561403610395u, 2852497928146826439u, 118647349622822563u, 2038740285422565247u, 5603244184571253355u, 5777048188553278391u, 8511711324634206675u, 7778039831901335567u, ++ 15351860113773370363u, 14475212630091872807u, 17208772955998935107u, 17527831139023518111u, 11724816064851319947u, 13787876126790335831u, 11055209722282565427u, 9549167182608629487u, ++ 8523233093003384414u, 7756906139291137922u, 5590532753172682214u, 5799235221864313914u, 140370455597977902u, 2025555993157185778u, 4192752931662582422u, 2864620100732154698u, ++ 11041922101731072190u, 9570786891571902818u, 11736905209177070342u, 13767318537498720986u, 17187672274535555022u, 17539385849830522386u, 15374150458257759350u, 14462604578592423338u, ++ 15486092620961298855u, 14629711868178897019u, 17092483903335922207u, 17355247692313779139u, 11624791503456485079u, 13600030943165030155u, 11137009302703308143u, 9754815117126884531u, ++ 4151744643171039047u, 2626583331457439387u, 162377516962444543u, 2282879863086044451u, 5631712546292871223u, 6037452326221451755u, 8501327171535303567u, 7499692239708246611u, ++ 11158140837063703266u, 9743299917872012094u, 11602602247471462746u, 13612749016692676742u, 17105661501857119634u, 17333526894853233742u, 15473963965085515306u, 14650238604571402230u, ++ 8479714083293312002u, 7512977616177960414u, 5652276691881064378u, 6025361010828170854u, 150824891399123826u, 2303974039851176622u, 4164354990367371466u, 2604286280411140374u, ++ 5659250822143950637u, 6009834889821986545u, 8454565055791594645u, 7546392787102457161u, 4121809449076176989u, 2656298618920900993u, 211263906290727909u, 2233791159333640761u, ++ 11672732454520566221u, 13552292306546298897u, 11106145987650286197u, 9785898338790069161u, 15440531030182573757u, 14675335027319969633u, 17121240571213837573u, 17326570184971408601u, ++ 196390824332639336u, 2258328937796115892u, 4135620394250371024u, 2632959299571932684u, 8431742436040817432u, 7560729365405768388u, 5683126765473888416u, 5994308631384381820u, ++ 17135610109059871368u, 17303780593489122132u, 15425108168748986672u, 14699314298944934124u, 11130580386221503992u, 9770921945649714212u, 11649360192741635648u, 13566070240564762524u, ++ 8426555122807220790u, 7574959341548112874u, 5704995856293652878u, 5963537623700588626u, 237294699245645126u, 2208312048661695642u, 4077480570845130494u, 2700071425513574178u, ++ 11206488369142506710u, 9686112028953249034u, 11554096377106556782u, 13670376701660284594u, 17023422649268413350u, 17424940338905547386u, 15556079663802671134u, 14559229772221530562u, ++ 4089596066908350835u, 2679540256679954607u, 224121464376355531u, 2230046074588744471u, 5727171952466636291u, 5950815117732351967u, 8405427952099257787u, 7586487769270013031u, ++ 15543464952953907091u, 14581513594800801359u, 17034988434643772459u, 17403850594581005815u, 11533527867866456291u, 13682454788587061567u, 11228114617197060955u, 9672831084924650119u, ++ 17046466186006768828u, 17401835225210195296u, 15513812278582275844u, 14601417988320120536u, 11181065506345364428u, 9711332585899690512u, 11598470443728627828u, 13625782737014311336u, ++ 280740911195955804u, 2165085734748128128u, 4051111986314371556u, 2726642315882184760u, 8385505863325164844u, 7616087770173211888u, 5729240201464309396u, 5939354855465699144u, ++ 11574598932837183481u, 13641322155266051621u, 11203874897631210561u, 9696991643941850525u, 15500005765847099529u, 14624770467483748693u, 17061326039500450609u, 17377293083093715693u, ++ 5752625691707646233u, 5925581285101240517u, 8361067032314929825u, 7631051003498906493u, 4066548076212889193u, 2702667407911749557u, 266366940911429073u, 2187862166416278541u, ++ }, { ++ 0u, 6642096280510406750u, 13284192561020813500u, 16462795876764246242u, 16315823105410768893u, 13708963636559134627u, 6500836570635362113u, 439922346977066783u, ++ 6197597939812213119u, 733872460607717665u, 17174658310779658691u, 12859417258165748125u, 13001673141270724226u, 16736026809386770140u, 879844693954133566u, 5771540452186644064u, ++ 12395195879624426238u, 17305613297699152544u, 1467744921215435330u, 5220531075568771612u, 5650300446275329283u, 1316336633116425565u, 17740532779662220735u, 12258375912742239713u, ++ 18016332033719362433u, 11973850846087693279u, 4781749989466252093u, 2193612730179060579u, 1759689387908267132u, 4919860766213921826u, 11543080904373288128u, 18166453874549300382u, ++ 14614610554166352761u, 10879836598703668007u, 8253805222095936453u, 3361408799105547163u, 2935489842430870660u, 8399638907315561690u, 10441062151137543224u, 14757009366268798054u, ++ 11300600892550658566u, 13906759146888600152u, 2632673266232851130u, 8693166652788693732u, 9132946036408395259u, 2491556468171146661u, 14331668736193815879u, 11153489555886392601u, ++ 7409848711186274695u, 4249257595424012761u, 16037314857127418171u, 9413239572791867749u, 9563499978932504186u, 15606406401646028324u, 4387225460358121158u, 6976068332272625304u, ++ 3519378775816534264u, 7852640824571713702u, 9839721532427843652u, 15321459211647031322u, 15184496315767285509u, 10274783960564057947u, 7701371084599273401u, 3949009615571978215u, ++ 539203352115488887u, 6581683165424715817u, 13772373076031531211u, 16360516657443457173u, 16507610444191872906u, 13347445937900984276u, 6722817598211094326u, 99441604310980456u, ++ 5870979684861741320u, 960568039155968342u, 16799277814631123380u, 13046489736199563754u, 12904108438562707189u, 17238069777753355947u, 814716683761407561u, 6296880972452001303u, ++ 12357655745765665417u, 17821378201246059223u, 1379747099228580405u, 5694995023857257067u, 5265346532465702260u, 1530999186474390826u, 17386333305577387464u, 12494636173022434710u, ++ 18265892072816790518u, 11623803214076996520u, 4983112936342293322u, 1804507146630605588u, 2238305212630619147u, 4845162757404030037u, 12054694172541097143u, 18115614168568345833u, ++ 14819697422372549390u, 10486441695742104400u, 8498515190848025522u, 3016776137306395628u, 3442815973027425523u, 8352525304506551469u, 10925090729870978127u, 14677459070913039377u, ++ 11216336045685248625u, 14376925237369287215u, 2590274523633996493u, 9214355580338500243u, 8774450920716242316u, 2731551919773330898u, 13952136664545250608u, 11363291318662491502u, ++ 7038757551633068528u, 4432606169309893038u, 15705281649143427404u, 9644785238863483154u, 9494645848386137613u, 16136034042300943955u, 4294513027018469041u, 7472698529450626799u, ++ 4011857131457007759u, 7746628612951437521u, 10373500843358195763u, 15265904688119197805u, 15402742169198546802u, 9938598876682809132u, 7898019231143956430u, 3582070091934478224u, ++ 1078406704230977774u, 5970139571501035696u, 13163366330849431634u, 16897748309796073484u, 17049000381336047379u, 12733717820530814797u, 6107119981172920239u, 643361792051163121u, ++ 6410046491609887121u, 349161128571523535u, 16190407203032477997u, 13583585392940618099u, 13445635196422188652u, 16624205252526067250u, 198883208621960912u, 6840937431151644302u, ++ 11741959369723482640u, 18365299631022420558u, 1921136078311936684u, 5081265949533565682u, 4656338829252136429u, 2068229881835728307u, 17925537898651110737u, 11883093821164285199u, ++ 17650059563187254127u, 12167860639460954929u, 5524638460789093331u, 1190641388963713933u, 1629433367522815122u, 5382257181810330828u, 12593761944904002606u, 17504208224571739248u, ++ 14134199920450915223u, 10956049054195313609u, 8970094247992396587u, 2328741787718953845u, 2759494198457160810u, 8819954874021999668u, 11389990047714514134u, 13996106797082358920u, ++ 10530693064931404520u, 14846677937748691638u, 3061998372948781652u, 8526176301674629642u, 8091274350704555285u, 3198835872954668363u, 14416890915810522537u, 10682083699634542071u, ++ 7503655637611612521u, 3751252662574033207u, 15021960841764981205u, 10112215774463453579u, 9966225872684586644u, 15448000658827392714u, 3609014293261211176u, 7942304654960916086u, ++ 4476610425261238294u, 7065420035288041544u, 9690325514808060074u, 15733189881789008116u, 15874467260079749099u, 9250420838410950581u, 7212375292832610135u, 4051821833783301897u, ++ 688179623118076057u, 6170372224719608007u, 12814440204992854053u, 17148438651140642939u, 16997030381696051044u, 13244209591132604218u, 6033552274612791256u, 1123099122930255750u, ++ 6885631946054851046u, 262293608834169272u, 16705050609013102938u, 13544914965422553348u, 13683025758949262875u, 16271127284595091013u, 412415468322195111u, 6454862019777308409u, ++ 11927910341603441255u, 17988788832627006009u, 2148953154424896219u, 4755777988240824965u, 5180549047267992986u, 2001980365486523844u, 18428711160677000486u, 11786650616022549880u, ++ 17548901841432484632u, 12657171448130714438u, 5463103839546661796u, 1728714438829439994u, 1290082918514197733u, 5605359706950509755u, 12231113943998710873u, 17694874057198724103u, ++ 14077515103266137056u, 11488706867561743294u, 8865212338619786076u, 2822341649514070786u, 2391433177253116957u, 9015472726907116611u, 11054926469989481633u, 14215482952762858751u, ++ 10763369033251996319u, 14515766235920655041u, 3244216653174833699u, 8153963644554617469u, 8589026054036938082u, 3107253741862419772u, 14945397058901253598u, 10612099275430968704u, ++ 8023714262914015518u, 3707732413820797248u, 15493257225902875042u, 10029072425162228220u, 10174906129304731363u, 15067338284929851069u, 3850131242430201439u, 7584939832928591361u, ++ 4133108057121652833u, 7311251501606674495u, 9295800309597257949u, 15937155243838988419u, 15796038462287912860u, 9735579710801330114u, 7164140183868956448u, 4558017662132191102u, ++ }, { ++ 0u, 7026975924517234630u, 14053951849034469260u, 11713158812725061706u, 1498566550037692829u, 8453026741656872539u, 15547077823203331601u, 13134332388348864983u, ++ 2997133100075385658u, 5193532126013515004u, 16906053483313745078u, 10023477084983765872u, 4421425403924087463u, 6690338751863514465u, 18326734871926164779u, 11516110084014746349u, ++ 5994266200150771316u, 3651077923391955378u, 10387064252027030008u, 17411644826573123134u, 5180286430728521705u, 2765428220391841839u, 9578516152858789989u, 16530863678517358499u, ++ 8842850807848174926u, 1962664170658947720u, 13380677503727028930u, 15579466327313067268u, 7958959654645957843u, 1150444288916906773u, 12500388506175163231u, 14771411239789669529u, ++ 11988532400301542632u, 14401112944851970862u, 7302155846783910756u, 347530691846251682u, 12867955000885349749u, 15208934917731379891u, 8186843028093092601u, 1160054057126929727u, ++ 10360572861457043410u, 17171366937719040020u, 5530856440783683678u, 3262112454209283992u, 11170013709381963343u, 18052407625221859721u, 6344013830343901635u, 4147432248901248517u, ++ 17685701615696349852u, 10733466276663946586u, 3925328341317895440u, 6340298665266291414u, 16265807495604570881u, 9241127928571882695u, 2500178400086410381u, 4843267757373072203u, ++ 15917919309291915686u, 13646779991004769888u, 2300888577833813546u, 9109287431904666092u, 14423962049646856251u, 12225267820500938749u, 803223682168014775u, 7683504840782913649u, ++ 16025789128531904341u, 13827140552201887891u, 2120809441137969369u, 9001136188144267039u, 14604311693567821512u, 12333148557000565006u, 695061383692503364u, 7503436758785666690u, ++ 17866059964468495471u, 10841338299774886825u, 3817174930229677027u, 6160221704524114981u, 16373686056186185202u, 9421479739856314932u, 2320108114253859454u, 4735107671358188984u, ++ 10180636633891078433u, 17063072784830850791u, 5638869205660782253u, 3442330069771397483u, 11061712881567367356u, 17872478072565786490u, 6524224908418567984u, 4255451551249279222u, ++ 11880240423364919835u, 14221174549956093405u, 7482375666214882711u, 455541244296276561u, 12688027660687803270u, 15100631886079386688u, 8294864497802497034u, 1340262959281482700u, ++ 8662912472460168125u, 1854372134182743163u, 13488687978245964849u, 15759686224643400695u, 7850656682635790880u, 970516889046347238u, 12680597330532582828u, 14879432787265004138u, ++ 5885971969496909959u, 3471141773623390017u, 10567281927262422795u, 17519657531808653517u, 5000356800172820762u, 2657127470508076764u, 9686535514746144406u, 16711074697083887952u, ++ 3105005063510429129u, 5373890534425651727u, 16725976600334615109u, 9915323596096578947u, 4601777155667627092u, 6798217371950640018u, 18218574863809332184u, 11336039720248747038u, ++ 180360639130832627u, 7134845665859430709u, 13945800545768817023u, 11533079735570376377u, 1606447364336029550u, 8633376307814525096u, 15367009681565827298u, 13026170149548992292u, ++ 3321048140255203375u, 5733767250183223273u, 17086394267351834531u, 10131907641284540517u, 4241618882275938738u, 6582455852881933940u, 18002272376288534078u, 10975340495589554680u, ++ 540800415553098517u, 7351451582082282707u, 14161821513074465945u, 11892934580260027231u, 1390122767385006728u, 8272655212095272270u, 15006873517571333380u, 12810430501506267842u, ++ 9023334491325470299u, 2070960623556915613u, 13704726720259086807u, 16119558478964112913u, 7634349860459354054u, 609813203025260544u, 12320443409048229962u, 14663675712440713100u, ++ 6101997361665611105u, 3831000989484282535u, 10927717295939115757u, 17736259059608567083u, 4640216228507718908u, 2441383434118427450u, 9470215342716377968u, 16350357972595129526u, ++ 9820495924665654471u, 16847328885758262017u, 5422549171225416523u, 3081613207998608525u, 11277738411321564506u, 18232337151134792348u, 6884660139542794966u, 4472053216375158032u, ++ 11663933463862517757u, 13860471001487472699u, 7122221882022416497u, 239784031886489527u, 13048449816837135968u, 15317220237859158438u, 8510903102498558444u, 1700135351162517034u, ++ 15809464669166377651u, 13466419319190748533u, 1760673139591009599u, 8785396677427507961u, 14964751332429765422u, 12549754610540477672u, 911082488592553122u, 7863291466191287140u, ++ 17505901828360837513u, 10625576643111779919u, 3600872305391818245u, 5799522617425244611u, 16589728995604994068u, 9781356593166352338u, 2680525918562965400u, 4951691578960654430u, ++ 17325824944920336250u, 10517423154702741692u, 3708744268365486326u, 5979881026315534128u, 16481568986909349607u, 9601286230029496609u, 2860877669727689067u, 5059570199676927661u, ++ 15701313365271581760u, 13286340242614875014u, 1941033778092694476u, 8893266419348519946u, 14784683190314112477u, 12441592372201976347u, 1018963302412737105u, 8043641032810315159u, ++ 11771943938993819918u, 14040690898222216904u, 6942283547246780034u, 131491994814691652u, 13228658641689481363u, 15425241784889898837u, 8402600130983321375u, 1520207950847359193u, ++ 10000713600345641524u, 16955341590498866674u, 5314254941016153528u, 2901677057735113342u, 11385757773804508073u, 18412548169088955503u, 6704730509582687269u, 4363752465879022563u, ++ 6210010127020858258u, 4011218604585024596u, 10747781068851303454u, 17627964906259002328u, 4820427307211528719u, 2549402735887646153u, 9361914515530929539u, 16170428419360240197u, ++ 9203554311335254184u, 2178971175377796974u, 13596434743901280036u, 15939620083439087842u, 7742371330630129973u, 790022104701665011u, 12140516069312059065u, 14555372680310567295u, ++ 360721278261665254u, 7243300338934250016u, 14269691331718861418u, 12073295142069515692u, 1281960468464901243u, 8092587130592951229u, 15187223161047700471u, 12918311238500824113u, ++ 3212894728672059100u, 5553690289885640986u, 17266752615629050192u, 10239779664840078998u, 4061548595831021377u, 6474295767462639751u, 18110150936257777869u, 11155692307469580043u, ++ }, { ++ 0u, 2517245393515406572u, 5034490787030813144u, 7435750759411199284u, 10068981574061626288u, 12201157653998401372u, 14871501518822398568u, 17045318164640841348u, ++ 9628913577918544357u, 12056075433989135625u, 13870769438669140029u, 16326061061730899153u, 1016952077871524437u, 3239211695253081785u, 5459183210385793933u, 7578968205522831201u, ++ 11067918171351838031u, 13508029996328618403u, 15872723984458359959u, 18349972777811820667u, 1307470557354262271u, 3515654148887976467u, 6339673239971903271u, 8436375012170683339u, ++ 2033904155743048874u, 4528066323082129478u, 6478423390506163570u, 8865607338129291678u, 10918366420771587866u, 13072499669943034870u, 15157936411045662402u, 17344703028974807598u, ++ 11667391723826758683u, 9441211325989495031u, 16444045520167767491u, 14329311757255665967u, 3050858413050517419u, 628778578755597127u, 8036894684654706291u, 5577642697640442527u, ++ 2614941114708524542u, 478839856218937618u, 7031308297775952934u, 4862538486186004682u, 12679346479943806542u, 10167187506301176482u, 16872750024341366678u, 14467534086004917114u, ++ 4067808311486097748u, 1917635425212288440u, 9056132646164258956u, 6864284009665987680u, 12956846781012327140u, 10457633378212404744u, 17731214676258583356u, 15347951510183778256u, ++ 13678285260964991153u, 11474057634298917981u, 17873974704293108073u, 15772186515461651845u, 3922409453435093761u, 1477250791027468269u, 8336488571297909465u, 5863164957556321845u, ++ 15063804914172139187u, 17573731408537121375u, 10724047561790938987u, 13131499433903012743u, 6535100908406441219u, 8673469987586793967u, 2265113888856263899u, 4431612735036172343u, ++ 6101716826101034838u, 8521560882533092282u, 1257557157511194254u, 3719041779816530530u, 16073789369309412582u, 18302240886422657034u, 11155285395280885054u, 13267751491267498450u, ++ 5229882229417049084u, 7672809353916620560u, 957679712437875236u, 3433240205686757064u, 14062616595551905868u, 16269110787469675680u, 9725076972372009364u, 11824592944582215032u, ++ 14786588404820918809u, 17283564772171425525u, 9865866699426761665u, 12251361247433944877u, 5082513026899726761u, 7234957975966594373u, 240568853608110193u, 2430150771060047005u, ++ 8135616622972195496u, 5911125624750880324u, 3835270850424576880u, 1717722887501053852u, 18112265292328517912u, 15687370158510810612u, 13728568019331975360u, 11271004332422294572u, ++ 17674167644946721613u, 15539754686561718177u, 12725302718847165077u, 10553717607734429305u, 9150035367232403709u, 6635062193578351633u, 4261933579054297381u, 1858407040333796809u, ++ 16825062113507622887u, 14668696227990231819u, 12439147139764057663u, 10254616302904316627u, 7116415003206659159u, 4624520499557157051u, 2818284765131990415u, 428829699325493603u, ++ 7844818906870187522u, 5634399380472423150u, 2954501582054936538u, 860032292373900086u, 16672977142595818930u, 14235136279826723166u, 11726329915112643690u, 9246813302127474822u, ++ 3513487962258617315u, 1309817375275636495u, 8438743075148003899u, 6337546835477044951u, 13510341259434958931u, 11065716548023207103u, 18347741267953084811u, 15874986514718330215u, ++ 13070201816812882438u, 10920562880461237994u, 17346939975173587934u, 15155660198108440370u, 4530227777712527798u, 2031571415669472602u, 8863225470072344686u, 6480554254231811202u, ++ 12203433652202069676u, 10066744842596399680u, 17043121765066184564u, 14873799311837557656u, 2515114315022388508u, 2382082824317424u, 7438083559633061060u, 5032329272252129320u, ++ 3241337884980569929u, 1014584229661574053u, 7576621447749742225u, 5461349336866867837u, 12053812688995611897u, 9631145302510833685u, 16328262745174523169u, 13868458115447806413u, ++ 10459764458834098168u, 12954464700354433812u, 15345618707833241120u, 17733376188870843084u, 1915359424875750472u, 4070045040789094564u, 6866480411373514128u, 9053834855311329660u, ++ 1479513538183220765u, 3920177730975673073u, 5860963271950469061u, 8338799892386374441u, 11471931442405006765u, 13680653107046267201u, 15774533275401163893u, 17871808579940708505u, ++ 626467317811485367u, 3053060038512016987u, 5579874205336949615u, 8034632152261867395u, 9443377510452431111u, 11665044903776710123u, 14326943696444768479u, 16446171926791300147u, ++ 10165026053799453522u, 12681679222183806910u, 14469915951933188746u, 16870619158449294950u, 481137707216220386u, 2612744652856644622u, 4860301542120094010u, 7033584512875404758u, ++ 16271233245944390992u, 14060243759811248572u, 11822251249501760648u, 9727246909562751076u, 7670541700849153760u, 5232109988680716812u, 3435445775002107704u, 955373222128557012u, ++ 7237229143405862069u, 5080272407415421017u, 2427958334666397037u, 242871556844564865u, 17281429885116092165u, 14788965422804986857u, 12253699033039161053u, 9863708918048465457u, ++ 8671167069616523295u, 6537293559533907187u, 4433853414635209159u, 2262842661302265131u, 17575888975148309423u, 15061467343334031171u, 13129122476067492471u, 10726182388697724571u, ++ 18300070734464807418u, 16076131279156974870u, 13270124387156703266u, 11153162876657622222u, 8523867158108594762u, 6099511471519499942u, 3716814080667593618u, 1259824750463930238u, ++ 4622362935074513227u, 7118752576211060135u, 431206655032469651u, 2816149936058911871u, 14670999143827763963u, 16822869460218058263u, 10252375625438018339u, 12441418369480155087u, ++ 14232830006413318318u, 16675182499310091330u, 9249040999114314102u, 11724062320027170202u, 5636569530263980830u, 7842476994894082034u, 857659398650987206u, 2956624102806742570u, ++ 15689637813740375044u, 18110037535197587688u, 11268798760944846300u, 13730874507508556080u, 5909003164109873076u, 8137989456584309592u, 1720064584747800172u, 3833100915362378368u, ++ 6637197082762229217u, 9147658351414628621u, 1856069252600036409u, 4264091358266300629u, 15537483516989711953u, 17676408262268928701u, 10555910046260817801u, 12723000017772809061u, ++ }, { ++ 0u, 15762200328042667840u, 2856835172924432389u, 18238190752146915141u, 5713670345848864778u, 10805715811487326026u, 7561135427655163919u, 12848797446532677455u, ++ 11427340691697729556u, 4911321075843194708u, 13345174655120580625u, 7173389830452510545u, 15122270855310327838u, 820654137405644638u, 17760118084036943899u, 3226275954771115867u, ++ 12678913378224905901u, 8451595299172663789u, 9822642151686389416u, 5976168202979041768u, 16194808345499688615u, 4179641502022828519u, 14346779660905021090u, 2135996745225445858u, ++ 3558579666237890233u, 16995468946051088889u, 1641308274811289276u, 14733962144962732540u, 9090961916423626419u, 11859948271085519347u, 6452551909542231734u, 9453764156601606646u, ++ 14785799433083167711u, 1697614691135618207u, 16903190598345327578u, 3470771065211313306u, 9402037001392841685u, 6396285171454065813u, 11952336405958083536u, 9178809987380452496u, ++ 6027971268800324555u, 9878982515431963787u, 8359283004045657038u, 12591138999497481358u, 2084233168694272961u, 14290549069261356161u, 4271993490450891716u, 16282692837778922628u, ++ 7117159332475780466u, 13293411258189767218u, 4999205320339463543u, 11519692655715205687u, 3282616549622578552u, 17811921192019632696u, 732879648334208381u, 15029958398333780541u, ++ 18181923832847252838u, 2805107922438644262u, 15850048426093911395u, 92388385340408355u, 12905103819084463468u, 7612972483059622444u, 10717907374994120041u, 5621392111171994153u, ++ 629311348378851643u, 15133597752622646907u, 3395229382271236414u, 17699378041462564478u, 5183867188229904689u, 11335100742646646385u, 6941542130422626612u, 13469099241846138484u, ++ 10821536956051937583u, 5517832210058282607u, 12792570342908131626u, 7725577015716947562u, 15665448522205731109u, 277059068684322405u, 18357619974760904992u, 2629481737494357600u, ++ 12055942537600649110u, 9075274912216783062u, 9289461107078326163u, 6508930745710590163u, 16718566008091314076u, 3655465612432595164u, 14961454118931310489u, 1522030784741112025u, ++ 4168466337388545922u, 16386289672930760898u, 2196870928291817351u, 14177982363995224263u, 8543986980901783432u, 12406505804242475208u, 5852377756745475981u, 10054645982306597069u, ++ 14234318664951560932u, 2248669261341992356u, 16298510681658284769u, 4076149859246245281u, 9998410640678927086u, 5800610134637962670u, 12494386096293518059u, 8636334373997692331u, ++ 6565233099245157104u, 9341293662428177840u, 8987461698644630261u, 11963660006880118197u, 1465759296668416762u, 14909722918146729402u, 3743309483160705791u, 16810949547632248255u, ++ 7673845564465570889u, 12736298827739970313u, 5610215844877288524u, 10909381007990496012u, 2681314179816367171u, 18413922163761052419u, 184776770680816710u, 15577635352405072646u, ++ 17647610443766686813u, 3338994288425483037u, 15225944966119244888u, 717191546761911064u, 13520897736746902615u, 6997878541721926423u, 11242784222343988306u, 5096087965850491666u, ++ 1258622696757703286u, 14684288965200833846u, 3950222953022231155u, 17036158029906267443u, 6790458764542472828u, 9548224856613104956u, 8762045755503235705u, 11756540858562383161u, ++ 10367734376459809378u, 6151638724996853026u, 12124837022850257511u, 8285082520580115751u, 13883084260845253224u, 1879138195689975080u, 16649556998353834605u, 4445490780332133677u, ++ 13727827248377474267u, 7223104792207356827u, 11035664420116565214u, 4870673773980832670u, 17422178244240010449u, 3131857036752565137u, 15451154031433895124u, 924103331921597332u, ++ 2311784730144877775u, 18062687245331231631u, 554118137368644810u, 15928680121837474698u, 8024872609708797125u, 13105623011270275973u, 5258963474988715200u, 10539833548380279680u, ++ 15872427342139003305u, 502333042764009193u, 18150549824433566124u, 2404114375865757420u, 10596187595637903779u, 5310779519913856739u, 13017861491421180326u, 7932573568563556070u, ++ 4814384572959953341u, 10983915471956430589u, 7310931224865190328u, 13820193315420761848u, 980423156880069047u, 15503004023780282103u, 3044061569482224050u, 17329913425393921778u, ++ 8336932674777091844u, 12181156958151692356u, 6059373863990406913u, 10279938678082531393u, 4393741856583634702u, 16593268045114871886u, 1971504083133951755u, 13970910599835103307u, ++ 17087973961803566864u, 4006576835745435728u, 14591990156772618005u, 1170861220680101973u, 11704755513490951962u, 8705792948709298266u, 9640554597612056351u, 6878321524855255135u, ++ 1858937689852799821u, 14083548048513152013u, 4497338522683984712u, 16489741062169236488u, 6235036951360285511u, 10104345546597921799u, 8152299718492490562u, 12365860697102636034u, ++ 9753200483853429593u, 6765745319621112857u, 11601220269275925340u, 8809399250468705308u, 14416405870873226067u, 1346516287098352659u, 17272668747995384662u, 3821952007586370582u, ++ 13130466198490314208u, 7820039919040899744u, 10492627387899532773u, 5414409408661555877u, 17974923397289260522u, 2579810761044912810u, 16057098401758057967u, 317732763665910447u, ++ 2931518593336833524u, 17442526084696124084u, 1084062204544407025u, 15399436031514938033u, 7486618966321411582u, 13644576356632980158u, 4629793036166665723u, 11168576964637084347u, ++ 15347691128931141778u, 1027777753507534802u, 17534896747071563927u, 3019349226222860247u, 11220431689754577048u, 4686116923914377176u, 13552315720802183325u, 7398828111596124125u, ++ 5362628359632734342u, 10436379358185592774u, 7912374160093407363u, 13218332977821366211u, 369553541361633420u, 16113456511805446092u, 2487515902914439305u, 17887166489985742793u, ++ 8865757316743550527u, 11653040814255671679u, 6677988576850966074u, 9660905738751846778u, 3765703796660934197u, 17220887603689539957u, 1434383093523822128u, 14508740362393577840u, ++ 16546065181022836267u, 4549193289962883435u, 13995757083443852846u, 1766676892172462446u, 12309576339732698657u, 8100554995509053793u, 10192175931700983332u, 6327407589325138276u, ++ }, ++}; + +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} ++static const uint8_t ++WUFFS_CRC64__ECMA_X86_SSE42_FOLD1[16] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 228u, 58u, 57u, 202u, 151u, 212u, 93u, 224u, ++ 64u, 95u, 135u, 199u, 175u, 149u, 190u, 218u, ++}; + +-// -------- func gif.decoder.do_tell_me_more ++static const uint8_t ++WUFFS_CRC64__ECMA_X86_SSE42_FOLD2[16] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 68u, 250u, 158u, 138u, 0u, 91u, 9u, 96u, ++ 81u, 175u, 225u, 15u, 163u, 83u, 230u, 59u, ++}; ++ ++static const uint8_t ++WUFFS_CRC64__ECMA_X86_SSE42_FOLD4[16] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 243u, 65u, 212u, 157u, 187u, 239u, 227u, 106u, ++ 244u, 45u, 132u, 167u, 84u, 96u, 31u, 8u, ++}; ++ ++static const uint8_t ++WUFFS_CRC64__ECMA_X86_SSE42_FOLD8[16] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 16u, 204u, 79u, 29u, 215u, 87u, 135u, ++ 64u, 231u, 61u, 247u, 42u, 107u, 216u, 215u, ++}; ++ ++static const uint8_t ++WUFFS_CRC64__ECMA_X86_SSE42_MUPX[16] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 213u, 99u, 41u, 23u, 108u, 70u, 62u, 156u, ++ 133u, 30u, 14u, 175u, 43u, 175u, 216u, 146u, ++}; ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__do_tell_me_more( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++static wuffs_base__empty_struct ++wuffs_crc64__ecma_hasher__up( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x); + +- uint64_t v_chunk_length = 0; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_crc64__ecma_hasher__up__choosy_default( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_crc64__ecma_hasher__up_x86_sse42( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) + +- uint32_t coro_susp_point = self->private_impl.p_do_tell_me_more[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++// ---------------- VTables + +- if ((self->private_impl.f_call_sequence & 16u) == 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } +- if (self->private_impl.f_metadata_fourcc == 0u) { +- status = wuffs_base__make_status(wuffs_base__error__no_more_information); +- goto exit; +- } +- while (true) { +- while (true) { +- if (wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) != self->private_impl.f_metadata_io_position) { +- if (a_minfo != NULL) { +- wuffs_base__more_information__set(a_minfo, +- 2u, +- 0u, +- self->private_impl.f_metadata_io_position, +- 0u, +- 0u); +- } +- status = wuffs_base__make_status(wuffs_base__suspension__mispositioned_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- continue; +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_minfo != NULL) { +- wuffs_base__more_information__set(a_minfo, +- 0u, +- 0u, +- 0u, +- 0u, +- 0u); +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- continue; +- } +- break; +- } +- v_chunk_length = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))); +- if (v_chunk_length <= 0u) { +- iop_a_src += 1u; +- break; +- } +- if (self->private_impl.f_metadata_fourcc == 1481461792u) { +- v_chunk_length += 1u; +- } else { +- iop_a_src += 1u; +- } +- self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))), v_chunk_length); +- if (a_minfo != NULL) { +- wuffs_base__more_information__set(a_minfo, +- 3u, +- self->private_impl.f_metadata_fourcc, +- 0u, +- wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))), +- self->private_impl.f_metadata_io_position); +- } +- status = wuffs_base__make_status(wuffs_base__suspension__even_more_information); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++const wuffs_base__hasher_u64__func_ptrs ++wuffs_crc64__ecma_hasher__func_ptrs_for__wuffs_base__hasher_u64 = { ++ (uint64_t(*)(const void*))(&wuffs_crc64__ecma_hasher__checksum_u64), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_crc64__ecma_hasher__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_crc64__ecma_hasher__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_crc64__ecma_hasher__update), ++ (uint64_t(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_crc64__ecma_hasher__update_u64), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_crc64__ecma_hasher__initialize( ++ wuffs_crc64__ecma_hasher* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); + } +- if (a_minfo != NULL) { +- wuffs_base__more_information__set(a_minfo, +- 3u, +- self->private_impl.f_metadata_fourcc, +- 0u, +- self->private_impl.f_metadata_io_position, +- self->private_impl.f_metadata_io_position); ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); + } +- self->private_impl.f_call_sequence &= 239u; +- self->private_impl.f_metadata_fourcc = 0u; +- self->private_impl.f_metadata_io_position = 0u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- +- ok: +- self->private_impl.p_do_tell_me_more[0] = 0; +- goto exit; + } + +- goto suspend; +- suspend: +- self->private_impl.p_do_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.choosy_up = &wuffs_crc64__ecma_hasher__up__choosy_default; + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__hasher_u64.vtable_name = ++ wuffs_base__hasher_u64__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__hasher_u64.function_pointers = ++ (const void*)(&wuffs_crc64__ecma_hasher__func_ptrs_for__wuffs_base__hasher_u64); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_crc64__ecma_hasher* ++wuffs_crc64__ecma_hasher__alloc(void) { ++ wuffs_crc64__ecma_hasher* x = ++ (wuffs_crc64__ecma_hasher*)(calloc(1, sizeof(wuffs_crc64__ecma_hasher))); ++ if (!x) { ++ return NULL; + } ++ if (wuffs_crc64__ecma_hasher__initialize( ++ x, sizeof(wuffs_crc64__ecma_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} + +- return status; ++size_t ++sizeof__wuffs_crc64__ecma_hasher(void) { ++ return sizeof(wuffs_crc64__ecma_hasher); + } + +-// -------- func gif.decoder.num_animation_loops ++// ---------------- Function Implementations ++ ++// -------- func crc64.ecma_hasher.get_quirk + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_gif__decoder__num_animation_loops( +- const wuffs_gif__decoder* self) { ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_crc64__ecma_hasher__get_quirk( ++ const wuffs_crc64__ecma_hasher* self, ++ uint32_t a_key) { + if (!self) { + return 0; + } +@@ -37136,38 +37965,134 @@ wuffs_gif__decoder__num_animation_loops( + return 0; + } + +- if (self->private_impl.f_seen_num_animation_loops_value) { +- return self->private_impl.f_num_animation_loops_value; +- } +- if (self->private_impl.f_num_decoded_frame_configs_value > 1u) { +- return 1u; +- } + return 0u; + } + +-// -------- func gif.decoder.num_decoded_frame_configs ++// -------- func crc64.ecma_hasher.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_crc64__ecma_hasher__set_quirk( ++ wuffs_crc64__ecma_hasher* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func crc64.ecma_hasher.update ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_crc64__ecma_hasher__update( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); ++ } ++ ++ if (self->private_impl.f_state == 0u) { ++ self->private_impl.choosy_up = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_crc64__ecma_hasher__up_x86_sse42 : ++#endif ++ self->private_impl.choosy_up); ++ } ++ wuffs_crc64__ecma_hasher__up(self, a_x); ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func crc64.ecma_hasher.update_u64 + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_gif__decoder__num_decoded_frame_configs( +- const wuffs_gif__decoder* self) { ++wuffs_crc64__ecma_hasher__update_u64( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x) { + if (!self) { + return 0; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { + return 0; + } + +- return self->private_impl.f_num_decoded_frame_configs_value; ++ wuffs_crc64__ecma_hasher__update(self, a_x); ++ return wuffs_crc64__ecma_hasher__checksum_u64(self); + } + +-// -------- func gif.decoder.num_decoded_frames ++// -------- func crc64.ecma_hasher.up ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_crc64__ecma_hasher__up( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ return (*self->private_impl.choosy_up)(self, a_x); ++} ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_crc64__ecma_hasher__up__choosy_default( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint64_t v_s = 0; ++ wuffs_base__slice_u8 v_p = {0}; ++ ++ v_s = (18446744073709551615u ^ self->private_impl.f_state); ++ { ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 8; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8)); ++ while (v_p.ptr < i_end0_p) { ++ v_s ^= ((((uint64_t)(v_p.ptr[0u])) << 0u) | ++ (((uint64_t)(v_p.ptr[1u])) << 8u) | ++ (((uint64_t)(v_p.ptr[2u])) << 16u) | ++ (((uint64_t)(v_p.ptr[3u])) << 24u) | ++ (((uint64_t)(v_p.ptr[4u])) << 32u) | ++ (((uint64_t)(v_p.ptr[5u])) << 40u) | ++ (((uint64_t)(v_p.ptr[6u])) << 48u) | ++ (((uint64_t)(v_p.ptr[7u])) << 56u)); ++ v_s = (WUFFS_CRC64__ECMA_TABLE[0u][(255u & (v_s >> 56u))] ^ ++ WUFFS_CRC64__ECMA_TABLE[1u][(255u & (v_s >> 48u))] ^ ++ WUFFS_CRC64__ECMA_TABLE[2u][(255u & (v_s >> 40u))] ^ ++ WUFFS_CRC64__ECMA_TABLE[3u][(255u & (v_s >> 32u))] ^ ++ WUFFS_CRC64__ECMA_TABLE[4u][(255u & (v_s >> 24u))] ^ ++ WUFFS_CRC64__ECMA_TABLE[5u][(255u & (v_s >> 16u))] ^ ++ WUFFS_CRC64__ECMA_TABLE[6u][(255u & (v_s >> 8u))] ^ ++ WUFFS_CRC64__ECMA_TABLE[7u][(255u & (v_s >> 0u))]); ++ v_p.ptr += 8; ++ } ++ v_p.len = 1; ++ const uint8_t* i_end1_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end1_p) { ++ v_s = (WUFFS_CRC64__ECMA_TABLE[0u][((uint8_t)(((uint8_t)(v_s)) ^ v_p.ptr[0u]))] ^ (v_s >> 8u)); ++ v_p.ptr += 1; ++ } ++ v_p.len = 0; ++ } ++ self->private_impl.f_state = (18446744073709551615u ^ v_s); ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func crc64.ecma_hasher.checksum_u64 + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_gif__decoder__num_decoded_frames( +- const wuffs_gif__decoder* self) { ++wuffs_crc64__ecma_hasher__checksum_u64( ++ const wuffs_crc64__ecma_hasher* self) { + if (!self) { + return 0; + } +@@ -37176,72 +38101,473 @@ wuffs_gif__decoder__num_decoded_frames( + return 0; + } + +- return self->private_impl.f_num_decoded_frames_value; ++ return self->private_impl.f_state; + } + +-// -------- func gif.decoder.frame_dirty_rect ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++// -------- func crc64.ecma_hasher.up_x86_sse42 + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_gif__decoder__frame_dirty_rect( +- const wuffs_gif__decoder* self) { ++static wuffs_base__empty_struct ++wuffs_crc64__ecma_hasher__up_x86_sse42( ++ wuffs_crc64__ecma_hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint64_t v_s = 0; ++ wuffs_base__slice_u8 v_p = {0}; ++ uint8_t v_buf[48] = {0}; ++ __m128i v_xa = {0}; ++ __m128i v_xb = {0}; ++ __m128i v_xc = {0}; ++ __m128i v_xd = {0}; ++ __m128i v_xe = {0}; ++ __m128i v_xf = {0}; ++ __m128i v_xg = {0}; ++ __m128i v_xh = {0}; ++ __m128i v_mu1 = {0}; ++ __m128i v_mu2 = {0}; ++ __m128i v_mu4 = {0}; ++ __m128i v_mu8 = {0}; ++ __m128i v_mupx = {0}; ++ ++ v_s = (18446744073709551615u ^ self->private_impl.f_state); ++ while ((((uint64_t)(a_x.len)) > 0u) && ((15u & ((uint32_t)(0xFFFu & (uintptr_t)(a_x.ptr)))) != 0u)) { ++ v_s = (WUFFS_CRC64__ECMA_TABLE[0u][((uint8_t)(((uint8_t)(v_s)) ^ a_x.ptr[0u]))] ^ (v_s >> 8u)); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); ++ } ++ do { ++ do { ++ if (((uint64_t)(a_x.len)) >= 128u) { ++ } else if (((uint64_t)(a_x.len)) >= 64u) { ++ v_xa = _mm_xor_si128(_mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u)), _mm_cvtsi64_si128((int64_t)(v_s))); ++ v_xb = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u)); ++ v_xc = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32u)); ++ v_xd = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48u)); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 64u); ++ break; ++ } else if (((uint64_t)(a_x.len)) >= 32u) { ++ v_xa = _mm_xor_si128(_mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u)), _mm_cvtsi64_si128((int64_t)(v_s))); ++ v_xb = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u)); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 32u); ++ goto label__chain2__break; ++ } else { ++ { ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 1; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end0_p) { ++ v_s = (WUFFS_CRC64__ECMA_TABLE[0u][((uint8_t)(((uint8_t)(v_s)) ^ v_p.ptr[0u]))] ^ (v_s >> 8u)); ++ v_p.ptr += 1; ++ } ++ v_p.len = 0; ++ } ++ self->private_impl.f_state = (18446744073709551615u ^ v_s); ++ return wuffs_base__make_empty_struct(); ++ } ++ v_xa = _mm_xor_si128(_mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u)), _mm_cvtsi64_si128((int64_t)(v_s))); ++ v_xb = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u)); ++ v_xc = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32u)); ++ v_xd = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48u)); ++ v_xe = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 64u)); ++ v_xf = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 80u)); ++ v_xg = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 96u)); ++ v_xh = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 112u)); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 128u); ++ v_mu8 = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC64__ECMA_X86_SSE42_FOLD8)); ++ while (((uint64_t)(a_x.len)) >= 128u) { ++ v_xa = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xa, v_mu8, (int32_t)(0u)), _mm_clmulepi64_si128(v_xa, v_mu8, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u))); ++ v_xb = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xb, v_mu8, (int32_t)(0u)), _mm_clmulepi64_si128(v_xb, v_mu8, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u))); ++ v_xc = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xc, v_mu8, (int32_t)(0u)), _mm_clmulepi64_si128(v_xc, v_mu8, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32u))); ++ v_xd = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xd, v_mu8, (int32_t)(0u)), _mm_clmulepi64_si128(v_xd, v_mu8, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48u))); ++ v_xe = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xe, v_mu8, (int32_t)(0u)), _mm_clmulepi64_si128(v_xe, v_mu8, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 64u))); ++ v_xf = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xf, v_mu8, (int32_t)(0u)), _mm_clmulepi64_si128(v_xf, v_mu8, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 80u))); ++ v_xg = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xg, v_mu8, (int32_t)(0u)), _mm_clmulepi64_si128(v_xg, v_mu8, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 96u))); ++ v_xh = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xh, v_mu8, (int32_t)(0u)), _mm_clmulepi64_si128(v_xh, v_mu8, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 112u))); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 128u); ++ } ++ v_mu4 = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC64__ECMA_X86_SSE42_FOLD4)); ++ v_xa = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xa, v_mu4, (int32_t)(0u)), _mm_clmulepi64_si128(v_xa, v_mu4, (int32_t)(17u))), v_xe); ++ v_xb = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xb, v_mu4, (int32_t)(0u)), _mm_clmulepi64_si128(v_xb, v_mu4, (int32_t)(17u))), v_xf); ++ v_xc = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xc, v_mu4, (int32_t)(0u)), _mm_clmulepi64_si128(v_xc, v_mu4, (int32_t)(17u))), v_xg); ++ v_xd = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xd, v_mu4, (int32_t)(0u)), _mm_clmulepi64_si128(v_xd, v_mu4, (int32_t)(17u))), v_xh); ++ if (((uint64_t)(a_x.len)) > 64u) { ++ v_xa = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xa, v_mu4, (int32_t)(0u)), _mm_clmulepi64_si128(v_xa, v_mu4, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u))); ++ v_xb = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xb, v_mu4, (int32_t)(0u)), _mm_clmulepi64_si128(v_xb, v_mu4, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u))); ++ v_xc = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xc, v_mu4, (int32_t)(0u)), _mm_clmulepi64_si128(v_xc, v_mu4, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32u))); ++ v_xd = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xd, v_mu4, (int32_t)(0u)), _mm_clmulepi64_si128(v_xd, v_mu4, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48u))); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 64u); ++ } ++ } while (0); ++ v_mu2 = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC64__ECMA_X86_SSE42_FOLD2)); ++ v_xa = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xa, v_mu2, (int32_t)(0u)), _mm_clmulepi64_si128(v_xa, v_mu2, (int32_t)(17u))), v_xc); ++ v_xb = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xb, v_mu2, (int32_t)(0u)), _mm_clmulepi64_si128(v_xb, v_mu2, (int32_t)(17u))), v_xd); ++ if (((uint64_t)(a_x.len)) > 32u) { ++ v_xa = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xa, v_mu2, (int32_t)(0u)), _mm_clmulepi64_si128(v_xa, v_mu2, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u))); ++ v_xb = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xb, v_mu2, (int32_t)(0u)), _mm_clmulepi64_si128(v_xb, v_mu2, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16u))); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 32u); ++ } ++ } while (0); ++ label__chain2__break:; ++ v_mu1 = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC64__ECMA_X86_SSE42_FOLD1)); ++ v_xa = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xa, v_mu1, (int32_t)(0u)), _mm_clmulepi64_si128(v_xa, v_mu1, (int32_t)(17u))), v_xb); ++ if (((uint64_t)(a_x.len)) > 24u) { ++ v_xa = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(v_xa, v_mu1, (int32_t)(0u)), _mm_clmulepi64_si128(v_xa, v_mu1, (int32_t)(17u))), _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0u))); ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 16u); ++ if (((uint64_t)(a_x.len)) > 24u) { ++ return wuffs_base__make_empty_struct(); ++ } ++ } ++ _mm_storeu_si128((__m128i*)(void*)(v_buf + (24u - ((uint64_t)(a_x.len)))), v_xa); ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(v_buf, ((24u - ((uint64_t)(a_x.len))) + 16u), 48), a_x); ++ v_mu2 = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC64__ECMA_X86_SSE42_FOLD2)); ++ v_xa = _mm_lddqu_si128((const __m128i*)(const void*)(v_buf + 0u)); ++ v_xb = _mm_lddqu_si128((const __m128i*)(const void*)(v_buf + 16u)); ++ v_xc = _mm_lddqu_si128((const __m128i*)(const void*)(v_buf + 32u)); ++ v_xd = _mm_xor_si128(_mm_clmulepi64_si128(v_xa, v_mu2, (int32_t)(0u)), _mm_clmulepi64_si128(v_xa, v_mu2, (int32_t)(17u))); ++ v_xe = _mm_xor_si128(_mm_clmulepi64_si128(v_xb, v_mu1, (int32_t)(0u)), _mm_clmulepi64_si128(v_xb, v_mu1, (int32_t)(17u))); ++ v_xa = _mm_xor_si128(v_xd, _mm_xor_si128(v_xe, v_xc)); ++ v_mupx = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC64__ECMA_X86_SSE42_MUPX)); ++ v_xb = _mm_clmulepi64_si128(v_xa, v_mupx, (int32_t)(0u)); ++ v_xc = _mm_clmulepi64_si128(v_xb, v_mupx, (int32_t)(16u)); ++ v_s = ((uint64_t)(_mm_extract_epi64(_mm_xor_si128(_mm_xor_si128(v_xc, _mm_slli_si128(v_xb, (int32_t)(8u))), v_xa), (int32_t)(1u)))); ++ self->private_impl.f_state = (18446744073709551615u ^ v_s); ++ return wuffs_base__make_empty_struct(); ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC64) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_deflate__error__bad_huffman_code_over_subscribed[] = "#deflate: bad Huffman code (over-subscribed)"; ++const char wuffs_deflate__error__bad_huffman_code_under_subscribed[] = "#deflate: bad Huffman code (under-subscribed)"; ++const char wuffs_deflate__error__bad_huffman_code_length_count[] = "#deflate: bad Huffman code length count"; ++const char wuffs_deflate__error__bad_huffman_code_length_repetition[] = "#deflate: bad Huffman code length repetition"; ++const char wuffs_deflate__error__bad_huffman_code[] = "#deflate: bad Huffman code"; ++const char wuffs_deflate__error__bad_huffman_minimum_code_length[] = "#deflate: bad Huffman minimum code length"; ++const char wuffs_deflate__error__bad_block[] = "#deflate: bad block"; ++const char wuffs_deflate__error__bad_distance[] = "#deflate: bad distance"; ++const char wuffs_deflate__error__bad_distance_code_count[] = "#deflate: bad distance code count"; ++const char wuffs_deflate__error__bad_literal_length_code_count[] = "#deflate: bad literal/length code count"; ++const char wuffs_deflate__error__inconsistent_stored_block_length[] = "#deflate: inconsistent stored block length"; ++const char wuffs_deflate__error__missing_end_of_block_code[] = "#deflate: missing end-of-block code"; ++const char wuffs_deflate__error__no_huffman_codes[] = "#deflate: no Huffman codes"; ++const char wuffs_deflate__error__truncated_input[] = "#deflate: truncated input"; ++const char wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state[] = "#deflate: internal error: inconsistent Huffman decoder state"; ++const char wuffs_deflate__error__internal_error_inconsistent_i_o[] = "#deflate: internal error: inconsistent I/O"; ++const char wuffs_deflate__error__internal_error_inconsistent_distance[] = "#deflate: internal error: inconsistent distance"; ++const char wuffs_deflate__error__internal_error_inconsistent_n_bits[] = "#deflate: internal error: inconsistent n_bits"; ++ ++// ---------------- Private Consts ++ ++static const uint8_t ++WUFFS_DEFLATE__CODE_ORDER[19] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 16u, 17u, 18u, 0u, 8u, 7u, 9u, 6u, ++ 10u, 5u, 11u, 4u, 12u, 3u, 13u, 2u, ++ 14u, 1u, 15u, ++}; ++ ++static const uint8_t ++WUFFS_DEFLATE__REVERSE8[256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 128u, 64u, 192u, 32u, 160u, 96u, 224u, ++ 16u, 144u, 80u, 208u, 48u, 176u, 112u, 240u, ++ 8u, 136u, 72u, 200u, 40u, 168u, 104u, 232u, ++ 24u, 152u, 88u, 216u, 56u, 184u, 120u, 248u, ++ 4u, 132u, 68u, 196u, 36u, 164u, 100u, 228u, ++ 20u, 148u, 84u, 212u, 52u, 180u, 116u, 244u, ++ 12u, 140u, 76u, 204u, 44u, 172u, 108u, 236u, ++ 28u, 156u, 92u, 220u, 60u, 188u, 124u, 252u, ++ 2u, 130u, 66u, 194u, 34u, 162u, 98u, 226u, ++ 18u, 146u, 82u, 210u, 50u, 178u, 114u, 242u, ++ 10u, 138u, 74u, 202u, 42u, 170u, 106u, 234u, ++ 26u, 154u, 90u, 218u, 58u, 186u, 122u, 250u, ++ 6u, 134u, 70u, 198u, 38u, 166u, 102u, 230u, ++ 22u, 150u, 86u, 214u, 54u, 182u, 118u, 246u, ++ 14u, 142u, 78u, 206u, 46u, 174u, 110u, 238u, ++ 30u, 158u, 94u, 222u, 62u, 190u, 126u, 254u, ++ 1u, 129u, 65u, 193u, 33u, 161u, 97u, 225u, ++ 17u, 145u, 81u, 209u, 49u, 177u, 113u, 241u, ++ 9u, 137u, 73u, 201u, 41u, 169u, 105u, 233u, ++ 25u, 153u, 89u, 217u, 57u, 185u, 121u, 249u, ++ 5u, 133u, 69u, 197u, 37u, 165u, 101u, 229u, ++ 21u, 149u, 85u, 213u, 53u, 181u, 117u, 245u, ++ 13u, 141u, 77u, 205u, 45u, 173u, 109u, 237u, ++ 29u, 157u, 93u, 221u, 61u, 189u, 125u, 253u, ++ 3u, 131u, 67u, 195u, 35u, 163u, 99u, 227u, ++ 19u, 147u, 83u, 211u, 51u, 179u, 115u, 243u, ++ 11u, 139u, 75u, 203u, 43u, 171u, 107u, 235u, ++ 27u, 155u, 91u, 219u, 59u, 187u, 123u, 251u, ++ 7u, 135u, 71u, 199u, 39u, 167u, 103u, 231u, ++ 23u, 151u, 87u, 215u, 55u, 183u, 119u, 247u, ++ 15u, 143u, 79u, 207u, 47u, 175u, 111u, 239u, ++ 31u, 159u, 95u, 223u, 63u, 191u, 127u, 255u, ++}; ++ ++static const uint32_t ++WUFFS_DEFLATE__LCODE_MAGIC_NUMBERS[32] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1073741824u, 1073742080u, 1073742336u, 1073742592u, 1073742848u, 1073743104u, 1073743360u, 1073743616u, ++ 1073743888u, 1073744400u, 1073744912u, 1073745424u, 1073745952u, 1073746976u, 1073748000u, 1073749024u, ++ 1073750064u, 1073752112u, 1073754160u, 1073756208u, 1073758272u, 1073762368u, 1073766464u, 1073770560u, ++ 1073774672u, 1073782864u, 1073791056u, 1073799248u, 1073807104u, 134217728u, 134217728u, 134217728u, ++}; ++ ++static const uint32_t ++WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[32] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1073741824u, 1073742080u, 1073742336u, 1073742592u, 1073742864u, 1073743376u, 1073743904u, 1073744928u, ++ 1073745968u, 1073748016u, 1073750080u, 1073754176u, 1073758288u, 1073766480u, 1073774688u, 1073791072u, ++ 1073807472u, 1073840240u, 1073873024u, 1073938560u, 1074004112u, 1074135184u, 1074266272u, 1074528416u, ++ 1074790576u, 1075314864u, 1075839168u, 1076887744u, 1077936336u, 1080033488u, 134217728u, 134217728u, ++}; ++ ++#define WUFFS_DEFLATE__HUFFS_TABLE_SIZE 1024u ++ ++#define WUFFS_DEFLATE__HUFFS_TABLE_MASK 1023u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__do_transform_io( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__decode_blocks( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__decode_uncompressed( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__init_fixed_huffman( ++ wuffs_deflate__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__init_dynamic_huffman( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__init_huff( ++ wuffs_deflate__decoder* self, ++ uint32_t a_which, ++ uint32_t a_n_codes0, ++ uint32_t a_n_codes1, ++ uint32_t a_base_symbol); ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__decode_huffman_bmi2( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__decode_huffman_fast32( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__decode_huffman_fast64( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__decode_huffman_fast64__choosy_default( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__decode_huffman_slow( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++// ---------------- VTables ++ ++const wuffs_base__io_transformer__func_ptrs ++wuffs_deflate__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++ (wuffs_base__optional_u63(*)(const void*))(&wuffs_deflate__decoder__dst_history_retain_length), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_deflate__decoder__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_deflate__decoder__set_quirk), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_deflate__decoder__transform_io), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_deflate__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_deflate__decoder__initialize( ++ wuffs_deflate__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ + if (!self) { +- return wuffs_base__utility__empty_rect_ie_u32(); ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_rect_ie_u32(); ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); + } + +- return wuffs_base__utility__make_rect_ie_u32( +- wuffs_base__u32__min(self->private_impl.f_frame_rect_x0, self->private_impl.f_width), +- wuffs_base__u32__min(self->private_impl.f_frame_rect_y0, self->private_impl.f_height), +- wuffs_base__u32__min(self->private_impl.f_frame_rect_x1, self->private_impl.f_width), +- wuffs_base__u32__min(self->private_impl.f_dirty_max_excl_y, self->private_impl.f_height)); ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.choosy_decode_huffman_fast64 = &wuffs_deflate__decoder__decode_huffman_fast64__choosy_default; ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = ++ wuffs_base__io_transformer__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = ++ (const void*)(&wuffs_deflate__decoder__func_ptrs_for__wuffs_base__io_transformer); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_deflate__decoder* ++wuffs_deflate__decoder__alloc(void) { ++ wuffs_deflate__decoder* x = ++ (wuffs_deflate__decoder*)(calloc(1, sizeof(wuffs_deflate__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_deflate__decoder__initialize( ++ x, sizeof(wuffs_deflate__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_deflate__decoder(void) { ++ return sizeof(wuffs_deflate__decoder); + } + +-// -------- func gif.decoder.history_retain_length ++// ---------------- Function Implementations ++ ++// -------- func deflate.decoder.add_history + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_gif__decoder__history_retain_length( +- const wuffs_gif__decoder* self) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_deflate__decoder__add_history( ++ wuffs_deflate__decoder* self, ++ wuffs_base__slice_u8 a_hist) { + if (!self) { +- return 0; ++ return wuffs_base__make_empty_struct(); + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); + } + +- return 0u; ++ wuffs_base__slice_u8 v_s = {0}; ++ uint64_t v_n_copied = 0; ++ uint32_t v_already_full = 0; ++ ++ v_s = a_hist; ++ if (((uint64_t)(v_s.len)) >= 32768u) { ++ v_s = wuffs_private_impl__slice_u8__suffix(v_s, 32768u); ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s); ++ self->private_impl.f_history_index = 32768u; ++ } else { ++ v_n_copied = wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_history, (self->private_impl.f_history_index & 32767u), 32768), v_s); ++ if (v_n_copied < ((uint64_t)(v_s.len))) { ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, v_n_copied); ++ v_n_copied = wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s); ++ self->private_impl.f_history_index = (((uint32_t)((v_n_copied & 32767u))) + 32768u); ++ } else { ++ v_already_full = 0u; ++ if (self->private_impl.f_history_index >= 32768u) { ++ v_already_full = 32768u; ++ } ++ self->private_impl.f_history_index = ((self->private_impl.f_history_index & 32767u) + ((uint32_t)((v_n_copied & 32767u))) + v_already_full); ++ } ++ } ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_history, 32768, 33025), wuffs_base__make_slice_u8(self->private_data.f_history, 33025)); ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func gif.decoder.workbuf_len ++// -------- func deflate.decoder.get_quirk + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_gif__decoder__workbuf_len( +- const wuffs_gif__decoder* self) { ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_deflate__decoder__get_quirk( ++ const wuffs_deflate__decoder* self, ++ uint32_t a_key) { + if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ return 0; + } + if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && + (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ return 0; + } + +- return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++ return 0u; + } + +-// -------- func gif.decoder.restart_frame ++// -------- func deflate.decoder.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_gif__decoder__restart_frame( +- wuffs_gif__decoder* self, +- uint64_t a_index, +- uint64_t a_io_position) { ++wuffs_deflate__decoder__set_quirk( ++ wuffs_deflate__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +@@ -37252,28 +38578,52 @@ wuffs_gif__decoder__restart_frame( + : wuffs_base__error__initialize_not_called); + } + +- if (self->private_impl.f_call_sequence < 32u) { +- return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- } else if (a_io_position == 0u) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func deflate.decoder.dst_history_retain_length ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_deflate__decoder__dst_history_retain_length( ++ const wuffs_deflate__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); + } +- self->private_impl.f_delayed_num_decoded_frames = false; +- self->private_impl.f_frame_config_io_position = a_io_position; +- self->private_impl.f_num_decoded_frame_configs_value = a_index; +- self->private_impl.f_num_decoded_frames_value = a_index; +- wuffs_gif__decoder__reset_gc(self); +- self->private_impl.f_call_sequence = 40u; +- return wuffs_base__make_status(NULL); ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ ++ return wuffs_base__utility__make_optional_u63(true, 0u); + } + +-// -------- func gif.decoder.decode_frame_config ++// -------- func deflate.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_deflate__decoder__workbuf_len( ++ const wuffs_deflate__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__make_range_ii_u64(1u, 1u); ++} ++ ++// -------- func deflate.decoder.transform_io + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_gif__decoder__decode_frame_config( +- wuffs_gif__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { ++wuffs_deflate__decoder__transform_io( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +@@ -37283,12 +38633,12 @@ wuffs_gif__decoder__decode_frame_config( + ? wuffs_base__error__disabled_by_previous_error + : wuffs_base__error__initialize_not_called); + } +- if (!a_src) { ++ if (!a_dst || !a_src) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 3)) { ++ (self->private_impl.active_coroutine != 1)) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } +@@ -37297,17 +38647,17 @@ wuffs_gif__decoder__decode_frame_config( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_transform_io; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_gif__decoder__do_decode_frame_config(self, a_dst, a_src); ++ wuffs_base__status t_0 = wuffs_deflate__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_gif__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_deflate__error__truncated_input); + goto exit; + } + status = v_status; +@@ -37315,14 +38665,14 @@ wuffs_gif__decoder__decode_frame_config( + } + + ok: +- self->private_impl.p_decode_frame_config[0] = 0; ++ self->private_impl.p_transform_io = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ self->private_impl.p_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; + + goto exit; + exit: +@@ -37332,403 +38682,103 @@ wuffs_gif__decoder__decode_frame_config( + return status; + } + +-// -------- func gif.decoder.do_decode_frame_config ++// -------- func deflate.decoder.do_transform_io + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__do_decode_frame_config( +- wuffs_gif__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { ++wuffs_deflate__decoder__do_transform_io( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_background_color = 0; +- uint8_t v_flags = 0; ++ uint64_t v_mark = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config[0]; +- if (coro_susp_point) { +- v_background_color = self->private_data.s_do_decode_frame_config[0].v_background_color; +- } ++ uint32_t coro_susp_point = self->private_impl.p_do_transform_io; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- self->private_impl.f_dirty_max_excl_y = 0u; +- if ((self->private_impl.f_call_sequence & 16u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } else if (self->private_impl.f_call_sequence == 32u) { +- } else if (self->private_impl.f_call_sequence < 32u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ self->private_impl.choosy_decode_huffman_fast64 = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++ wuffs_base__cpu_arch__have_x86_bmi2() ? &wuffs_deflate__decoder__decode_huffman_bmi2 : ++#endif ++ self->private_impl.choosy_decode_huffman_fast64); ++ while (true) { ++ v_mark = ((uint64_t)(iop_a_dst - io0_a_dst)); ++ { ++ if (a_dst) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ wuffs_base__status t_0 = wuffs_deflate__decoder__decode_blocks(self, a_dst, a_src); ++ v_status = t_0; ++ if (a_dst) { ++ iop_a_dst = a_dst->data.ptr + a_dst->meta.wi; ++ } + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_gif__decoder__do_decode_image_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } else if (self->private_impl.f_call_sequence == 40u) { +- if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_restart); +- goto exit; +- } +- } else if (self->private_impl.f_call_sequence == 64u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- status = wuffs_gif__decoder__skip_frame(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- if (self->private_impl.f_call_sequence >= 96u) { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- if ((self->private_impl.f_num_decoded_frame_configs_value > 0u) || (self->private_impl.f_call_sequence == 40u)) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- if (self->private_impl.f_call_sequence >= 96u) { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- } +- v_background_color = self->private_impl.f_black_color_u32_argb_premul; +- if ( ! self->private_impl.f_gc_has_transparent_index) { +- v_background_color = self->private_impl.f_background_color_u32_argb_premul; +- if (self->private_impl.f_quirks[1u] && (self->private_impl.f_num_decoded_frame_configs_value == 0u)) { +- while (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); +- } +- v_flags = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if ((v_flags & 128u) != 0u) { +- v_background_color = self->private_impl.f_black_color_u32_argb_premul; ++ if ( ! wuffs_base__status__is_suspension(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; + } ++ goto ok; + } +- } +- if (a_dst != NULL) { +- wuffs_base__frame_config__set( +- a_dst, +- wuffs_base__utility__make_rect_ie_u32( +- wuffs_base__u32__min(self->private_impl.f_frame_rect_x0, self->private_impl.f_width), +- wuffs_base__u32__min(self->private_impl.f_frame_rect_y0, self->private_impl.f_height), +- wuffs_base__u32__min(self->private_impl.f_frame_rect_x1, self->private_impl.f_width), +- wuffs_base__u32__min(self->private_impl.f_frame_rect_y1, self->private_impl.f_height)), +- ((wuffs_base__flicks)(self->private_impl.f_gc_duration)), +- self->private_impl.f_num_decoded_frame_configs_value, +- self->private_impl.f_frame_config_io_position, +- self->private_impl.f_gc_disposal, +- ! self->private_impl.f_gc_has_transparent_index, +- false, +- v_background_color); +- } +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frame_configs_value, 1u); +- self->private_impl.f_call_sequence = 64u; +- +- ok: +- self->private_impl.p_do_decode_frame_config[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_decode_frame_config[0].v_background_color = v_background_color; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func gif.decoder.skip_frame +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__skip_frame( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint8_t v_flags = 0; +- uint8_t v_lw = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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_skip_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_flags = t_0; +- } +- if ((v_flags & 128u) != 0u) { +- self->private_data.s_skip_frame[0].scratch = (((uint32_t)(3u)) << (1u + (v_flags & 7u))); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_skip_frame[0].scratch; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- v_lw = t_1; +- } +- if (v_lw > 8u) { +- status = wuffs_base__make_status(wuffs_gif__error__bad_literal_width); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- status = wuffs_gif__decoder__skip_blocks(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- if (self->private_impl.f_quirks[0u]) { +- self->private_impl.f_delayed_num_decoded_frames = true; +- } else { +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); +- } +- wuffs_gif__decoder__reset_gc(self); +- self->private_impl.f_call_sequence = 32u; +- +- goto ok; +- ok: +- self->private_impl.p_skip_frame[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_skip_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func gif.decoder.decode_frame +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_gif__decoder__decode_frame( +- wuffs_gif__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 4)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_gif__decoder__do_decode_frame(self, +- a_dst, +- a_src, +- a_blend, +- a_workbuf, +- a_opts); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_gif__error__truncated_input); +- goto exit; +- } ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_transformed_history_count, wuffs_private_impl__io__count_since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)))); ++ wuffs_deflate__decoder__add_history(self, wuffs_private_impl__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); + status = v_status; + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } + + ok: +- self->private_impl.p_decode_frame[0] = 0; ++ self->private_impl.p_do_transform_io = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0; ++ self->private_impl.p_do_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} +- +-// -------- func gif.decoder.do_decode_frame +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__do_decode_frame( +- wuffs_gif__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- if (self->private_impl.f_call_sequence == 64u) { +- } else if (self->private_impl.f_call_sequence < 64u) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_gif__decoder__do_decode_frame_config(self, NULL, a_src); +- if (status.repr) { +- goto suspend; +- } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- if (self->private_impl.f_quirks[5u] && ((self->private_impl.f_frame_rect_x0 == self->private_impl.f_frame_rect_x1) || (self->private_impl.f_frame_rect_y0 == self->private_impl.f_frame_rect_y1))) { +- status = wuffs_base__make_status(wuffs_gif__error__bad_frame_size); +- goto exit; +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- status = wuffs_gif__decoder__decode_id_part1(self, a_dst, a_src, a_blend); +- if (status.repr) { +- goto suspend; +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_gif__decoder__decode_id_part2(self, a_dst, a_src, a_workbuf); +- if (status.repr) { +- goto suspend; +- } +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); +- wuffs_gif__decoder__reset_gc(self); +- self->private_impl.f_call_sequence = 32u; +- +- ok: +- self->private_impl.p_do_decode_frame[0] = 0; +- goto exit; ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); + } + +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: + return status; + } + +-// -------- func gif.decoder.reset_gc +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_gif__decoder__reset_gc( +- wuffs_gif__decoder* self) { +- self->private_impl.f_gc_has_transparent_index = false; +- self->private_impl.f_gc_transparent_index = 0u; +- self->private_impl.f_gc_disposal = 0u; +- self->private_impl.f_gc_duration = 0u; +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func gif.decoder.decode_up_to_id_part1 ++// -------- func deflate.decoder.decode_blocks + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_up_to_id_part1( +- wuffs_gif__decoder* self, ++wuffs_deflate__decoder__decode_blocks( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_block_type = 0; ++ uint32_t v_final = 0; ++ uint32_t v_b0 = 0; ++ uint32_t v_type = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -37741,71 +38791,125 @@ wuffs_gif__decoder__decode_up_to_id_part1( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_up_to_id_part1[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_blocks; ++ if (coro_susp_point) { ++ v_final = self->private_data.s_decode_blocks.v_final; ++ } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((self->private_impl.f_frame_config_io_position == 0u) || (self->private_impl.f_num_decoded_frame_configs_value > 0u)) { +- self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- } +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ label__outer__continue:; ++ while (v_final == 0u) { ++ while (self->private_impl.f_n_bits < 3u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_0 = *iop_a_src++; ++ v_b0 = t_0; + } +- uint8_t t_0 = *iop_a_src++; +- v_block_type = t_0; ++ self->private_impl.f_bits |= (v_b0 << (self->private_impl.f_n_bits & 3u)); ++ self->private_impl.f_n_bits = ((self->private_impl.f_n_bits & 3u) + 8u); + } +- if (v_block_type == 33u) { ++ v_final = (self->private_impl.f_bits & 1u); ++ v_type = ((self->private_impl.f_bits >> 1u) & 3u); ++ self->private_impl.f_bits >>= 3u; ++ self->private_impl.f_n_bits -= 3u; ++ if (v_type == 0u) { + if (a_src) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- status = wuffs_gif__decoder__decode_extension(self, a_src); ++ status = wuffs_deflate__decoder__decode_uncompressed(self, a_dst, a_src); + if (a_src) { + iop_a_src = a_src->data.ptr + a_src->meta.ri; + } + if (status.repr) { + goto suspend; + } +- } else if (v_block_type == 44u) { +- if (self->private_impl.f_delayed_num_decoded_frames) { +- self->private_impl.f_delayed_num_decoded_frames = false; +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); ++ continue; ++ } else if (v_type == 1u) { ++ v_status = wuffs_deflate__decoder__init_fixed_huffman(self); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; + } ++ } else if (v_type == 2u) { + if (a_src) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_gif__decoder__decode_id_part0(self, a_src); ++ status = wuffs_deflate__decoder__init_dynamic_huffman(self, a_src); + if (a_src) { + iop_a_src = a_src->data.ptr + a_src->meta.ri; + } + if (status.repr) { + goto suspend; + } +- break; + } else { +- if (self->private_impl.f_delayed_num_decoded_frames) { +- self->private_impl.f_delayed_num_decoded_frames = false; +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_block); ++ goto exit; ++ } ++ self->private_impl.f_end_of_block = false; ++ while (true) { ++ if (sizeof(void*) == 4u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_status = wuffs_deflate__decoder__decode_huffman_fast32(self, a_dst, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } else { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_status = wuffs_deflate__decoder__decode_huffman_fast64(self, a_dst, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ if (wuffs_base__status__is_error(&v_status)) { ++ status = v_status; ++ goto exit; ++ } ++ if (self->private_impl.f_end_of_block) { ++ goto label__outer__continue; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_deflate__decoder__decode_huffman_slow(self, a_dst, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (self->private_impl.f_end_of_block) { ++ goto label__outer__continue; + } +- self->private_impl.f_call_sequence = 96u; +- break; + } + } + +- goto ok; + ok: +- self->private_impl.p_decode_up_to_id_part1[0] = 0; ++ self->private_impl.p_decode_blocks = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_up_to_id_part1[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_blocks = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_blocks.v_final = v_final; + + goto exit; + exit: +@@ -37816,18 +38920,32 @@ wuffs_gif__decoder__decode_up_to_id_part1( + return status; + } + +-// -------- func gif.decoder.decode_header ++// -------- func deflate.decoder.decode_uncompressed + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_header( +- wuffs_gif__decoder* self, ++wuffs_deflate__decoder__decode_uncompressed( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c[6] = {0}; +- uint32_t v_i = 0; ++ uint32_t v_length = 0; ++ uint32_t v_n_copied = 0; + ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -37839,50 +38957,85 @@ wuffs_gif__decoder__decode_header( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_header[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_uncompressed; + if (coro_susp_point) { +- memcpy(v_c, self->private_data.s_decode_header[0].v_c, sizeof(v_c)); +- v_i = self->private_data.s_decode_header[0].v_i; ++ v_length = self->private_data.s_decode_uncompressed.v_length; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- while (v_i < 6u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_n_bits = 0u; ++ self->private_impl.f_bits = 0u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_uncompressed.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_uncompressed.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; + } +- uint8_t t_0 = *iop_a_src++; +- v_c[v_i] = t_0; + } +- v_i += 1u; ++ v_length = t_0; + } +- if ((v_c[0u] != 71u) || +- (v_c[1u] != 73u) || +- (v_c[2u] != 70u) || +- (v_c[3u] != 56u) || +- ((v_c[4u] != 55u) && (v_c[4u] != 57u)) || +- (v_c[5u] != 97u)) { +- status = wuffs_base__make_status(wuffs_gif__error__bad_header); ++ if ((((v_length) & 0xFFFFu) + ((v_length) >> (32u - 16u))) != 65535u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__inconsistent_stored_block_length); + goto exit; + } ++ v_length = ((v_length) & 0xFFFFu); ++ while (true) { ++ v_n_copied = wuffs_private_impl__io_writer__limited_copy_u32_from_reader( ++ &iop_a_dst, io2_a_dst,v_length, &iop_a_src, io2_a_src); ++ if (v_length <= v_n_copied) { ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ v_length -= v_n_copied; ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) == 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ } else { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ } ++ } + +- goto ok; + ok: +- self->private_impl.p_decode_header[0] = 0; ++ self->private_impl.p_decode_uncompressed = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_header[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- memcpy(self->private_data.s_decode_header[0].v_c, v_c, sizeof(v_c)); +- self->private_data.s_decode_header[0].v_i = v_i; ++ self->private_impl.p_decode_uncompressed = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_uncompressed.v_length = v_length; + + goto exit; + exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -37890,21 +39043,80 @@ wuffs_gif__decoder__decode_header( + return status; + } + +-// -------- func gif.decoder.decode_lsd ++// -------- func deflate.decoder.init_fixed_huffman + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_lsd( +- wuffs_gif__decoder* self, ++wuffs_deflate__decoder__init_fixed_huffman( ++ wuffs_deflate__decoder* self) { ++ uint32_t v_i = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ while (v_i < 144u) { ++ self->private_data.f_code_lengths[v_i] = 8u; ++ v_i += 1u; ++ } ++ while (v_i < 256u) { ++ self->private_data.f_code_lengths[v_i] = 9u; ++ v_i += 1u; ++ } ++ while (v_i < 280u) { ++ self->private_data.f_code_lengths[v_i] = 7u; ++ v_i += 1u; ++ } ++ while (v_i < 288u) { ++ self->private_data.f_code_lengths[v_i] = 8u; ++ v_i += 1u; ++ } ++ while (v_i < 320u) { ++ self->private_data.f_code_lengths[v_i] = 5u; ++ v_i += 1u; ++ } ++ v_status = wuffs_deflate__decoder__init_huff(self, ++ 0u, ++ 0u, ++ 288u, ++ 257u); ++ if (wuffs_base__status__is_error(&v_status)) { ++ return v_status; ++ } ++ v_status = wuffs_deflate__decoder__init_huff(self, ++ 1u, ++ 288u, ++ 320u, ++ 0u); ++ if (wuffs_base__status__is_error(&v_status)) { ++ return v_status; ++ } ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func deflate.decoder.init_dynamic_huffman ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__init_dynamic_huffman( ++ wuffs_deflate__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_flags = 0; +- uint8_t v_background_color_index = 0; +- uint32_t v_num_palette_entries = 0; ++ uint32_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint32_t v_b0 = 0; ++ uint32_t v_n_lit = 0; ++ uint32_t v_n_dist = 0; ++ uint32_t v_n_clen = 0; + uint32_t v_i = 0; +- uint32_t v_j = 0; +- uint32_t v_argb = 0; ++ uint32_t v_b1 = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint32_t v_mask = 0; ++ uint32_t v_table_entry = 0; ++ uint32_t v_table_entry_n_bits = 0; ++ uint32_t v_b2 = 0; ++ uint32_t v_n_extra_bits = 0; ++ uint8_t v_rep_symbol = 0; ++ uint32_t v_rep_count = 0; ++ uint32_t v_b3 = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -37917,172 +39129,215 @@ wuffs_gif__decoder__decode_lsd( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_lsd[0]; ++ uint32_t coro_susp_point = self->private_impl.p_init_dynamic_huffman; + if (coro_susp_point) { +- v_flags = self->private_data.s_decode_lsd[0].v_flags; +- v_background_color_index = self->private_data.s_decode_lsd[0].v_background_color_index; +- v_num_palette_entries = self->private_data.s_decode_lsd[0].v_num_palette_entries; +- v_i = self->private_data.s_decode_lsd[0].v_i; ++ v_bits = self->private_data.s_init_dynamic_huffman.v_bits; ++ v_n_bits = self->private_data.s_init_dynamic_huffman.v_n_bits; ++ v_n_lit = self->private_data.s_init_dynamic_huffman.v_n_lit; ++ v_n_dist = self->private_data.s_init_dynamic_huffman.v_n_dist; ++ v_n_clen = self->private_data.s_init_dynamic_huffman.v_n_clen; ++ v_i = self->private_data.s_init_dynamic_huffman.v_i; ++ v_mask = self->private_data.s_init_dynamic_huffman.v_mask; ++ v_n_extra_bits = self->private_data.s_init_dynamic_huffman.v_n_extra_bits; ++ v_rep_symbol = self->private_data.s_init_dynamic_huffman.v_rep_symbol; ++ v_rep_count = self->private_data.s_init_dynamic_huffman.v_rep_count; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_lsd[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { ++ v_bits = self->private_impl.f_bits; ++ v_n_bits = self->private_impl.f_n_bits; ++ while (v_n_bits < 14u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_0 = *iop_a_src++; ++ v_b0 = t_0; ++ } ++ v_bits |= (v_b0 << v_n_bits); ++ v_n_bits += 8u; ++ } ++ v_n_lit = (((v_bits) & 0x1Fu) + 257u); ++ if (v_n_lit > 286u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_literal_length_code_count); ++ goto exit; ++ } ++ v_bits >>= 5u; ++ v_n_dist = (((v_bits) & 0x1Fu) + 1u); ++ if (v_n_dist > 30u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_distance_code_count); ++ goto exit; ++ } ++ v_bits >>= 5u; ++ v_n_clen = (((v_bits) & 0xFu) + 4u); ++ v_bits >>= 4u; ++ v_n_bits -= 14u; ++ v_i = 0u; ++ while (v_i < v_n_clen) { ++ while (v_n_bits < 3u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; +- if (num_bits_0 == 8) { +- t_0 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ uint32_t t_1 = *iop_a_src++; ++ v_b1 = t_1; + } ++ v_bits |= (v_b1 << v_n_bits); ++ v_n_bits += 8u; + } +- self->private_impl.f_width = t_0; ++ self->private_data.f_code_lengths[WUFFS_DEFLATE__CODE_ORDER[v_i]] = ((uint8_t)((v_bits & 7u))); ++ v_bits >>= 3u; ++ v_n_bits -= 3u; ++ v_i += 1u; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_lsd[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { ++ while (v_i < 19u) { ++ self->private_data.f_code_lengths[WUFFS_DEFLATE__CODE_ORDER[v_i]] = 0u; ++ v_i += 1u; ++ } ++ v_status = wuffs_deflate__decoder__init_huff(self, ++ 0u, ++ 0u, ++ 19u, ++ 4095u); ++ if (wuffs_base__status__is_error(&v_status)) { ++ status = v_status; ++ goto exit; ++ } ++ v_mask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); ++ v_i = 0u; ++ while (v_i < (v_n_lit + v_n_dist)) { ++ while (true) { ++ v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_mask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ if (v_n_bits >= v_table_entry_n_bits) { ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ break; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; +- if (num_bits_1 == 8) { +- t_1 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ uint32_t t_2 = *iop_a_src++; ++ v_b2 = t_2; + } ++ v_bits |= (v_b2 << v_n_bits); ++ v_n_bits += 8u; + } +- self->private_impl.f_height = t_1; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ if ((v_table_entry >> 24u) != 128u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; + } +- uint8_t t_2 = *iop_a_src++; +- v_flags = t_2; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ v_table_entry = ((v_table_entry >> 8u) & 255u); ++ if (v_table_entry < 16u) { ++ self->private_data.f_code_lengths[v_i] = ((uint8_t)(v_table_entry)); ++ v_i += 1u; ++ continue; + } +- uint8_t t_3 = *iop_a_src++; +- v_background_color_index = t_3; +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src++; +- v_i = 0u; +- self->private_impl.f_has_global_palette = ((v_flags & 128u) != 0u); +- if (self->private_impl.f_has_global_palette) { +- v_num_palette_entries = (((uint32_t)(1u)) << (1u + (v_flags & 7u))); +- while (v_i < v_num_palette_entries) { ++ v_n_extra_bits = 0u; ++ v_rep_symbol = 0u; ++ v_rep_count = 0u; ++ if (v_table_entry == 16u) { ++ v_n_extra_bits = 2u; ++ if (v_i <= 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_repetition); ++ goto exit; ++ } ++ v_rep_symbol = ((uint8_t)(self->private_data.f_code_lengths[(v_i - 1u)] & 15u)); ++ v_rep_count = 3u; ++ } else if (v_table_entry == 17u) { ++ v_n_extra_bits = 3u; ++ v_rep_symbol = 0u; ++ v_rep_count = 3u; ++ } else if (v_table_entry == 18u) { ++ v_n_extra_bits = 7u; ++ v_rep_symbol = 0u; ++ v_rep_count = 11u; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } ++ while (v_n_bits < v_n_extra_bits) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- uint32_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { +- t_4 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src))); +- iop_a_src += 3; +- } else { +- self->private_data.s_decode_lsd[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); +- if (num_bits_4 == 16) { +- t_4 = ((uint32_t)(*scratch >> 40)); +- break; +- } +- num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)); +- } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- v_argb = t_4; ++ uint32_t t_3 = *iop_a_src++; ++ v_b3 = t_3; + } +- v_argb |= 4278190080u; +- self->private_data.f_palettes[0u][((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); +- self->private_data.f_palettes[0u][((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); +- self->private_data.f_palettes[0u][((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); +- self->private_data.f_palettes[0u][((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); +- v_i += 1u; ++ v_bits |= (v_b3 << v_n_bits); ++ v_n_bits += 8u; + } +- if (self->private_impl.f_quirks[2u]) { +- if ((v_background_color_index != 0u) && (((uint32_t)(v_background_color_index)) < v_num_palette_entries)) { +- v_j = (4u * ((uint32_t)(v_background_color_index))); +- self->private_impl.f_background_color_u32_argb_premul = ((((uint32_t)(self->private_data.f_palettes[0u][(v_j + 0u)])) << 0u) | +- (((uint32_t)(self->private_data.f_palettes[0u][(v_j + 1u)])) << 8u) | +- (((uint32_t)(self->private_data.f_palettes[0u][(v_j + 2u)])) << 16u) | +- (((uint32_t)(self->private_data.f_palettes[0u][(v_j + 3u)])) << 24u)); +- } else { +- self->private_impl.f_background_color_u32_argb_premul = 77u; ++ v_rep_count += ((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(v_n_extra_bits)); ++ v_bits >>= v_n_extra_bits; ++ v_n_bits -= v_n_extra_bits; ++ while (v_rep_count > 0u) { ++ if (v_i >= (v_n_lit + v_n_dist)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_count); ++ goto exit; + } ++ self->private_data.f_code_lengths[v_i] = v_rep_symbol; ++ v_i += 1u; ++ v_rep_count -= 1u; + } + } +- while (v_i < 256u) { +- self->private_data.f_palettes[0u][((4u * v_i) + 0u)] = 0u; +- self->private_data.f_palettes[0u][((4u * v_i) + 1u)] = 0u; +- self->private_data.f_palettes[0u][((4u * v_i) + 2u)] = 0u; +- self->private_data.f_palettes[0u][((4u * v_i) + 3u)] = 255u; +- v_i += 1u; ++ if (v_i != (v_n_lit + v_n_dist)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_count); ++ goto exit; ++ } ++ if (self->private_data.f_code_lengths[256u] == 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__missing_end_of_block_code); ++ goto exit; ++ } ++ v_status = wuffs_deflate__decoder__init_huff(self, ++ 0u, ++ 0u, ++ v_n_lit, ++ 257u); ++ if (wuffs_base__status__is_error(&v_status)) { ++ status = v_status; ++ goto exit; ++ } ++ v_status = wuffs_deflate__decoder__init_huff(self, ++ 1u, ++ v_n_lit, ++ (v_n_lit + v_n_dist), ++ 0u); ++ if (wuffs_base__status__is_error(&v_status)) { ++ status = v_status; ++ goto exit; + } ++ self->private_impl.f_bits = v_bits; ++ self->private_impl.f_n_bits = v_n_bits; + + goto ok; + ok: +- self->private_impl.p_decode_lsd[0] = 0; ++ self->private_impl.p_init_dynamic_huffman = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_lsd[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_lsd[0].v_flags = v_flags; +- self->private_data.s_decode_lsd[0].v_background_color_index = v_background_color_index; +- self->private_data.s_decode_lsd[0].v_num_palette_entries = v_num_palette_entries; +- self->private_data.s_decode_lsd[0].v_i = v_i; ++ self->private_impl.p_init_dynamic_huffman = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_init_dynamic_huffman.v_bits = v_bits; ++ self->private_data.s_init_dynamic_huffman.v_n_bits = v_n_bits; ++ self->private_data.s_init_dynamic_huffman.v_n_lit = v_n_lit; ++ self->private_data.s_init_dynamic_huffman.v_n_dist = v_n_dist; ++ self->private_data.s_init_dynamic_huffman.v_n_clen = v_n_clen; ++ self->private_data.s_init_dynamic_huffman.v_i = v_i; ++ self->private_data.s_init_dynamic_huffman.v_mask = v_mask; ++ self->private_data.s_init_dynamic_huffman.v_n_extra_bits = v_n_extra_bits; ++ self->private_data.s_init_dynamic_huffman.v_rep_symbol = v_rep_symbol; ++ self->private_data.s_init_dynamic_huffman.v_rep_count = v_rep_count; + + goto exit; + exit: +@@ -38093,185 +39348,299 @@ wuffs_gif__decoder__decode_lsd( + return status; + } + +-// -------- func gif.decoder.decode_extension ++// -------- func deflate.decoder.init_huff + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_extension( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint8_t v_label = 0; ++wuffs_deflate__decoder__init_huff( ++ wuffs_deflate__decoder* self, ++ uint32_t a_which, ++ uint32_t a_n_codes0, ++ uint32_t a_n_codes1, ++ uint32_t a_base_symbol) { ++ uint16_t v_counts[16] = {0}; ++ uint32_t v_i = 0; ++ uint32_t v_remaining = 0; ++ uint16_t v_offsets[16] = {0}; ++ uint32_t v_n_symbols = 0; ++ uint32_t v_count = 0; ++ uint16_t v_symbols[320] = {0}; ++ uint32_t v_min_cl = 0; ++ uint32_t v_max_cl = 0; ++ uint32_t v_initial_high_bits = 0; ++ uint32_t v_prev_cl = 0; ++ uint32_t v_prev_redirect_key = 0; ++ uint32_t v_top = 0; ++ uint32_t v_next_top = 0; ++ uint32_t v_code = 0; ++ uint32_t v_key = 0; ++ uint32_t v_value = 0; ++ uint32_t v_cl = 0; ++ uint32_t v_redirect_key = 0; ++ uint32_t v_j = 0; ++ uint32_t v_reversed_key = 0; ++ uint32_t v_symbol = 0; ++ uint32_t v_high_bits = 0; ++ uint32_t v_delta = 0; + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++ v_i = a_n_codes0; ++ while (v_i < a_n_codes1) { ++ if (v_counts[((uint8_t)(self->private_data.f_code_lengths[v_i] & 15u))] >= 320u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_counts[((uint8_t)(self->private_data.f_code_lengths[v_i] & 15u))] += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_i += 1u; + } +- +- uint32_t coro_susp_point = self->private_impl.p_decode_extension[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_label = t_0; ++ if ((((uint32_t)(v_counts[0u])) + a_n_codes0) == a_n_codes1) { ++ return wuffs_base__make_status(wuffs_deflate__error__no_huffman_codes); ++ } ++ v_remaining = 1u; ++ v_i = 1u; ++ while (v_i <= 15u) { ++ if (v_remaining > 1073741824u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); + } +- if (v_label == 249u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- status = wuffs_gif__decoder__decode_gc(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- status = wuffs_base__make_status(NULL); +- goto ok; +- } else if (v_label == 255u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_gif__decoder__decode_ae(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; ++ v_remaining <<= 1u; ++ if (v_remaining < ((uint32_t)(v_counts[v_i]))) { ++ return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_over_subscribed); ++ } ++ v_remaining -= ((uint32_t)(v_counts[v_i])); ++ v_i += 1u; ++ } ++ if (v_remaining != 0u) { ++ if ((a_which == 1u) && (v_counts[1u] == 1u) && ((((uint32_t)(v_counts[0u])) + a_n_codes0 + 1u) == a_n_codes1)) { ++ v_i = 0u; ++ while (v_i <= 29u) { ++ if (self->private_data.f_code_lengths[(a_n_codes0 + v_i)] == 1u) { ++ self->private_impl.f_n_huffs_bits[1u] = 1u; ++ self->private_data.f_huffs[1u][0u] = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[v_i] | 1u); ++ self->private_data.f_huffs[1u][1u] = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[31u] | 1u); ++ return wuffs_base__make_status(NULL); ++ } ++ v_i += 1u; + } +- status = wuffs_base__make_status(NULL); +- goto ok; + } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_under_subscribed); ++ } ++ v_i = 1u; ++ while (v_i <= 15u) { ++ v_offsets[v_i] = ((uint16_t)(v_n_symbols)); ++ v_count = ((uint32_t)(v_counts[v_i])); ++ if (v_n_symbols > (320u - v_count)) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- status = wuffs_gif__decoder__skip_blocks(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ v_n_symbols = (v_n_symbols + v_count); ++ v_i += 1u; ++ } ++ if (v_n_symbols > 288u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ v_i = a_n_codes0; ++ while (v_i < a_n_codes1) { ++ if (v_i < a_n_codes0) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); + } +- if (status.repr) { +- goto suspend; ++ if (self->private_data.f_code_lengths[v_i] != 0u) { ++ if (v_offsets[((uint8_t)(self->private_data.f_code_lengths[v_i] & 15u))] >= 320u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ v_symbols[v_offsets[((uint8_t)(self->private_data.f_code_lengths[v_i] & 15u))]] = ((uint16_t)((v_i - a_n_codes0))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_offsets[((uint8_t)(self->private_data.f_code_lengths[v_i] & 15u))] += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif + } +- +- ok: +- self->private_impl.p_decode_extension[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_extension[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ v_i += 1u; + } +- +- return status; +-} +- +-// -------- func gif.decoder.skip_blocks +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_gif__decoder__skip_blocks( +- wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint8_t v_block_size = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++ v_min_cl = 1u; ++ while (true) { ++ if (v_counts[v_min_cl] != 0u) { ++ break; ++ } ++ if (v_min_cl >= 9u) { ++ return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_minimum_code_length); ++ } ++ v_min_cl += 1u; + } +- +- uint32_t coro_susp_point = self->private_impl.p_skip_blocks[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ v_max_cl = 15u; ++ while (true) { ++ if (v_counts[v_max_cl] != 0u) { ++ break; ++ } ++ if (v_max_cl <= 1u) { ++ return wuffs_base__make_status(wuffs_deflate__error__no_huffman_codes); ++ } ++ v_max_cl -= 1u; ++ } ++ if (v_max_cl <= 9u) { ++ self->private_impl.f_n_huffs_bits[a_which] = v_max_cl; ++ } else { ++ self->private_impl.f_n_huffs_bits[a_which] = 9u; ++ } ++ v_i = 0u; ++ if ((v_n_symbols != ((uint32_t)(v_offsets[v_max_cl]))) || (v_n_symbols != ((uint32_t)(v_offsets[15u])))) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ if ((a_n_codes0 + ((uint32_t)(v_symbols[0u]))) >= 320u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ v_initial_high_bits = 512u; ++ if (v_max_cl < 9u) { ++ v_initial_high_bits = (((uint32_t)(1u)) << v_max_cl); ++ } ++ v_prev_cl = ((uint32_t)(((uint8_t)(self->private_data.f_code_lengths[(a_n_codes0 + ((uint32_t)(v_symbols[0u])))] & 15u)))); ++ v_prev_redirect_key = 4294967295u; ++ v_top = 0u; ++ v_next_top = 512u; ++ v_code = 0u; ++ v_key = 0u; ++ v_value = 0u; ++ while (true) { ++ if ((a_n_codes0 + ((uint32_t)(v_symbols[v_i]))) >= 320u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ v_cl = ((uint32_t)(((uint8_t)(self->private_data.f_code_lengths[(a_n_codes0 + ((uint32_t)(v_symbols[v_i])))] & 15u)))); ++ if (v_cl > v_prev_cl) { ++ v_code <<= (v_cl - v_prev_cl); ++ if (v_code >= 32768u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ } ++ v_prev_cl = v_cl; ++ v_key = v_code; ++ if (v_cl > 9u) { ++ v_cl -= 9u; ++ v_redirect_key = ((v_key >> v_cl) & 511u); ++ v_key = ((v_key) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(v_cl)); ++ if (v_prev_redirect_key != v_redirect_key) { ++ v_prev_redirect_key = v_redirect_key; ++ v_remaining = (((uint32_t)(1u)) << v_cl); ++ v_j = v_prev_cl; ++ while (v_j <= 15u) { ++ if (v_remaining <= ((uint32_t)(v_counts[v_j]))) { ++ break; ++ } ++ v_remaining -= ((uint32_t)(v_counts[v_j])); ++ if (v_remaining > 1073741824u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ v_remaining <<= 1u; ++ v_j += 1u; + } +- uint8_t t_0 = *iop_a_src++; +- v_block_size = t_0; ++ if ((v_j <= 9u) || (15u < v_j)) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ v_j -= 9u; ++ v_initial_high_bits = (((uint32_t)(1u)) << v_j); ++ v_top = v_next_top; ++ if ((v_top + (((uint32_t)(1u)) << v_j)) > 1024u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ v_next_top = (v_top + (((uint32_t)(1u)) << v_j)); ++ v_redirect_key = (((uint32_t)(WUFFS_DEFLATE__REVERSE8[(v_redirect_key >> 1u)])) | ((v_redirect_key & 1u) << 8u)); ++ self->private_data.f_huffs[a_which][v_redirect_key] = (268435465u | (v_top << 8u) | (v_j << 4u)); + } +- if (v_block_size == 0u) { +- status = wuffs_base__make_status(NULL); +- goto ok; ++ } ++ if ((v_key >= 512u) || (v_counts[v_prev_cl] <= 0u)) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_counts[v_prev_cl] -= 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_reversed_key = (((uint32_t)(WUFFS_DEFLATE__REVERSE8[(v_key >> 1u)])) | ((v_key & 1u) << 8u)); ++ v_reversed_key >>= (9u - v_cl); ++ v_symbol = ((uint32_t)(v_symbols[v_i])); ++ if (v_symbol == 256u) { ++ v_value = (536870912u | v_cl); ++ } else if ((v_symbol < 256u) && (a_which == 0u)) { ++ v_value = (2147483648u | (v_symbol << 8u) | v_cl); ++ } else if (v_symbol >= a_base_symbol) { ++ v_symbol -= a_base_symbol; ++ if (a_which == 0u) { ++ v_value = (WUFFS_DEFLATE__LCODE_MAGIC_NUMBERS[(v_symbol & 31u)] | v_cl); ++ } else { ++ v_value = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[(v_symbol & 31u)] | v_cl); + } +- self->private_data.s_skip_blocks[0].scratch = ((uint32_t)(v_block_size)); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (self->private_data.s_skip_blocks[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_skip_blocks[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ } else { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ } ++ v_high_bits = v_initial_high_bits; ++ v_delta = (((uint32_t)(1u)) << v_cl); ++ while (v_high_bits >= v_delta) { ++ v_high_bits -= v_delta; ++ if ((v_top + ((v_high_bits | v_reversed_key) & 511u)) >= 1024u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); + } +- iop_a_src += self->private_data.s_skip_blocks[0].scratch; ++ self->private_data.f_huffs[a_which][(v_top + ((v_high_bits | v_reversed_key) & 511u))] = v_value; ++ } ++ v_i += 1u; ++ if (v_i >= v_n_symbols) { ++ break; ++ } ++ v_code += 1u; ++ if (v_code >= 32768u) { ++ return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); + } +- +- ok: +- self->private_impl.p_skip_blocks[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_skip_blocks[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- +- return status; ++ return wuffs_base__make_status(NULL); + } + +-// -------- func gif.decoder.decode_ae ++// ‼ WUFFS MULTI-FILE SECTION +x86_bmi2 ++// -------- func deflate.decoder.decode_huffman_bmi2 + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("bmi2") + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_ae( +- wuffs_gif__decoder* self, ++wuffs_deflate__decoder__decode_huffman_bmi2( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint8_t v_block_size = 0; +- bool v_is_animexts = false; +- bool v_is_netscape = false; +- bool v_is_iccp = false; +- bool v_is_xmp = false; ++ uint64_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint32_t v_table_entry = 0; ++ uint32_t v_table_entry_n_bits = 0; ++ uint64_t v_lmask = 0; ++ uint64_t v_dmask = 0; ++ uint32_t v_redir_top = 0; ++ uint32_t v_redir_mask = 0; ++ uint32_t v_length = 0; ++ uint32_t v_dist_minus_1 = 0; ++ uint32_t v_hlen = 0; ++ uint32_t v_hdist = 0; ++ uint32_t v_hdist_adjustment = 0; + ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -38283,214 +39652,206 @@ wuffs_gif__decoder__decode_ae( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_ae[0]; +- if (coro_susp_point) { +- v_block_size = self->private_data.s_decode_ae[0].v_block_size; +- v_is_animexts = self->private_data.s_decode_ae[0].v_is_animexts; +- v_is_netscape = self->private_data.s_decode_ae[0].v_is_netscape; +- v_is_iccp = self->private_data.s_decode_ae[0].v_is_iccp; +- v_is_xmp = self->private_data.s_decode_ae[0].v_is_xmp; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ goto exit; + } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- do { +- if (self->private_impl.f_metadata_fourcc != 0u) { +- status = wuffs_base__make_status(wuffs_base__note__metadata_reported); +- goto ok; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_block_size = t_0; +- } +- if (v_block_size == 0u) { +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- if (v_block_size != 11u) { +- self->private_data.s_decode_ae[0].scratch = ((uint32_t)(v_block_size)); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_decode_ae[0].scratch; ++ v_bits = ((uint64_t)(self->private_impl.f_bits)); ++ v_n_bits = self->private_impl.f_n_bits; ++ v_lmask = ((((uint64_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); ++ v_dmask = ((((uint64_t)(1u)) << self->private_impl.f_n_huffs_bits[1u]) - 1u); ++ if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0u)) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position); ++ goto exit; ++ } ++ v_hdist_adjustment = ((uint32_t)((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0u)))); ++ label__loop__continue:; ++ while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 8u)) { ++ v_bits |= ((uint64_t)(wuffs_base__peek_u64le__no_bounds_check(iop_a_src) << (v_n_bits & 63u))); ++ iop_a_src += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_lmask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 31u) != 0u) { ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); ++ continue; ++ } else if ((v_table_entry >> 30u) != 0u) { ++ } else if ((v_table_entry >> 29u) != 0u) { ++ self->private_impl.f_end_of_block = true; ++ break; ++ } else if ((v_table_entry >> 28u) != 0u) { ++ v_redir_top = ((v_table_entry >> 8u) & 65535u); ++ v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); ++ v_table_entry = self->private_data.f_huffs[0u][((v_redir_top + (((uint32_t)(v_bits)) & v_redir_mask)) & 1023u)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 31u) != 0u) { ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); ++ continue; ++ } else if ((v_table_entry >> 30u) != 0u) { ++ } else if ((v_table_entry >> 29u) != 0u) { ++ self->private_impl.f_end_of_block = true; + break; ++ } else if ((v_table_entry >> 28u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } else if ((v_table_entry >> 27u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; + } +- v_is_animexts = true; +- v_is_netscape = true; +- v_is_iccp = true; +- v_is_xmp = true; +- v_block_size = 0u; +- while (v_block_size < 11u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; +- } +- v_is_animexts = (v_is_animexts && (v_c == WUFFS_GIF__ANIMEXTS1DOT0[v_block_size])); +- v_is_netscape = (v_is_netscape && (v_c == WUFFS_GIF__NETSCAPE2DOT0[v_block_size])); +- v_is_iccp = (v_is_iccp && (v_c == WUFFS_GIF__ICCRGBG1012[v_block_size])); +- v_is_xmp = (v_is_xmp && (v_c == WUFFS_GIF__XMPDATAXMP[v_block_size])); +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_block_size += 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif ++ } else if ((v_table_entry >> 27u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } ++ v_length = (((v_table_entry >> 8u) & 255u) + 3u); ++ v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); ++ if (v_table_entry_n_bits > 0u) { ++ v_length = (((v_length + 253u + ((uint32_t)(((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 255u) + 3u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ } ++ v_table_entry = self->private_data.f_huffs[1u][(v_bits & v_dmask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 28u) == 1u) { ++ v_redir_top = ((v_table_entry >> 8u) & 65535u); ++ v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); ++ v_table_entry = self->private_data.f_huffs[1u][((v_redir_top + (((uint32_t)(v_bits)) & v_redir_mask)) & 1023u)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ } ++ if ((v_table_entry >> 24u) != 64u) { ++ if ((v_table_entry >> 24u) == 8u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; + } +- if (v_is_animexts || v_is_netscape) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_2 = *iop_a_src++; +- v_block_size = t_2; +- } +- if (v_block_size != 3u) { +- self->private_data.s_decode_ae[0].scratch = ((uint32_t)(v_block_size)); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_decode_ae[0].scratch; +- break; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_3 = *iop_a_src++; +- v_c = t_3; ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } ++ v_dist_minus_1 = ((v_table_entry >> 8u) & 32767u); ++ v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); ++ v_dist_minus_1 = ((v_dist_minus_1 + ((uint32_t)(((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 32767u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ do { ++ if (((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) { ++ v_hlen = 0u; ++ v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1u))) - ((uint64_t)(iop_a_dst - io0_a_dst))))); ++ if (v_length > v_hdist) { ++ v_length -= v_hdist; ++ v_hlen = v_hdist; ++ } else { ++ v_hlen = v_length; ++ v_length = 0u; + } +- if (v_c != 1u) { +- self->private_data.s_decode_ae[0].scratch = 2u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_decode_ae[0].scratch; +- break; ++ v_hdist += v_hdist_adjustment; ++ if (self->private_impl.f_history_index < v_hdist) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_distance); ++ goto exit; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- uint32_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_4 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_ae[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_ae[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; +- if (num_bits_4 == 8) { +- t_4 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)) << 56; +- } +- } +- self->private_impl.f_num_animation_loops_value = t_4; ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767u), 33025)); ++ if (v_length == 0u) { ++ goto label__loop__continue; + } +- self->private_impl.f_seen_num_animation_loops_value = true; +- if ((0u < self->private_impl.f_num_animation_loops_value) && (self->private_impl.f_num_animation_loops_value <= 65535u)) { +- self->private_impl.f_num_animation_loops_value += 1u; ++ if ((((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8u))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance); ++ goto exit; + } +- } else if (self->private_impl.f_call_sequence >= 32u) { +- } else if (v_is_iccp && self->private_impl.f_report_metadata_iccp) { +- self->private_impl.f_metadata_fourcc = 1229144912u; +- self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- self->private_impl.f_call_sequence = 16u; +- status = wuffs_base__make_status(wuffs_base__note__metadata_reported); +- goto ok; +- } else if (v_is_xmp && self->private_impl.f_report_metadata_xmp) { +- self->private_impl.f_metadata_fourcc = 1481461792u; +- self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- self->private_impl.f_call_sequence = 16u; +- status = wuffs_base__make_status(wuffs_base__note__metadata_reported); +- goto ok; ++ } ++ if ((v_dist_minus_1 + 1u) >= 8u) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ } else if ((v_dist_minus_1 + 1u) == 1u) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ } else { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); + } + } while (0); +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- status = wuffs_gif__decoder__skip_blocks(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; ++ } ++ if (v_n_bits > 63u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ while (v_n_bits >= 8u) { ++ v_n_bits -= 8u; ++ if (iop_a_src > io1_a_src) { ++ iop_a_src--; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o); ++ goto exit; + } +- +- ok: +- self->private_impl.p_decode_ae[0] = 0; ++ } ++ self->private_impl.f_bits = ((uint32_t)((v_bits & ((((uint64_t)(1u)) << v_n_bits) - 1u)))); ++ self->private_impl.f_n_bits = v_n_bits; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); + goto exit; + } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_ae[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_ae[0].v_block_size = v_block_size; +- self->private_data.s_decode_ae[0].v_is_animexts = v_is_animexts; +- self->private_data.s_decode_ae[0].v_is_netscape = v_is_netscape; +- self->private_data.s_decode_ae[0].v_is_iccp = v_is_iccp; +- self->private_data.s_decode_ae[0].v_is_xmp = v_is_xmp; +- + goto exit; + exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + + return status; + } ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++// ‼ WUFFS MULTI-FILE SECTION -x86_bmi2 + +-// -------- func gif.decoder.decode_gc ++// -------- func deflate.decoder.decode_huffman_fast32 + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_gc( +- wuffs_gif__decoder* self, ++wuffs_deflate__decoder__decode_huffman_fast32( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint8_t v_flags = 0; +- uint16_t v_gc_duration_centiseconds = 0; ++ uint32_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint32_t v_table_entry = 0; ++ uint32_t v_table_entry_n_bits = 0; ++ uint32_t v_lmask = 0; ++ uint32_t v_dmask = 0; ++ uint32_t v_redir_top = 0; ++ uint32_t v_redir_mask = 0; ++ uint32_t v_length = 0; ++ uint32_t v_dist_minus_1 = 0; ++ uint32_t v_hlen = 0; ++ uint32_t v_hdist = 0; ++ uint32_t v_hdist_adjustment = 0; + ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -38502,106 +39863,205 @@ wuffs_gif__decoder__decode_gc( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_gc[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ v_bits = self->private_impl.f_bits; ++ v_n_bits = self->private_impl.f_n_bits; ++ v_lmask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); ++ v_dmask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[1u]) - 1u); ++ if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0u)) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position); ++ goto exit; ++ } ++ v_hdist_adjustment = ((uint32_t)((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0u)))); ++ label__loop__continue:; ++ while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 12u)) { ++ if (v_n_bits < 15u) { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ } else { + } +- if (v_c != 4u) { +- status = wuffs_base__make_status(wuffs_gif__error__bad_graphic_control); ++ v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_lmask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 31u) != 0u) { ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); ++ continue; ++ } else if ((v_table_entry >> 30u) != 0u) { ++ } else if ((v_table_entry >> 29u) != 0u) { ++ self->private_impl.f_end_of_block = true; ++ break; ++ } else if ((v_table_entry >> 28u) != 0u) { ++ if (v_n_bits < 15u) { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ } else { ++ } ++ v_redir_top = ((v_table_entry >> 8u) & 65535u); ++ v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); ++ v_table_entry = self->private_data.f_huffs[0u][((v_redir_top + (v_bits & v_redir_mask)) & 1023u)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 31u) != 0u) { ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); ++ continue; ++ } else if ((v_table_entry >> 30u) != 0u) { ++ } else if ((v_table_entry >> 29u) != 0u) { ++ self->private_impl.f_end_of_block = true; ++ break; ++ } else if ((v_table_entry >> 28u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } else if ((v_table_entry >> 27u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } ++ } else if ((v_table_entry >> 27u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); + goto exit; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ v_length = (((v_table_entry >> 8u) & 255u) + 3u); ++ v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); ++ if (v_table_entry_n_bits > 0u) { ++ if (v_n_bits < 15u) { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ } else { + } +- uint8_t t_1 = *iop_a_src++; +- v_flags = t_1; ++ v_length = (((v_length + 253u + ((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 255u) + 3u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ } else { + } +- self->private_impl.f_gc_has_transparent_index = ((v_flags & 1u) != 0u); +- v_flags = ((v_flags >> 2u) & 7u); +- if (v_flags == 2u) { +- self->private_impl.f_gc_disposal = 1u; +- } else if ((v_flags == 3u) || (v_flags == 4u)) { +- self->private_impl.f_gc_disposal = 2u; ++ if (v_n_bits < 15u) { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; + } else { +- self->private_impl.f_gc_disposal = 0u; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint16_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); +- iop_a_src += 2; ++ v_table_entry = self->private_data.f_huffs[1u][(v_bits & v_dmask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 28u) == 1u) { ++ if (v_n_bits < 15u) { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; + } else { +- self->private_data.s_decode_gc[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_gc[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; +- if (num_bits_2 == 8) { +- t_2 = ((uint16_t)(*scratch)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)) << 56; +- } + } +- v_gc_duration_centiseconds = t_2; ++ v_redir_top = ((v_table_entry >> 8u) & 65535u); ++ v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); ++ v_table_entry = self->private_data.f_huffs[1u][((v_redir_top + (v_bits & v_redir_mask)) & 1023u)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ } else { + } +- self->private_impl.f_gc_duration = (((uint64_t)(v_gc_duration_centiseconds)) * 7056000u); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ if ((v_table_entry >> 24u) != 64u) { ++ if ((v_table_entry >> 24u) == 8u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; + } +- uint8_t t_3 = *iop_a_src++; +- self->private_impl.f_gc_transparent_index = t_3; ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_4 = *iop_a_src++; +- v_c = t_4; ++ v_dist_minus_1 = ((v_table_entry >> 8u) & 32767u); ++ v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); ++ if (v_n_bits < v_table_entry_n_bits) { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; + } +- if (v_c != 0u) { +- status = wuffs_base__make_status(wuffs_gif__error__bad_graphic_control); ++ v_dist_minus_1 = ((v_dist_minus_1 + ((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 32767u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ do { ++ if (((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) { ++ v_hlen = 0u; ++ v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1u))) - ((uint64_t)(iop_a_dst - io0_a_dst))))); ++ if (v_length > v_hdist) { ++ v_length -= v_hdist; ++ v_hlen = v_hdist; ++ } else { ++ v_hlen = v_length; ++ v_length = 0u; ++ } ++ v_hdist += v_hdist_adjustment; ++ if (self->private_impl.f_history_index < v_hdist) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_distance); ++ goto exit; ++ } ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767u), 33025)); ++ if (v_length == 0u) { ++ goto label__loop__continue; ++ } ++ if ((((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8u))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance); ++ goto exit; ++ } ++ } ++ if ((v_dist_minus_1 + 1u) >= 8u) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ } else { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ } ++ } while (0); ++ } ++ while (v_n_bits >= 8u) { ++ v_n_bits -= 8u; ++ if (iop_a_src > io1_a_src) { ++ iop_a_src--; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o); + goto exit; + } +- +- goto ok; +- ok: +- self->private_impl.p_decode_gc[0] = 0; ++ } ++ self->private_impl.f_bits = (v_bits & ((((uint32_t)(1u)) << v_n_bits) - 1u)); ++ self->private_impl.f_n_bits = v_n_bits; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); + goto exit; + } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_gc[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- + goto exit; + exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -38609,15 +40069,52 @@ wuffs_gif__decoder__decode_gc( + return status; + } + +-// -------- func gif.decoder.decode_id_part0 ++// -------- func deflate.decoder.decode_huffman_fast64 + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_id_part0( +- wuffs_gif__decoder* self, ++wuffs_deflate__decoder__decode_huffman_fast64( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ return (*self->private_impl.choosy_decode_huffman_fast64)(self, a_dst, a_src); ++} ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_deflate__decoder__decode_huffman_fast64__choosy_default( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + ++ uint64_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint32_t v_table_entry = 0; ++ uint32_t v_table_entry_n_bits = 0; ++ uint64_t v_lmask = 0; ++ uint64_t v_dmask = 0; ++ uint32_t v_redir_top = 0; ++ uint32_t v_redir_mask = 0; ++ uint32_t v_length = 0; ++ uint32_t v_dist_minus_1 = 0; ++ uint32_t v_hlen = 0; ++ uint32_t v_hdist = 0; ++ uint32_t v_hdist_adjustment = 0; ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -38629,147 +40126,160 @@ wuffs_gif__decoder__decode_id_part0( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_id_part0[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ v_bits = ((uint64_t)(self->private_impl.f_bits)); ++ v_n_bits = self->private_impl.f_n_bits; ++ v_lmask = ((((uint64_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); ++ v_dmask = ((((uint64_t)(1u)) << self->private_impl.f_n_huffs_bits[1u]) - 1u); ++ if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0u)) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position); ++ goto exit; ++ } ++ v_hdist_adjustment = ((uint32_t)((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0u)))); ++ label__loop__continue:; ++ while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 8u)) { ++ v_bits |= ((uint64_t)(wuffs_base__peek_u64le__no_bounds_check(iop_a_src) << (v_n_bits & 63u))); ++ iop_a_src += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_lmask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 31u) != 0u) { ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); ++ continue; ++ } else if ((v_table_entry >> 30u) != 0u) { ++ } else if ((v_table_entry >> 29u) != 0u) { ++ self->private_impl.f_end_of_block = true; ++ break; ++ } else if ((v_table_entry >> 28u) != 0u) { ++ v_redir_top = ((v_table_entry >> 8u) & 65535u); ++ v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); ++ v_table_entry = self->private_data.f_huffs[0u][((v_redir_top + (((uint32_t)(v_bits)) & v_redir_mask)) & 1023u)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 31u) != 0u) { ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)((v_table_entry >> 8u)))), iop_a_dst += 1); ++ continue; ++ } else if ((v_table_entry >> 30u) != 0u) { ++ } else if ((v_table_entry >> 29u) != 0u) { ++ self->private_impl.f_end_of_block = true; ++ break; ++ } else if ((v_table_entry >> 28u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } else if ((v_table_entry >> 27u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; + } else { +- self->private_data.s_decode_id_part0[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; +- if (num_bits_0 == 8) { +- t_0 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)) << 56; +- } ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; + } +- self->private_impl.f_frame_rect_x0 = t_0; ++ } else if ((v_table_entry >> 27u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_id_part0[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; +- if (num_bits_1 == 8) { +- t_1 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)) << 56; +- } +- } +- self->private_impl.f_frame_rect_y0 = t_1; ++ v_length = (((v_table_entry >> 8u) & 255u) + 3u); ++ v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); ++ if (v_table_entry_n_bits > 0u) { ++ v_length = (((v_length + 253u + ((uint32_t)(((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 255u) + 3u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- uint32_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_2 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_id_part0[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; +- if (num_bits_2 == 8) { +- t_2 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)) << 56; +- } ++ v_table_entry = self->private_data.f_huffs[1u][(v_bits & v_dmask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ if ((v_table_entry >> 28u) == 1u) { ++ v_redir_top = ((v_table_entry >> 8u) & 65535u); ++ v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); ++ v_table_entry = self->private_data.f_huffs[1u][((v_redir_top + (((uint32_t)(v_bits)) & v_redir_mask)) & 1023u)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ } ++ if ((v_table_entry >> 24u) != 64u) { ++ if ((v_table_entry >> 24u) == 8u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; + } +- self->private_impl.f_frame_rect_x1 = t_2; ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; + } +- self->private_impl.f_frame_rect_x1 += self->private_impl.f_frame_rect_x0; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- uint32_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_3 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_id_part0[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; +- if (num_bits_3 == 8) { +- t_3 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ v_dist_minus_1 = ((v_table_entry >> 8u) & 32767u); ++ v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); ++ v_dist_minus_1 = ((v_dist_minus_1 + ((uint32_t)(((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 32767u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ do { ++ if (((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) { ++ v_hlen = 0u; ++ v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1u))) - ((uint64_t)(iop_a_dst - io0_a_dst))))); ++ if (v_length > v_hdist) { ++ v_length -= v_hdist; ++ v_hlen = v_hdist; ++ } else { ++ v_hlen = v_length; ++ v_length = 0u; ++ } ++ v_hdist += v_hdist_adjustment; ++ if (self->private_impl.f_history_index < v_hdist) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_distance); ++ goto exit; ++ } ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767u), 33025)); ++ if (v_length == 0u) { ++ goto label__loop__continue; ++ } ++ if ((((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8u))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance); ++ goto exit; + } + } +- self->private_impl.f_frame_rect_y1 = t_3; +- } +- self->private_impl.f_frame_rect_y1 += self->private_impl.f_frame_rect_y0; +- self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0; +- self->private_impl.f_dst_y = self->private_impl.f_frame_rect_y0; +- if ((self->private_impl.f_num_decoded_frame_configs_value == 0u) && ! self->private_impl.f_quirks[4u]) { +- self->private_impl.f_width = wuffs_base__u32__max(self->private_impl.f_width, self->private_impl.f_frame_rect_x1); +- self->private_impl.f_height = wuffs_base__u32__max(self->private_impl.f_height, self->private_impl.f_frame_rect_y1); ++ if ((v_dist_minus_1 + 1u) >= 8u) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ } else if ((v_dist_minus_1 + 1u) == 1u) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ } else { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ } ++ } while (0); ++ } ++ if (v_n_bits > 63u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ while (v_n_bits >= 8u) { ++ v_n_bits -= 8u; ++ if (iop_a_src > io1_a_src) { ++ iop_a_src--; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o); ++ goto exit; + } +- +- goto ok; +- ok: +- self->private_impl.p_decode_id_part0[0] = 0; ++ } ++ self->private_impl.f_bits = ((uint32_t)((v_bits & ((((uint64_t)(1u)) << v_n_bits) - 1u)))); ++ self->private_impl.f_n_bits = v_n_bits; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); + goto exit; + } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_id_part0[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- + goto exit; + exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -38777,25 +40287,49 @@ wuffs_gif__decoder__decode_id_part0( + return status; + } + +-// -------- func gif.decoder.decode_id_part1 ++// -------- func deflate.decoder.decode_huffman_slow + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_id_part1( +- wuffs_gif__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend) { ++wuffs_deflate__decoder__decode_huffman_slow( ++ wuffs_deflate__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_flags = 0; +- uint8_t v_which_palette = 0; +- uint32_t v_num_palette_entries = 0; +- uint32_t v_i = 0; +- uint32_t v_argb = 0; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- uint8_t v_lw = 0; ++ uint32_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint32_t v_table_entry = 0; ++ uint32_t v_table_entry_n_bits = 0; ++ uint32_t v_lmask = 0; ++ uint32_t v_dmask = 0; ++ uint32_t v_b0 = 0; ++ uint32_t v_redir_top = 0; ++ uint32_t v_redir_mask = 0; ++ uint32_t v_b1 = 0; ++ uint32_t v_length = 0; ++ uint32_t v_b2 = 0; ++ uint32_t v_b3 = 0; ++ uint32_t v_b4 = 0; ++ uint32_t v_dist_minus_1 = 0; ++ uint32_t v_b5 = 0; ++ uint32_t v_n_copied = 0; ++ uint32_t v_hlen = 0; ++ uint32_t v_hdist = 0; + ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -38807,139 +40341,275 @@ wuffs_gif__decoder__decode_id_part1( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_id_part1[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_huffman_slow; + if (coro_susp_point) { +- v_which_palette = self->private_data.s_decode_id_part1[0].v_which_palette; +- v_num_palette_entries = self->private_data.s_decode_id_part1[0].v_num_palette_entries; +- v_i = self->private_data.s_decode_id_part1[0].v_i; ++ v_bits = self->private_data.s_decode_huffman_slow.v_bits; ++ v_n_bits = self->private_data.s_decode_huffman_slow.v_n_bits; ++ v_table_entry_n_bits = self->private_data.s_decode_huffman_slow.v_table_entry_n_bits; ++ v_lmask = self->private_data.s_decode_huffman_slow.v_lmask; ++ v_dmask = self->private_data.s_decode_huffman_slow.v_dmask; ++ v_redir_top = self->private_data.s_decode_huffman_slow.v_redir_top; ++ v_redir_mask = self->private_data.s_decode_huffman_slow.v_redir_mask; ++ v_length = self->private_data.s_decode_huffman_slow.v_length; ++ v_dist_minus_1 = self->private_data.s_decode_huffman_slow.v_dist_minus_1; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_flags = t_0; +- } +- if ((v_flags & 64u) != 0u) { +- self->private_impl.f_interlace = 4u; +- } else { +- self->private_impl.f_interlace = 0u; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); ++ goto exit; + } +- v_which_palette = 1u; +- if ((v_flags & 128u) != 0u) { +- v_num_palette_entries = (((uint32_t)(1u)) << (1u + (v_flags & 7u))); +- v_i = 0u; +- while (v_i < v_num_palette_entries) { ++ v_bits = self->private_impl.f_bits; ++ v_n_bits = self->private_impl.f_n_bits; ++ v_lmask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[0u]) - 1u); ++ v_dmask = ((((uint32_t)(1u)) << self->private_impl.f_n_huffs_bits[1u]) - 1u); ++ label__loop__continue:; ++ while ( ! (self->private_impl.p_decode_huffman_slow != 0)) { ++ while (true) { ++ v_table_entry = self->private_data.f_huffs[0u][(v_bits & v_lmask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ if (v_n_bits >= v_table_entry_n_bits) { ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ break; ++ } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { +- t_1 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src))); +- iop_a_src += 3; +- } else { +- self->private_data.s_decode_id_part1[0].scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_0 = *iop_a_src++; ++ v_b0 = t_0; ++ } ++ v_bits |= (v_b0 << v_n_bits); ++ v_n_bits += 8u; ++ } ++ if ((v_table_entry >> 31u) != 0u) { ++ self->private_data.s_decode_huffman_slow.scratch = ((uint8_t)((v_table_entry >> 8u))); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (iop_a_dst == io2_a_dst) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ goto suspend; ++ } ++ *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_huffman_slow.scratch)); ++ continue; ++ } else if ((v_table_entry >> 30u) != 0u) { ++ } else if ((v_table_entry >> 29u) != 0u) { ++ self->private_impl.f_end_of_block = true; ++ break; ++ } else if ((v_table_entry >> 28u) != 0u) { ++ v_redir_top = ((v_table_entry >> 8u) & 65535u); ++ v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); ++ while (true) { ++ v_table_entry = self->private_data.f_huffs[0u][((v_redir_top + (v_bits & v_redir_mask)) & 1023u)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ if (v_n_bits >= v_table_entry_n_bits) { ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ break; ++ } ++ { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_id_part1[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); +- if (num_bits_1 == 16) { +- t_1 = ((uint32_t)(*scratch >> 40)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint32_t t_1 = *iop_a_src++; ++ v_b1 = t_1; + } +- v_argb = t_1; ++ v_bits |= (v_b1 << v_n_bits); ++ v_n_bits += 8u; + } +- v_argb |= 4278190080u; +- self->private_data.f_palettes[1u][((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); +- self->private_data.f_palettes[1u][((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); +- self->private_data.f_palettes[1u][((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); +- self->private_data.f_palettes[1u][((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); +- v_i += 1u; ++ if ((v_table_entry >> 31u) != 0u) { ++ self->private_data.s_decode_huffman_slow.scratch = ((uint8_t)((v_table_entry >> 8u))); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (iop_a_dst == io2_a_dst) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ goto suspend; ++ } ++ *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_huffman_slow.scratch)); ++ continue; ++ } else if ((v_table_entry >> 30u) != 0u) { ++ } else if ((v_table_entry >> 29u) != 0u) { ++ self->private_impl.f_end_of_block = true; ++ break; ++ } else if ((v_table_entry >> 28u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } else if ((v_table_entry >> 27u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; ++ } ++ } else if ((v_table_entry >> 27u) != 0u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); ++ goto exit; + } +- while (v_i < 256u) { +- self->private_data.f_palettes[1u][((4u * v_i) + 0u)] = 0u; +- self->private_data.f_palettes[1u][((4u * v_i) + 1u)] = 0u; +- self->private_data.f_palettes[1u][((4u * v_i) + 2u)] = 0u; +- self->private_data.f_palettes[1u][((4u * v_i) + 3u)] = 255u; +- v_i += 1u; ++ v_length = (((v_table_entry >> 8u) & 255u) + 3u); ++ v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); ++ if (v_table_entry_n_bits > 0u) { ++ while (v_n_bits < v_table_entry_n_bits) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_2 = *iop_a_src++; ++ v_b2 = t_2; ++ } ++ v_bits |= (v_b2 << v_n_bits); ++ v_n_bits += 8u; ++ } ++ v_length = (((v_length + 253u + ((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 255u) + 3u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; + } +- } else if (self->private_impl.f_quirks[6u] && ! self->private_impl.f_has_global_palette) { +- status = wuffs_base__make_status(wuffs_gif__error__bad_palette); +- goto exit; +- } else if (self->private_impl.f_gc_has_transparent_index) { +- wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_palettes[1u], 1024), wuffs_base__make_slice_u8(self->private_data.f_palettes[0u], 1024)); +- } else { +- v_which_palette = 0u; +- } +- if (self->private_impl.f_gc_has_transparent_index) { +- self->private_data.f_palettes[1u][((4u * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 0u)] = 0u; +- self->private_data.f_palettes[1u][((4u * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 1u)] = 0u; +- self->private_data.f_palettes[1u][((4u * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 2u)] = 0u; +- self->private_data.f_palettes[1u][((4u * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 3u)] = 0u; +- } +- v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, +- wuffs_base__pixel_buffer__pixel_format(a_dst), +- wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), +- wuffs_base__utility__make_pixel_format(2198077448u), +- wuffs_base__make_slice_u8(self->private_data.f_palettes[v_which_palette], 1024), +- a_blend); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ while (true) { ++ v_table_entry = self->private_data.f_huffs[1u][(v_bits & v_dmask)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ if (v_n_bits >= v_table_entry_n_bits) { ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ break; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_3 = *iop_a_src++; ++ v_b3 = t_3; ++ } ++ v_bits |= (v_b3 << v_n_bits); ++ v_n_bits += 8u; ++ } ++ if ((v_table_entry >> 28u) == 1u) { ++ v_redir_top = ((v_table_entry >> 8u) & 65535u); ++ v_redir_mask = ((((uint32_t)(1u)) << ((v_table_entry >> 4u) & 15u)) - 1u); ++ while (true) { ++ v_table_entry = self->private_data.f_huffs[1u][((v_redir_top + (v_bits & v_redir_mask)) & 1023u)]; ++ v_table_entry_n_bits = (v_table_entry & 15u); ++ if (v_n_bits >= v_table_entry_n_bits) { ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ break; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_4 = *iop_a_src++; ++ v_b4 = t_4; ++ } ++ v_bits |= (v_b4 << v_n_bits); ++ v_n_bits += 8u; ++ } ++ } ++ if ((v_table_entry >> 24u) != 64u) { ++ if ((v_table_entry >> 24u) == 8u) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state); + goto exit; + } +- goto ok; +- } +- if (self->private_impl.f_ignored_but_affects_benchmarks) { +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ v_dist_minus_1 = ((v_table_entry >> 8u) & 32767u); ++ v_table_entry_n_bits = ((v_table_entry >> 4u) & 15u); ++ if (v_table_entry_n_bits > 0u) { ++ while (v_n_bits < v_table_entry_n_bits) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_5 = *iop_a_src++; ++ v_b5 = t_5; ++ } ++ v_bits |= (v_b5 << v_n_bits); ++ v_n_bits += 8u; ++ } ++ v_dist_minus_1 = ((v_dist_minus_1 + ((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 32767u); ++ v_bits >>= v_table_entry_n_bits; ++ v_n_bits -= v_table_entry_n_bits; ++ } ++ while (true) { ++ if (((uint64_t)((v_dist_minus_1 + 1u))) > ((uint64_t)(iop_a_dst - io0_a_dst))) { ++ v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1u))) - ((uint64_t)(iop_a_dst - io0_a_dst))))); ++ if (v_hdist < v_length) { ++ v_hlen = v_hdist; ++ } else { ++ v_hlen = v_length; ++ } ++ v_hdist += ((uint32_t)(((uint64_t)(self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0u))))); ++ if (self->private_impl.f_history_index < v_hdist) { ++ status = wuffs_base__make_status(wuffs_deflate__error__bad_distance); ++ goto exit; ++ } ++ v_n_copied = wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767u), 33025)); ++ if (v_n_copied < v_hlen) { ++ v_length -= v_n_copied; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); ++ continue; ++ } ++ v_length -= v_hlen; ++ if (v_length == 0u) { ++ goto label__loop__continue; ++ } ++ } ++ v_n_copied = wuffs_private_impl__io_writer__limited_copy_u32_from_history( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1u)); ++ if (v_length <= v_n_copied) { ++ goto label__loop__continue; ++ } ++ v_length -= v_n_copied; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); + } +- uint8_t t_2 = *iop_a_src++; +- v_lw = t_2; + } +- if (v_lw > 8u) { +- status = wuffs_base__make_status(wuffs_gif__error__bad_literal_width); ++ self->private_impl.f_bits = v_bits; ++ self->private_impl.f_n_bits = v_n_bits; ++ if ((self->private_impl.f_n_bits >= 8u) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7u)) != 0u)) { ++ status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits); + goto exit; + } +- self->private_impl.f_lzw_pending_literal_width_plus_one = ((uint32_t)((1u + v_lw))); +- self->private_impl.f_ignored_but_affects_benchmarks = true; + + ok: +- self->private_impl.p_decode_id_part1[0] = 0; ++ self->private_impl.p_decode_huffman_slow = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_id_part1[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_id_part1[0].v_which_palette = v_which_palette; +- self->private_data.s_decode_id_part1[0].v_num_palette_entries = v_num_palette_entries; +- self->private_data.s_decode_id_part1[0].v_i = v_i; ++ self->private_impl.p_decode_huffman_slow = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_huffman_slow.v_bits = v_bits; ++ self->private_data.s_decode_huffman_slow.v_n_bits = v_n_bits; ++ self->private_data.s_decode_huffman_slow.v_table_entry_n_bits = v_table_entry_n_bits; ++ self->private_data.s_decode_huffman_slow.v_lmask = v_lmask; ++ self->private_data.s_decode_huffman_slow.v_dmask = v_dmask; ++ self->private_data.s_decode_huffman_slow.v_redir_top = v_redir_top; ++ self->private_data.s_decode_huffman_slow.v_redir_mask = v_redir_mask; ++ self->private_data.s_decode_huffman_slow.v_length = v_length; ++ self->private_data.s_decode_huffman_slow.v_dist_minus_1 = v_dist_minus_1; + + goto exit; + exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -38947,782 +40617,538 @@ wuffs_gif__decoder__decode_id_part1( + return status; + } + +-// -------- func gif.decoder.decode_id_part2 ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_gif__error__bad_lzw_code[] = "#gif: bad LZW code"; ++const char wuffs_gif__error__bad_extension_label[] = "#gif: bad extension label"; ++const char wuffs_gif__error__bad_frame_size[] = "#gif: bad frame size"; ++const char wuffs_gif__error__bad_graphic_control[] = "#gif: bad graphic control"; ++const char wuffs_gif__error__bad_header[] = "#gif: bad header"; ++const char wuffs_gif__error__bad_literal_width[] = "#gif: bad literal width"; ++const char wuffs_gif__error__bad_palette[] = "#gif: bad palette"; ++const char wuffs_gif__error__truncated_input[] = "#gif: truncated input"; ++const char wuffs_gif__error__internal_error_inconsistent_i_o[] = "#gif: internal error: inconsistent I/O"; ++ ++// ---------------- Private Consts ++ ++static const uint32_t ++WUFFS_GIF__INTERLACE_START[5] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 4294967295u, 1u, 2u, 4u, 0u, ++}; ++ ++static const uint8_t ++WUFFS_GIF__INTERLACE_DELTA[5] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1u, 2u, 4u, 8u, 8u, ++}; ++ ++static const uint8_t ++WUFFS_GIF__INTERLACE_COUNT[5] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 1u, 2u, 4u, 8u, ++}; ++ ++static const uint8_t ++WUFFS_GIF__ANIMEXTS1DOT0[11] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 65u, 78u, 73u, 77u, 69u, 88u, 84u, 83u, ++ 49u, 46u, 48u, ++}; ++ ++static const uint8_t ++WUFFS_GIF__NETSCAPE2DOT0[11] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 78u, 69u, 84u, 83u, 67u, 65u, 80u, 69u, ++ 50u, 46u, 48u, ++}; ++ ++static const uint8_t ++WUFFS_GIF__ICCRGBG1012[11] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 73u, 67u, 67u, 82u, 71u, 66u, 71u, 49u, ++ 48u, 49u, 50u, ++}; ++ ++static const uint8_t ++WUFFS_GIF__XMPDATAXMP[11] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 88u, 77u, 80u, 32u, 68u, 97u, 116u, 97u, ++ 88u, 77u, 80u, ++}; ++ ++#define WUFFS_GIF__QUIRKS_BASE 1041635328u ++ ++#define WUFFS_GIF__QUIRKS_COUNT 7u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gif__decoder__decode_id_part2( ++wuffs_gif__decoder__do_decode_image_config( ++ wuffs_gif__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__do_tell_me_more( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__do_decode_frame_config( ++ wuffs_gif__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__skip_frame( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__do_decode_frame( + wuffs_gif__decoder* self, + wuffs_base__pixel_buffer* a_dst, + wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint64_t v_block_size = 0; +- bool v_need_block_size = false; +- uint32_t v_n_copied = 0; +- uint64_t v_n_compressed = 0; +- wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_r = &u_r; +- const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint64_t v_mark = 0; +- wuffs_base__status v_copy_status = wuffs_base__make_status(NULL); ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_gif__decoder__reset_gc( ++ wuffs_gif__decoder* self); + +- uint32_t coro_susp_point = self->private_impl.p_decode_id_part2[0]; +- if (coro_susp_point) { +- v_block_size = self->private_data.s_decode_id_part2[0].v_block_size; +- v_need_block_size = self->private_data.s_decode_id_part2[0].v_need_block_size; +- } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_up_to_id_part1( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); + +- wuffs_gif__decoder__lzw_init(self); +- v_need_block_size = true; +- label__outer__continue:; +- while (true) { +- if (v_need_block_size) { +- v_need_block_size = false; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t t_0 = *iop_a_src++; +- v_block_size = t_0; +- } +- } +- if (v_block_size == 0u) { +- break; +- } +- while (((uint64_t)(io2_a_src - iop_a_src)) == 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- } +- if (self->private_impl.f_compressed_ri == self->private_impl.f_compressed_wi) { +- self->private_impl.f_compressed_ri = 0u; +- self->private_impl.f_compressed_wi = 0u; +- } +- while (self->private_impl.f_compressed_wi <= 3841u) { +- v_n_compressed = wuffs_base__u64__min(v_block_size, ((uint64_t)(io2_a_src - iop_a_src))); +- if (v_n_compressed <= 0u) { +- break; +- } +- v_n_copied = wuffs_base__io_reader__limited_copy_u32_to_slice( +- &iop_a_src, io2_a_src,((uint32_t)(v_n_compressed)), wuffs_base__make_slice_u8_ij(self->private_data.f_compressed, self->private_impl.f_compressed_wi, 4096)); +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_compressed_wi, ((uint64_t)(v_n_copied))); +- wuffs_base__u64__sat_sub_indirect(&v_block_size, ((uint64_t)(v_n_copied))); +- if (v_block_size > 0u) { +- break; +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- v_need_block_size = true; +- break; +- } +- v_block_size = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))); +- iop_a_src += 1u; +- } +- while (true) { +- if ((self->private_impl.f_compressed_ri > self->private_impl.f_compressed_wi) || (self->private_impl.f_compressed_wi > 4096u)) { +- status = wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- { +- wuffs_base__io_buffer* o_0_v_r = v_r; +- const uint8_t *o_0_iop_v_r = iop_v_r; +- const uint8_t *o_0_io0_v_r = io0_v_r; +- const uint8_t *o_0_io1_v_r = io1_v_r; +- const uint8_t *o_0_io2_v_r = io2_v_r; +- v_r = wuffs_base__io_reader__set( +- &u_r, +- &iop_v_r, +- &io0_v_r, +- &io1_v_r, +- &io2_v_r, +- wuffs_base__make_slice_u8_ij(self->private_data.f_compressed, +- self->private_impl.f_compressed_ri, +- self->private_impl.f_compressed_wi), +- 0u); +- v_mark = ((uint64_t)(iop_v_r - io0_v_r)); +- u_r.meta.ri = ((size_t)(iop_v_r - u_r.data.ptr)); +- wuffs_gif__decoder__lzw_read_from(self, v_r); +- iop_v_r = u_r.data.ptr + u_r.meta.ri; +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_compressed_ri, wuffs_base__io__count_since(v_mark, ((uint64_t)(iop_v_r - io0_v_r)))); +- v_r = o_0_v_r; +- iop_v_r = o_0_iop_v_r; +- io0_v_r = o_0_io0_v_r; +- io1_v_r = o_0_io1_v_r; +- io2_v_r = o_0_io2_v_r; +- } +- if (self->private_impl.f_lzw_output_ri < self->private_impl.f_lzw_output_wi) { +- v_copy_status = wuffs_gif__decoder__copy_to_image_buffer(self, a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_lzw_output, +- self->private_impl.f_lzw_output_ri, +- self->private_impl.f_lzw_output_wi)); +- if (wuffs_base__status__is_error(&v_copy_status)) { +- status = v_copy_status; +- goto exit; +- } +- self->private_impl.f_lzw_output_ri = 0u; +- self->private_impl.f_lzw_output_wi = 0u; +- } +- if (self->private_impl.f_lzw_read_from_return_value == 0u) { +- self->private_impl.f_ignored_but_affects_benchmarks = false; +- if (v_need_block_size || (v_block_size > 0u)) { +- self->private_data.s_decode_id_part2[0].scratch = ((uint32_t)(v_block_size)); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (self->private_data.s_decode_id_part2[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_decode_id_part2[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_decode_id_part2[0].scratch; +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- status = wuffs_gif__decoder__skip_blocks(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } +- goto label__outer__break; +- } else if (self->private_impl.f_lzw_read_from_return_value == 1u) { +- continue; +- } else if (self->private_impl.f_lzw_read_from_return_value == 2u) { +- goto label__outer__continue; +- } else if (self->private_impl.f_quirks[3u] && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1) && (self->private_impl.f_interlace == 0u)) { +- if (v_need_block_size || (v_block_size > 0u)) { +- self->private_data.s_decode_id_part2[0].scratch = ((uint32_t)(v_block_size)); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (self->private_data.s_decode_id_part2[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_decode_id_part2[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_decode_id_part2[0].scratch; +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- status = wuffs_gif__decoder__skip_blocks(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } +- goto label__outer__break; +- } else if (self->private_impl.f_lzw_read_from_return_value == 3u) { +- status = wuffs_base__make_status(wuffs_gif__error__truncated_input); +- goto exit; +- } else if (self->private_impl.f_lzw_read_from_return_value == 4u) { +- status = wuffs_base__make_status(wuffs_gif__error__bad_lzw_code); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- } +- label__outer__break:; +- self->private_impl.f_compressed_ri = 0u; +- self->private_impl.f_compressed_wi = 0u; +- if ((self->private_impl.f_dst_y < self->private_impl.f_frame_rect_y1) && (self->private_impl.f_frame_rect_x0 != self->private_impl.f_frame_rect_x1) && (self->private_impl.f_frame_rect_y0 != self->private_impl.f_frame_rect_y1)) { +- status = wuffs_base__make_status(wuffs_base__error__not_enough_data); +- goto exit; +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_header( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); + +- ok: +- self->private_impl.p_decode_id_part2[0] = 0; +- goto exit; +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_lsd( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); + +- goto suspend; +- suspend: +- self->private_impl.p_decode_id_part2[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_id_part2[0].v_block_size = v_block_size; +- self->private_data.s_decode_id_part2[0].v_need_block_size = v_need_block_size; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_extension( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__skip_blocks( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); + +- return status; +-} ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_ae( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); + +-// -------- func gif.decoder.copy_to_image_buffer ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_gc( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_id_part0( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_id_part1( ++ wuffs_gif__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_id_part2( ++ wuffs_gif__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status + wuffs_gif__decoder__copy_to_image_buffer( + wuffs_gif__decoder* self, + wuffs_base__pixel_buffer* a_pb, +- wuffs_base__slice_u8 a_src) { +- wuffs_base__slice_u8 v_dst = {0}; +- wuffs_base__slice_u8 v_src = {0}; +- uint64_t v_width_in_bytes = 0; +- uint64_t v_n = 0; +- uint64_t v_src_ri = 0; +- wuffs_base__pixel_format v_pixfmt = {0}; +- uint32_t v_bytes_per_pixel = 0; +- uint32_t v_bits_per_pixel = 0; +- wuffs_base__table_u8 v_tab = {0}; +- uint64_t v_i = 0; +- uint64_t v_j = 0; +- uint32_t v_replicate_y0 = 0; +- uint32_t v_replicate_y1 = 0; +- wuffs_base__slice_u8 v_replicate_dst = {0}; +- wuffs_base__slice_u8 v_replicate_src = {0}; ++ wuffs_base__slice_u8 a_src); + +- v_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_pb); +- v_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_pixfmt); +- if ((v_bits_per_pixel & 7u) != 0u) { +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_gif__decoder__lzw_init( ++ wuffs_gif__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_gif__decoder__lzw_read_from( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++// ---------------- VTables ++ ++const wuffs_base__image_decoder__func_ptrs ++wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_gif__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_gif__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_gif__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_gif__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_gif__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_gif__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_gif__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_gif__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_gif__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_gif__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_gif__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_gif__decoder__initialize( ++ wuffs_gif__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- v_bytes_per_pixel = (v_bits_per_pixel >> 3u); +- v_width_in_bytes = ((uint64_t)((self->private_impl.f_width * v_bytes_per_pixel))); +- v_tab = wuffs_base__pixel_buffer__plane(a_pb, 0u); +- while (v_src_ri < ((uint64_t)(a_src.len))) { +- v_src = wuffs_base__slice_u8__subslice_i(a_src, v_src_ri); +- if (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1) { +- if (self->private_impl.f_quirks[3u]) { +- return wuffs_base__make_status(NULL); +- } +- return wuffs_base__make_status(wuffs_base__error__too_much_data); +- } +- v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (self->private_impl.f_dst_y >= self->private_impl.f_height) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, 0u); +- } else if (v_width_in_bytes < ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_width_in_bytes); +- } +- v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_bytes_per_pixel))); +- if (v_i < ((uint64_t)(v_dst.len))) { +- v_j = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * ((uint64_t)(v_bytes_per_pixel))); +- if ((v_i <= v_j) && (v_j <= ((uint64_t)(v_dst.len)))) { +- v_dst = wuffs_base__slice_u8__subslice_ij(v_dst, v_i, v_j); +- } else { +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i); +- } +- v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024), v_src); +- wuffs_base__u64__sat_add_indirect(&v_src_ri, v_n); +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); +- self->private_impl.f_dirty_max_excl_y = wuffs_base__u32__max(self->private_impl.f_dirty_max_excl_y, wuffs_base__u32__sat_add(self->private_impl.f_dst_y, 1u)); +- } +- if (self->private_impl.f_frame_rect_x1 <= self->private_impl.f_dst_x) { +- self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0; +- if (self->private_impl.f_interlace == 0u) { +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, 1u); +- continue; +- } +- if ((self->private_impl.f_num_decoded_frames_value == 0u) && ! self->private_impl.f_gc_has_transparent_index && (self->private_impl.f_interlace > 1u)) { +- v_replicate_src = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- v_replicate_y0 = wuffs_base__u32__sat_add(self->private_impl.f_dst_y, 1u); +- v_replicate_y1 = wuffs_base__u32__sat_add(self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_COUNT[self->private_impl.f_interlace]))); +- v_replicate_y1 = wuffs_base__u32__min(v_replicate_y1, self->private_impl.f_frame_rect_y1); +- while (v_replicate_y0 < v_replicate_y1) { +- v_replicate_dst = wuffs_base__table_u8__row_u32(v_tab, v_replicate_y0); +- wuffs_base__slice_u8__copy_from_slice(v_replicate_dst, v_replicate_src); +- v_replicate_y0 += 1u; +- } +- self->private_impl.f_dirty_max_excl_y = wuffs_base__u32__max(self->private_impl.f_dirty_max_excl_y, v_replicate_y1); +- } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_DELTA[self->private_impl.f_interlace]))); +- while ((self->private_impl.f_interlace > 0u) && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1)) { +-#if defined(__GNUC__) ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) + #pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_impl.f_interlace -= 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + #endif +- self->private_impl.f_dst_y = wuffs_base__u32__sat_add(self->private_impl.f_frame_rect_y0, WUFFS_GIF__INTERLACE_START[self->private_impl.f_interlace]); +- } +- continue; +- } +- if (((uint64_t)(a_src.len)) == v_src_ri) { +- break; +- } else if (((uint64_t)(a_src.len)) < v_src_ri) { +- return wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_i_o); ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); + } +- v_n = ((uint64_t)((self->private_impl.f_frame_rect_x1 - self->private_impl.f_dst_x))); +- v_n = wuffs_base__u64__min(v_n, (((uint64_t)(a_src.len)) - v_src_ri)); +- wuffs_base__u64__sat_add_indirect(&v_src_ri, v_n); +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); +- if (self->private_impl.f_frame_rect_x1 <= self->private_impl.f_dst_x) { +- self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0; +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_DELTA[self->private_impl.f_interlace]))); +- while ((self->private_impl.f_interlace > 0u) && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1)) { +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_impl.f_interlace -= 1u; +-#if defined(__GNUC__) ++#if !defined(__clang__) && defined(__GNUC__) + #pragma GCC diagnostic pop + #endif +- self->private_impl.f_dst_y = wuffs_base__u32__sat_add(self->private_impl.f_frame_rect_y0, WUFFS_GIF__INTERLACE_START[self->private_impl.f_interlace]); +- } +- continue; +- } +- if (v_src_ri != ((uint64_t)(a_src.len))) { +- return wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_i_o); ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); + } +- break; + } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder); + return wuffs_base__make_status(NULL); + } + +-// -------- func gif.decoder.lzw_init ++wuffs_gif__decoder* ++wuffs_gif__decoder__alloc(void) { ++ wuffs_gif__decoder* x = ++ (wuffs_gif__decoder*)(calloc(1, sizeof(wuffs_gif__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_gif__decoder__initialize( ++ x, sizeof(wuffs_gif__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_gif__decoder__lzw_init( +- wuffs_gif__decoder* self) { +- uint32_t v_i = 0; ++size_t ++sizeof__wuffs_gif__decoder(void) { ++ return sizeof(wuffs_gif__decoder); ++} + +- self->private_impl.f_lzw_literal_width = 8u; +- if (self->private_impl.f_lzw_pending_literal_width_plus_one > 0u) { +- self->private_impl.f_lzw_literal_width = (self->private_impl.f_lzw_pending_literal_width_plus_one - 1u); ++// ---------------- Function Implementations ++ ++// -------- func gif.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_gif__decoder__get_quirk( ++ const wuffs_gif__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; + } +- self->private_impl.f_lzw_clear_code = (((uint32_t)(1u)) << self->private_impl.f_lzw_literal_width); +- self->private_impl.f_lzw_end_code = (self->private_impl.f_lzw_clear_code + 1u); +- self->private_impl.f_lzw_save_code = self->private_impl.f_lzw_end_code; +- self->private_impl.f_lzw_prev_code = self->private_impl.f_lzw_end_code; +- self->private_impl.f_lzw_width = (self->private_impl.f_lzw_literal_width + 1u); +- self->private_impl.f_lzw_bits = 0u; +- self->private_impl.f_lzw_n_bits = 0u; +- self->private_impl.f_lzw_output_ri = 0u; +- self->private_impl.f_lzw_output_wi = 0u; +- v_i = 0u; +- while (v_i < self->private_impl.f_lzw_clear_code) { +- self->private_data.f_lzw_lm1s[v_i] = 0u; +- self->private_data.f_lzw_suffixes[v_i][0u] = ((uint8_t)(v_i)); +- v_i += 1u; ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } +- return wuffs_base__make_empty_struct(); ++ ++ uint32_t v_key = 0; ++ ++ if (a_key >= 1041635328u) { ++ v_key = (a_key - 1041635328u); ++ if (v_key < 7u) { ++ if (self->private_impl.f_quirks[v_key]) { ++ return 1u; ++ } ++ } ++ } ++ return 0u; + } + +-// -------- func gif.decoder.lzw_read_from ++// -------- func gif.decoder.set_quirk + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_gif__decoder__lzw_read_from( ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_gif__decoder__set_quirk( + wuffs_gif__decoder* self, +- wuffs_base__io_buffer* a_src) { +- uint32_t v_clear_code = 0; +- uint32_t v_end_code = 0; +- uint32_t v_save_code = 0; +- uint32_t v_prev_code = 0; +- uint32_t v_width = 0; +- uint32_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint32_t v_output_wi = 0; +- uint32_t v_code = 0; +- uint32_t v_c = 0; +- uint32_t v_o = 0; +- uint32_t v_steps = 0; +- uint8_t v_first_byte = 0; +- uint16_t v_lm1_b = 0; +- uint16_t v_lm1_a = 0; ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++ if ((self->private_impl.f_call_sequence == 0u) && (a_key >= 1041635328u)) { ++ a_key -= 1041635328u; ++ if (a_key < 7u) { ++ self->private_impl.f_quirks[a_key] = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } + } ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} + +- v_clear_code = self->private_impl.f_lzw_clear_code; +- v_end_code = self->private_impl.f_lzw_end_code; +- v_save_code = self->private_impl.f_lzw_save_code; +- v_prev_code = self->private_impl.f_lzw_prev_code; +- v_width = self->private_impl.f_lzw_width; +- v_bits = self->private_impl.f_lzw_bits; +- v_n_bits = self->private_impl.f_lzw_n_bits; +- v_output_wi = self->private_impl.f_lzw_output_wi; +- while (true) { +- if (v_n_bits < v_width) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= 4u) { +- v_bits |= ((uint32_t)(wuffs_base__peek_u32le__no_bounds_check(iop_a_src) << v_n_bits)); +- iop_a_src += ((31u - v_n_bits) >> 3u); +- v_n_bits |= 24u; +- } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_src && a_src->meta.closed) { +- self->private_impl.f_lzw_read_from_return_value = 3u; +- } else { +- self->private_impl.f_lzw_read_from_return_value = 2u; +- } +- break; +- } else { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- if (v_n_bits >= v_width) { +- } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_src && a_src->meta.closed) { +- self->private_impl.f_lzw_read_from_return_value = 3u; +- } else { +- self->private_impl.f_lzw_read_from_return_value = 2u; +- } +- break; +- } else { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- if (v_n_bits < v_width) { +- self->private_impl.f_lzw_read_from_return_value = 5u; +- break; +- } +- } +- } +- } +- v_code = ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_width)); +- v_bits >>= v_width; +- v_n_bits -= v_width; +- if (v_code < v_clear_code) { +- self->private_data.f_lzw_output[v_output_wi] = ((uint8_t)(v_code)); +- v_output_wi = ((v_output_wi + 1u) & 8191u); +- if (v_save_code <= 4095u) { +- v_lm1_a = (((uint16_t)(self->private_data.f_lzw_lm1s[v_prev_code] + 1u)) & 4095u); +- self->private_data.f_lzw_lm1s[v_save_code] = v_lm1_a; +- if ((v_lm1_a % 8u) != 0u) { +- self->private_impl.f_lzw_prefixes[v_save_code] = self->private_impl.f_lzw_prefixes[v_prev_code]; +- memcpy(self->private_data.f_lzw_suffixes[v_save_code],self->private_data.f_lzw_suffixes[v_prev_code], sizeof(self->private_data.f_lzw_suffixes[v_save_code])); +- self->private_data.f_lzw_suffixes[v_save_code][(v_lm1_a % 8u)] = ((uint8_t)(v_code)); +- } else { +- self->private_impl.f_lzw_prefixes[v_save_code] = ((uint16_t)(v_prev_code)); +- self->private_data.f_lzw_suffixes[v_save_code][0u] = ((uint8_t)(v_code)); +- } +- v_save_code += 1u; +- if (v_width < 12u) { +- v_width += (1u & (v_save_code >> v_width)); +- } +- v_prev_code = v_code; +- } +- } else if (v_code <= v_end_code) { +- if (v_code == v_end_code) { +- self->private_impl.f_lzw_read_from_return_value = 0u; +- break; +- } +- v_save_code = v_end_code; +- v_prev_code = v_end_code; +- v_width = (self->private_impl.f_lzw_literal_width + 1u); +- } else if (v_code <= v_save_code) { +- v_c = v_code; +- if (v_code == v_save_code) { +- v_c = v_prev_code; +- } +- v_o = ((v_output_wi + (((uint32_t)(self->private_data.f_lzw_lm1s[v_c])) & 4294967288u)) & 8191u); +- v_output_wi = ((v_output_wi + 1u + ((uint32_t)(self->private_data.f_lzw_lm1s[v_c]))) & 8191u); +- v_steps = (((uint32_t)(self->private_data.f_lzw_lm1s[v_c])) >> 3u); +- while (true) { +- memcpy((self->private_data.f_lzw_output)+(v_o), (self->private_data.f_lzw_suffixes[v_c]), 8u); +- if (v_steps <= 0u) { +- break; +- } +- v_steps -= 1u; +- v_o = (((uint32_t)(v_o - 8u)) & 8191u); +- v_c = ((uint32_t)(self->private_impl.f_lzw_prefixes[v_c])); +- } +- v_first_byte = self->private_data.f_lzw_suffixes[v_c][0u]; +- if (v_code == v_save_code) { +- self->private_data.f_lzw_output[v_output_wi] = v_first_byte; +- v_output_wi = ((v_output_wi + 1u) & 8191u); +- } +- if (v_save_code <= 4095u) { +- v_lm1_b = (((uint16_t)(self->private_data.f_lzw_lm1s[v_prev_code] + 1u)) & 4095u); +- self->private_data.f_lzw_lm1s[v_save_code] = v_lm1_b; +- if ((v_lm1_b % 8u) != 0u) { +- self->private_impl.f_lzw_prefixes[v_save_code] = self->private_impl.f_lzw_prefixes[v_prev_code]; +- memcpy(self->private_data.f_lzw_suffixes[v_save_code],self->private_data.f_lzw_suffixes[v_prev_code], sizeof(self->private_data.f_lzw_suffixes[v_save_code])); +- self->private_data.f_lzw_suffixes[v_save_code][(v_lm1_b % 8u)] = v_first_byte; +- } else { +- self->private_impl.f_lzw_prefixes[v_save_code] = ((uint16_t)(v_prev_code)); +- self->private_data.f_lzw_suffixes[v_save_code][0u] = ((uint8_t)(v_first_byte)); +- } +- v_save_code += 1u; +- if (v_width < 12u) { +- v_width += (1u & (v_save_code >> v_width)); +- } +- v_prev_code = v_code; +- } +- } else { +- self->private_impl.f_lzw_read_from_return_value = 4u; +- break; +- } +- if (v_output_wi > 4095u) { +- self->private_impl.f_lzw_read_from_return_value = 1u; +- break; +- } ++// -------- func gif.decoder.decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_gif__decoder__decode_image_config( ++ wuffs_gif__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- if (self->private_impl.f_lzw_read_from_return_value != 2u) { +- while (v_n_bits >= 8u) { +- v_n_bits -= 8u; +- if (iop_a_src > io1_a_src) { +- iop_a_src--; +- } else { +- self->private_impl.f_lzw_read_from_return_value = 5u; +- break; +- } +- } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } +- self->private_impl.f_lzw_save_code = v_save_code; +- self->private_impl.f_lzw_prev_code = v_prev_code; +- self->private_impl.f_lzw_width = v_width; +- self->private_impl.f_lzw_bits = v_bits; +- self->private_impl.f_lzw_n_bits = v_n_bits; +- self->private_impl.f_lzw_output_wi = v_output_wi; +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); + } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- return wuffs_base__make_empty_struct(); +-} +- +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF) ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP) ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-// ---------------- Status Codes Implementations ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_gif__decoder__do_decode_image_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_gif__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } + +-const char wuffs_gzip__error__bad_checksum[] = "#gzip: bad checksum"; +-const char wuffs_gzip__error__bad_compression_method[] = "#gzip: bad compression method"; +-const char wuffs_gzip__error__bad_encoding_flags[] = "#gzip: bad encoding flags"; +-const char wuffs_gzip__error__bad_header[] = "#gzip: bad header"; +-const char wuffs_gzip__error__truncated_input[] = "#gzip: truncated input"; ++ ok: ++ self->private_impl.p_decode_image_config = 0; ++ goto exit; ++ } + +-// ---------------- Private Consts ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; + +-// ---------------- Private Initializer Prototypes ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} + +-// ---------------- Private Function Prototypes ++// -------- func gif.decoder.do_decode_image_config + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gzip__decoder__do_transform_io( +- wuffs_gzip__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf); +- +-// ---------------- VTables +- +-const wuffs_base__io_transformer__func_ptrs +-wuffs_gzip__decoder__func_ptrs_for__wuffs_base__io_transformer = { +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_gzip__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_gzip__decoder__history_retain_length), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_gzip__decoder__set_quirk), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__slice_u8))(&wuffs_gzip__decoder__transform_io), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_gzip__decoder__workbuf_len), +-}; ++wuffs_gif__decoder__do_decode_image_config( ++ wuffs_gif__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-// ---------------- Initializer Implementations ++ bool v_ffio = false; + +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_gzip__decoder__initialize( +- wuffs_gzip__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); +- } ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ if (self->private_impl.f_call_sequence != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } else if ( ! self->private_impl.f_seen_header) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_gif__decoder__decode_header(self, a_src); ++ if (status.repr) { ++ goto suspend; ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_gif__decoder__decode_lsd(self, a_src); ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_seen_header = true; + } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src); ++ if (status.repr) { ++ goto suspend; + } +- } +- +- { +- wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize( +- &self->private_data.f_checksum, sizeof(self->private_data.f_checksum), WUFFS_VERSION, options); +- if (z.repr) { +- return z; ++ v_ffio = ! self->private_impl.f_gc_has_transparent_index; ++ if ( ! self->private_impl.f_quirks[2u]) { ++ v_ffio = (v_ffio && ++ (self->private_impl.f_frame_rect_x0 == 0u) && ++ (self->private_impl.f_frame_rect_y0 == 0u) && ++ (self->private_impl.f_frame_rect_x1 == self->private_impl.f_width) && ++ (self->private_impl.f_frame_rect_y1 == self->private_impl.f_height)); ++ } else if (v_ffio) { ++ self->private_impl.f_black_color_u32_argb_premul = 4278190080u; + } +- } +- { +- wuffs_base__status z = wuffs_deflate__decoder__initialize( +- &self->private_data.f_flate, sizeof(self->private_data.f_flate), WUFFS_VERSION, options); +- if (z.repr) { +- return z; ++ if (self->private_impl.f_background_color_u32_argb_premul == 77u) { ++ self->private_impl.f_background_color_u32_argb_premul = self->private_impl.f_black_color_u32_argb_premul; ++ } ++ if (a_dst != NULL) { ++ wuffs_base__image_config__set( ++ a_dst, ++ 2198077448u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ self->private_impl.f_frame_config_io_position, ++ v_ffio); ++ } ++ if (self->private_impl.f_call_sequence == 0u) { ++ self->private_impl.f_call_sequence = 32u; + } +- } +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = +- wuffs_base__io_transformer__vtable_name; +- self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = +- (const void*)(&wuffs_gzip__decoder__func_ptrs_for__wuffs_base__io_transformer); +- return wuffs_base__make_status(NULL); +-} + +-wuffs_gzip__decoder* +-wuffs_gzip__decoder__alloc(void) { +- wuffs_gzip__decoder* x = +- (wuffs_gzip__decoder*)(calloc(sizeof(wuffs_gzip__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_gzip__decoder__initialize( +- x, sizeof(wuffs_gzip__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; ++ goto ok; ++ ok: ++ self->private_impl.p_do_decode_image_config = 0; ++ goto exit; + } +- return x; +-} +- +-size_t +-sizeof__wuffs_gzip__decoder(void) { +- return sizeof(wuffs_gzip__decoder); +-} + +-// ---------------- Function Implementations +- +-// -------- func gzip.decoder.get_quirk +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_gzip__decoder__get_quirk( +- const wuffs_gzip__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + +- if ((a_key == 1u) && self->private_impl.f_ignore_checksum) { +- return 1u; +- } +- return 0u; ++ goto exit; ++ exit: ++ return status; + } + +-// -------- func gzip.decoder.set_quirk ++// -------- func gif.decoder.set_report_metadata + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_gzip__decoder__set_quirk( +- wuffs_gzip__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_gif__decoder__set_report_metadata( ++ wuffs_gif__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report) { + if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ return wuffs_base__make_empty_struct(); + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- +- if (a_key == 1u) { +- self->private_impl.f_ignore_checksum = (a_value > 0u); +- return wuffs_base__make_status(NULL); +- } +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); +-} +- +-// -------- func gzip.decoder.history_retain_length +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_gzip__decoder__history_retain_length( +- const wuffs_gzip__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ return wuffs_base__make_empty_struct(); + } + +- return 0u; +-} +- +-// -------- func gzip.decoder.workbuf_len +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_gzip__decoder__workbuf_len( +- const wuffs_gzip__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ if (a_fourcc == 1229144912u) { ++ self->private_impl.f_report_metadata_iccp = a_report; ++ } else if (a_fourcc == 1481461792u) { ++ self->private_impl.f_report_metadata_xmp = a_report; + } +- +- return wuffs_base__utility__make_range_ii_u64(1u, 1u); ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func gzip.decoder.transform_io ++// -------- func gif.decoder.tell_me_more + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_gzip__decoder__transform_io( +- wuffs_gzip__decoder* self, ++wuffs_gif__decoder__tell_me_more( ++ wuffs_gif__decoder* self, + wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +@@ -39737,7 +41163,7 @@ wuffs_gzip__decoder__transform_io( + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { ++ (self->private_impl.active_coroutine != 2)) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } +@@ -39746,17 +41172,17 @@ wuffs_gzip__decoder__transform_io( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_transform_io[0]; ++ uint32_t coro_susp_point = self->private_impl.p_tell_me_more; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_gzip__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); ++ wuffs_base__status t_0 = wuffs_gif__decoder__do_tell_me_more(self, a_dst, a_minfo, a_src); + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_gzip__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_gif__error__truncated_input); + goto exit; + } + status = v_status; +@@ -39764,14 +41190,14 @@ wuffs_gzip__decoder__transform_io( + } + + ok: +- self->private_impl.p_transform_io[0] = 0; ++ self->private_impl.p_tell_me_more = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ self->private_impl.p_tell_me_more = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; + + goto exit; + exit: +@@ -39781,40 +41207,19 @@ wuffs_gzip__decoder__transform_io( + return status; + } + +-// -------- func gzip.decoder.do_transform_io ++// -------- func gif.decoder.do_tell_me_more + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_gzip__decoder__do_transform_io( +- wuffs_gzip__decoder* self, ++wuffs_gif__decoder__do_tell_me_more( ++ wuffs_gif__decoder* self, + wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint8_t v_flags = 0; +- uint16_t v_xlen = 0; +- uint64_t v_mark = 0; +- uint32_t v_checksum_got = 0; +- uint32_t v_decoded_length_got = 0; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- uint32_t v_checksum_want = 0; +- uint32_t v_decoded_length_want = 0; ++ uint64_t v_chunk_length = 0; + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -39826,269 +41231,95 @@ wuffs_gzip__decoder__do_transform_io( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_transform_io[0]; +- if (coro_susp_point) { +- v_flags = self->private_data.s_do_transform_io[0].v_flags; +- v_checksum_got = self->private_data.s_do_transform_io[0].v_checksum_got; +- v_decoded_length_got = self->private_data.s_do_transform_io[0].v_decoded_length_got; +- v_checksum_want = self->private_data.s_do_transform_io[0].v_checksum_want; +- } ++ uint32_t coro_susp_point = self->private_impl.p_do_tell_me_more; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if (v_c != 31u) { +- status = wuffs_base__make_status(wuffs_gzip__error__bad_header); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; +- } +- if (v_c != 139u) { +- status = wuffs_base__make_status(wuffs_gzip__error__bad_header); ++ if (((uint8_t)(self->private_impl.f_call_sequence & 16u)) == 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); + goto exit; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_2 = *iop_a_src++; +- v_c = t_2; +- } +- if (v_c != 8u) { +- status = wuffs_base__make_status(wuffs_gzip__error__bad_compression_method); ++ if (self->private_impl.f_metadata_fourcc == 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); + goto exit; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_3 = *iop_a_src++; +- v_flags = t_3; +- } +- self->private_data.s_do_transform_io[0].scratch = 6u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (self->private_data.s_do_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_transform_io[0].scratch; +- if ((v_flags & 4u) != 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- uint16_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_4 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_transform_io[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; +- if (num_bits_4 == 8) { +- t_4 = ((uint16_t)(*scratch)); +- break; +- } +- num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)) << 56; +- } +- } +- v_xlen = t_4; +- } +- self->private_data.s_do_transform_io[0].scratch = ((uint32_t)(v_xlen)); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- if (self->private_data.s_do_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_transform_io[0].scratch; +- } +- if ((v_flags & 8u) != 0u) { ++ while (true) { + while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ if (wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) != self->private_impl.f_metadata_io_position) { ++ if (a_minfo != NULL) { ++ wuffs_base__more_information__set(a_minfo, ++ 2u, ++ 0u, ++ self->private_impl.f_metadata_io_position, ++ 0u, ++ 0u); + } +- uint8_t t_5 = *iop_a_src++; +- v_c = t_5; +- } +- if (v_c == 0u) { +- break; ++ status = wuffs_base__make_status(wuffs_base__suspension__mispositioned_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ continue; + } +- } +- } +- if ((v_flags & 16u) != 0u) { +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_minfo != NULL) { ++ wuffs_base__more_information__set(a_minfo, ++ 0u, ++ 0u, ++ 0u, ++ 0u, ++ 0u); + } +- uint8_t t_6 = *iop_a_src++; +- v_c = t_6; +- } +- if (v_c == 0u) { +- break; +- } +- } +- } +- if ((v_flags & 2u) != 0u) { +- self->private_data.s_do_transform_io[0].scratch = 2u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); +- if (self->private_data.s_do_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_transform_io[0].scratch; +- } +- if ((v_flags & 224u) != 0u) { +- status = wuffs_base__make_status(wuffs_gzip__error__bad_encoding_flags); +- goto exit; +- } +- while (true) { +- v_mark = ((uint64_t)(iop_a_dst - io0_a_dst)); +- { +- 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__status t_7 = wuffs_deflate__decoder__transform_io(&self->private_data.f_flate, a_dst, a_src, a_workbuf); +- v_status = t_7; +- 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; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ continue; + } ++ break; + } +- if ( ! self->private_impl.f_ignore_checksum) { +- v_checksum_got = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_checksum, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); +- v_decoded_length_got += ((uint32_t)(wuffs_base__io__count_since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst))))); +- } +- if (wuffs_base__status__is_ok(&v_status)) { ++ v_chunk_length = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))); ++ if (v_chunk_length <= 0u) { ++ iop_a_src += 1u; + break; + } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12); +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); +- uint32_t t_8; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; ++ if (self->private_impl.f_metadata_fourcc == 1481461792u) { ++ v_chunk_length += 1u; + } else { +- self->private_data.s_do_transform_io[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch; +- uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8; +- if (num_bits_8 == 24) { +- t_8 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_8 += 8u; +- *scratch |= ((uint64_t)(num_bits_8)) << 56; +- } ++ iop_a_src += 1u; + } +- v_checksum_want = t_8; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); +- uint32_t t_9; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_9 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_transform_io[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch; +- uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9; +- if (num_bits_9 == 24) { +- t_9 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_9 += 8u; +- *scratch |= ((uint64_t)(num_bits_9)) << 56; +- } ++ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))), v_chunk_length); ++ if (a_minfo != NULL) { ++ wuffs_base__more_information__set(a_minfo, ++ 3u, ++ self->private_impl.f_metadata_fourcc, ++ 0u, ++ wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))), ++ self->private_impl.f_metadata_io_position); + } +- v_decoded_length_want = t_9; ++ status = wuffs_base__make_status(wuffs_base__suspension__even_more_information); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); + } +- if ( ! self->private_impl.f_ignore_checksum && ((v_checksum_got != v_checksum_want) || (v_decoded_length_got != v_decoded_length_want))) { +- status = wuffs_base__make_status(wuffs_gzip__error__bad_checksum); +- goto exit; ++ if (a_minfo != NULL) { ++ wuffs_base__more_information__set(a_minfo, ++ 3u, ++ self->private_impl.f_metadata_fourcc, ++ 0u, ++ self->private_impl.f_metadata_io_position, ++ self->private_impl.f_metadata_io_position); + } ++ self->private_impl.f_call_sequence &= 239u; ++ self->private_impl.f_metadata_fourcc = 0u; ++ self->private_impl.f_metadata_io_position = 0u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; + + ok: +- self->private_impl.p_do_transform_io[0] = 0; ++ self->private_impl.p_do_tell_me_more = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_transform_io[0].v_flags = v_flags; +- self->private_data.s_do_transform_io[0].v_checksum_got = v_checksum_got; +- self->private_data.s_do_transform_io[0].v_decoded_length_got = v_decoded_length_got; +- self->private_data.s_do_transform_io[0].v_checksum_want = v_checksum_want; ++ self->private_impl.p_do_tell_me_more = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -40096,2260 +41327,1143 @@ wuffs_gzip__decoder__do_transform_io( + return status; + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JPEG) ++// -------- func gif.decoder.num_animation_loops + +-// ---------------- Status Codes Implementations ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_gif__decoder__num_animation_loops( ++ const wuffs_gif__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +-const char wuffs_jpeg__error__bad_dht_marker[] = "#jpeg: bad DHT marker"; +-const char wuffs_jpeg__error__bad_dqt_marker[] = "#jpeg: bad DQT marker"; +-const char wuffs_jpeg__error__bad_dri_marker[] = "#jpeg: bad DRI marker"; +-const char wuffs_jpeg__error__bad_sof_marker[] = "#jpeg: bad SOF marker"; +-const char wuffs_jpeg__error__bad_sos_marker[] = "#jpeg: bad SOS marker"; +-const char wuffs_jpeg__error__bad_header[] = "#jpeg: bad header"; +-const char wuffs_jpeg__error__bad_marker[] = "#jpeg: bad marker"; +-const char wuffs_jpeg__error__missing_huffman_table[] = "#jpeg: missing Huffman table"; +-const char wuffs_jpeg__error__missing_quantization_table[] = "#jpeg: missing Quantization table"; +-const char wuffs_jpeg__error__truncated_input[] = "#jpeg: truncated input"; +-const char wuffs_jpeg__error__unsupported_arithmetic_coding[] = "#jpeg: unsupported arithmetic coding"; +-const char wuffs_jpeg__error__unsupported_color_model[] = "#jpeg: unsupported color model"; +-const char wuffs_jpeg__error__unsupported_fractional_sampling[] = "#jpeg: unsupported fractional sampling"; +-const char wuffs_jpeg__error__unsupported_hierarchical_coding[] = "#jpeg: unsupported hierarchical coding"; +-const char wuffs_jpeg__error__unsupported_implicit_height[] = "#jpeg: unsupported implicit height"; +-const char wuffs_jpeg__error__unsupported_lossless_coding[] = "#jpeg: unsupported lossless coding"; +-const char wuffs_jpeg__error__unsupported_marker[] = "#jpeg: unsupported marker"; +-const char wuffs_jpeg__error__unsupported_precision_12_bits[] = "#jpeg: unsupported precision (12 bits)"; +-const char wuffs_jpeg__error__unsupported_precision_16_bits[] = "#jpeg: unsupported precision (16 bits)"; +-const char wuffs_jpeg__error__unsupported_precision[] = "#jpeg: unsupported precision"; +-const char wuffs_jpeg__error__unsupported_scan_count[] = "#jpeg: unsupported scan count"; +-const char wuffs_jpeg__error__internal_error_inconsistent_decoder_state[] = "#jpeg: internal error: inconsistent decoder state"; ++ if (self->private_impl.f_seen_num_animation_loops_value) { ++ return self->private_impl.f_num_animation_loops_value; ++ } ++ if (self->private_impl.f_num_decoded_frame_configs_value > 1u) { ++ return 1u; ++ } ++ return 0u; ++} + +-// ---------------- Private Consts ++// -------- func gif.decoder.num_decoded_frame_configs + +-static const uint8_t +-WUFFS_JPEG__UNZIG[80] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 0, 1, 8, 16, 9, 2, 3, +- 10, 17, 24, 32, 25, 18, 11, 4, +- 5, 12, 19, 26, 33, 40, 48, 41, +- 34, 27, 20, 13, 6, 7, 14, 21, +- 28, 35, 42, 49, 56, 57, 50, 43, +- 36, 29, 22, 15, 23, 30, 37, 44, +- 51, 58, 59, 52, 45, 38, 31, 39, +- 46, 53, 60, 61, 54, 47, 55, 62, +- 63, 63, 63, 63, 63, 63, 63, 63, +- 63, 63, 63, 63, 63, 63, 63, 63, +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_gif__decoder__num_decoded_frame_configs( ++ const wuffs_gif__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +-static const uint8_t +-WUFFS_JPEG__BIAS_AND_CLAMP[1024] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 128, 129, 130, 131, 132, 133, 134, 135, +- 136, 137, 138, 139, 140, 141, 142, 143, +- 144, 145, 146, 147, 148, 149, 150, 151, +- 152, 153, 154, 155, 156, 157, 158, 159, +- 160, 161, 162, 163, 164, 165, 166, 167, +- 168, 169, 170, 171, 172, 173, 174, 175, +- 176, 177, 178, 179, 180, 181, 182, 183, +- 184, 185, 186, 187, 188, 189, 190, 191, +- 192, 193, 194, 195, 196, 197, 198, 199, +- 200, 201, 202, 203, 204, 205, 206, 207, +- 208, 209, 210, 211, 212, 213, 214, 215, +- 216, 217, 218, 219, 220, 221, 222, 223, +- 224, 225, 226, 227, 228, 229, 230, 231, +- 232, 233, 234, 235, 236, 237, 238, 239, +- 240, 241, 242, 243, 244, 245, 246, 247, +- 248, 249, 250, 251, 252, 253, 254, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 255, 255, 255, 255, 255, 255, 255, 255, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 1, 2, 3, 4, 5, 6, 7, +- 8, 9, 10, 11, 12, 13, 14, 15, +- 16, 17, 18, 19, 20, 21, 22, 23, +- 24, 25, 26, 27, 28, 29, 30, 31, +- 32, 33, 34, 35, 36, 37, 38, 39, +- 40, 41, 42, 43, 44, 45, 46, 47, +- 48, 49, 50, 51, 52, 53, 54, 55, +- 56, 57, 58, 59, 60, 61, 62, 63, +- 64, 65, 66, 67, 68, 69, 70, 71, +- 72, 73, 74, 75, 76, 77, 78, 79, +- 80, 81, 82, 83, 84, 85, 86, 87, +- 88, 89, 90, 91, 92, 93, 94, 95, +- 96, 97, 98, 99, 100, 101, 102, 103, +- 104, 105, 106, 107, 108, 109, 110, 111, +- 112, 113, 114, 115, 116, 117, 118, 119, +- 120, 121, 122, 123, 124, 125, 126, 127, +-}; ++ return self->private_impl.f_num_decoded_frame_configs_value; ++} + +-static const uint16_t +-WUFFS_JPEG__EXTEND[16] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 65535, 65533, 65529, 65521, 65505, 65473, 65409, +- 65281, 65025, 64513, 63489, 61441, 57345, 49153, 32769, +-}; ++// -------- func gif.decoder.num_decoded_frames + +-static const uint8_t +-WUFFS_JPEG__DEFAULT_HUFF_TABLE_DC_LUMA[29] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 0, 1, 5, 1, 1, 1, 1, +- 1, 1, 0, 0, 0, 0, 0, 0, +- 0, 0, 1, 2, 3, 4, 5, 6, +- 7, 8, 9, 10, 11, +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_gif__decoder__num_decoded_frames( ++ const wuffs_gif__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +-static const uint8_t +-WUFFS_JPEG__DEFAULT_HUFF_TABLE_DC_CHROMA[29] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 1, 0, 3, 1, 1, 1, 1, 1, +- 1, 1, 1, 1, 0, 0, 0, 0, +- 0, 0, 1, 2, 3, 4, 5, 6, +- 7, 8, 9, 10, 11, +-}; ++ return self->private_impl.f_num_decoded_frames_value; ++} + +-static const uint8_t +-WUFFS_JPEG__DEFAULT_HUFF_TABLE_AC_LUMA[179] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 16, 0, 2, 1, 3, 3, 2, 4, +- 3, 5, 5, 4, 4, 0, 0, 1, +- 125, 1, 2, 3, 0, 4, 17, 5, +- 18, 33, 49, 65, 6, 19, 81, 97, +- 7, 34, 113, 20, 50, 129, 145, 161, +- 8, 35, 66, 177, 193, 21, 82, 209, +- 240, 36, 51, 98, 114, 130, 9, 10, +- 22, 23, 24, 25, 26, 37, 38, 39, +- 40, 41, 42, 52, 53, 54, 55, 56, +- 57, 58, 67, 68, 69, 70, 71, 72, +- 73, 74, 83, 84, 85, 86, 87, 88, +- 89, 90, 99, 100, 101, 102, 103, 104, +- 105, 106, 115, 116, 117, 118, 119, 120, +- 121, 122, 131, 132, 133, 134, 135, 136, +- 137, 138, 146, 147, 148, 149, 150, 151, +- 152, 153, 154, 162, 163, 164, 165, 166, +- 167, 168, 169, 170, 178, 179, 180, 181, +- 182, 183, 184, 185, 186, 194, 195, 196, +- 197, 198, 199, 200, 201, 202, 210, 211, +- 212, 213, 214, 215, 216, 217, 218, 225, +- 226, 227, 228, 229, 230, 231, 232, 233, +- 234, 241, 242, 243, 244, 245, 246, 247, +- 248, 249, 250, +-}; ++// -------- func gif.decoder.frame_dirty_rect + +-static const uint8_t +-WUFFS_JPEG__DEFAULT_HUFF_TABLE_AC_CHROMA[179] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 17, 0, 2, 1, 2, 4, 4, 3, +- 4, 7, 5, 4, 4, 0, 1, 2, +- 119, 0, 1, 2, 3, 17, 4, 5, +- 33, 49, 6, 18, 65, 81, 7, 97, +- 113, 19, 34, 50, 129, 8, 20, 66, +- 145, 161, 177, 193, 9, 35, 51, 82, +- 240, 21, 98, 114, 209, 10, 22, 36, +- 52, 225, 37, 241, 23, 24, 25, 26, +- 38, 39, 40, 41, 42, 53, 54, 55, +- 56, 57, 58, 67, 68, 69, 70, 71, +- 72, 73, 74, 83, 84, 85, 86, 87, +- 88, 89, 90, 99, 100, 101, 102, 103, +- 104, 105, 106, 115, 116, 117, 118, 119, +- 120, 121, 122, 130, 131, 132, 133, 134, +- 135, 136, 137, 138, 146, 147, 148, 149, +- 150, 151, 152, 153, 154, 162, 163, 164, +- 165, 166, 167, 168, 169, 170, 178, 179, +- 180, 181, 182, 183, 184, 185, 186, 194, +- 195, 196, 197, 198, 199, 200, 201, 202, +- 210, 211, 212, 213, 214, 215, 216, 217, +- 218, 226, 227, 228, 229, 230, 231, 232, +- 233, 234, 242, 243, 244, 245, 246, 247, +- 248, 249, 250, +-}; ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_gif__decoder__frame_dirty_rect( ++ const wuffs_gif__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } + +-// ---------------- Private Initializer Prototypes ++ return wuffs_base__utility__make_rect_ie_u32( ++ wuffs_base__u32__min(self->private_impl.f_frame_rect_x0, self->private_impl.f_width), ++ wuffs_base__u32__min(self->private_impl.f_frame_rect_y0, self->private_impl.f_height), ++ wuffs_base__u32__min(self->private_impl.f_frame_rect_x1, self->private_impl.f_width), ++ wuffs_base__u32__min(self->private_impl.f_dirty_max_excl_y, self->private_impl.f_height)); ++} + +-// ---------------- Private Function Prototypes ++// -------- func gif.decoder.workbuf_len + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__decode_idct( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_dst_buffer, +- uint64_t a_dst_stride, +- uint32_t a_q); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_gif__decoder__workbuf_len( ++ const wuffs_gif__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__decode_idct__choosy_default( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_dst_buffer, +- uint64_t a_dst_stride, +- uint32_t a_q); ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++} + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__decode_idct_x86_avx2( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_dst_buffer, +- uint64_t a_dst_stride, +- uint32_t a_q); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_64) ++// -------- func gif.decoder.restart_frame + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__do_decode_image_config( +- wuffs_jpeg__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_gif__decoder__restart_frame( ++ wuffs_gif__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__decode_dqt( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src); ++ if (self->private_impl.f_call_sequence < 32u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } else if (a_io_position == 0u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_delayed_num_decoded_frames = false; ++ self->private_impl.f_frame_config_io_position = a_io_position; ++ self->private_impl.f_num_decoded_frame_configs_value = a_index; ++ self->private_impl.f_num_decoded_frames_value = a_index; ++ wuffs_gif__decoder__reset_gc(self); ++ self->private_impl.f_call_sequence = 40u; ++ return wuffs_base__make_status(NULL); ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__decode_dri( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src); ++// -------- func gif.decoder.decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__decode_appn( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src, +- uint8_t a_marker); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_gif__decoder__decode_frame_config( ++ wuffs_gif__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 3)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__decode_sof( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src); ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__quantize_dimension( +- const wuffs_jpeg__decoder* self, +- uint32_t a_width, +- uint8_t a_h, +- uint8_t a_max_incl_h); ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__do_decode_frame_config( +- wuffs_jpeg__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_gif__decoder__do_decode_frame_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_gif__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__do_decode_frame( +- wuffs_jpeg__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); ++ ok: ++ self->private_impl.p_decode_frame_config = 0; ++ goto exit; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__decode_dht( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src); ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; + +-WUFFS_BASE__GENERATED_C_CODE +-static bool +-wuffs_jpeg__decoder__calculate_huff_tables( +- wuffs_jpeg__decoder* self, +- uint8_t a_tc4_th, +- uint32_t a_total_count); ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__decode_sos( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf); ++// -------- func gif.decoder.do_decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__prepare_scan( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src); ++wuffs_gif__decoder__do_decode_frame_config( ++ wuffs_gif__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__use_default_huffman_table( +- wuffs_jpeg__decoder* self, +- uint8_t a_tc4_th); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__calculate_single_component_scan_fields( +- wuffs_jpeg__decoder* self); ++ uint32_t v_background_color = 0; ++ uint8_t v_flags = 0; + +-WUFFS_BASE__GENERATED_C_CODE +-static bool +-wuffs_jpeg__decoder__calculate_multiple_component_scan_fields( +- wuffs_jpeg__decoder* self); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__fill_bitstream( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src); ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config; ++ if (coro_susp_point) { ++ v_background_color = self->private_data.s_do_decode_frame_config.v_background_color; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__load_mcu_blocks_for_single_component( +- wuffs_jpeg__decoder* self, +- uint32_t a_mx, +- uint32_t a_my, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_csel); ++ self->private_impl.f_dirty_max_excl_y = 0u; ++ if (((uint8_t)(self->private_impl.f_call_sequence & 16u)) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } else if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_gif__decoder__do_decode_image_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); ++ goto exit; ++ } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_gif__decoder__skip_frame(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (self->private_impl.f_call_sequence >= 96u) { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ if ((self->private_impl.f_num_decoded_frame_configs_value > 0u) || (self->private_impl.f_call_sequence == 40u)) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (self->private_impl.f_call_sequence >= 96u) { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ } ++ v_background_color = self->private_impl.f_black_color_u32_argb_premul; ++ if ( ! self->private_impl.f_gc_has_transparent_index) { ++ v_background_color = self->private_impl.f_background_color_u32_argb_premul; ++ if (self->private_impl.f_quirks[1u] && (self->private_impl.f_num_decoded_frame_configs_value == 0u)) { ++ while (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ } ++ v_flags = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if (((uint8_t)(v_flags & 128u)) != 0u) { ++ v_background_color = self->private_impl.f_black_color_u32_argb_premul; ++ } ++ } ++ } ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ wuffs_base__u32__min(self->private_impl.f_frame_rect_x0, self->private_impl.f_width), ++ wuffs_base__u32__min(self->private_impl.f_frame_rect_y0, self->private_impl.f_height), ++ wuffs_base__u32__min(self->private_impl.f_frame_rect_x1, self->private_impl.f_width), ++ wuffs_base__u32__min(self->private_impl.f_frame_rect_y1, self->private_impl.f_height)), ++ ((wuffs_base__flicks)(self->private_impl.f_gc_duration)), ++ self->private_impl.f_num_decoded_frame_configs_value, ++ self->private_impl.f_frame_config_io_position, ++ self->private_impl.f_gc_disposal, ++ ! self->private_impl.f_gc_has_transparent_index, ++ false, ++ v_background_color); ++ } ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frame_configs_value, 1u); ++ self->private_impl.f_call_sequence = 64u; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__load_mcu_blocks_for_single_component__choosy_default( +- wuffs_jpeg__decoder* self, +- uint32_t a_mx, +- uint32_t a_my, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_csel); ++ ok: ++ self->private_impl.p_do_decode_frame_config = 0; ++ goto exit; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__load_mcu_blocks( +- wuffs_jpeg__decoder* self, +- uint32_t a_mx, +- uint32_t a_my, +- wuffs_base__slice_u8 a_workbuf); ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_frame_config.v_background_color = v_background_color; + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__save_mcu_blocks( +- wuffs_jpeg__decoder* self, +- uint32_t a_mx, +- uint32_t a_my, +- wuffs_base__slice_u8 a_workbuf); ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__skip_past_the_next_restart_marker( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src); ++ return status; ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__apply_progressive_idct( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf); ++// -------- func gif.decoder.skip_frame + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__swizzle_gray( +- wuffs_jpeg__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf); ++wuffs_gif__decoder__skip_frame( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__swizzle_colorful( +- wuffs_jpeg__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf); ++ uint8_t v_flags = 0; ++ uint8_t v_lw = 0; + +-WUFFS_BASE__GENERATED_C_CODE +-static bool +-wuffs_jpeg__decoder__top_left_quants_has_zero( +- const wuffs_jpeg__decoder* self, +- uint32_t a_q); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__load_mcu_blocks_for_single_component_smooth( +- wuffs_jpeg__decoder* self, +- uint32_t a_mx, +- uint32_t a_my, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_csel); ++ uint32_t coro_susp_point = self->private_impl.p_skip_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_flags = t_0; ++ } ++ if (((uint8_t)(v_flags & 128u)) != 0u) { ++ self->private_data.s_skip_frame.scratch = (((uint32_t)(3u)) << ((uint8_t)(1u + ((uint8_t)(v_flags & 7u))))); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (self->private_data.s_skip_frame.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_skip_frame.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_skip_frame.scratch; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_lw = t_1; ++ } ++ if (v_lw > 8u) { ++ status = wuffs_base__make_status(wuffs_gif__error__bad_literal_width); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_gif__decoder__skip_blocks(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (self->private_impl.f_quirks[0u]) { ++ self->private_impl.f_delayed_num_decoded_frames = true; ++ } else { ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); ++ } ++ wuffs_gif__decoder__reset_gc(self); ++ self->private_impl.f_call_sequence = 32u; + +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu__choosy_default( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my); ++ goto ok; ++ ok: ++ self->private_impl.p_skip_frame = 0; ++ goto exit; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu_progressive_ac_high_bits( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my); ++ goto suspend; ++ suspend: ++ self->private_impl.p_skip_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu_progressive_ac_low_bit( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my); ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu_progressive_dc_high_bits( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my); ++ return status; ++} ++ ++// -------- func gif.decoder.decode_frame + + WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu_progressive_dc_low_bit( +- wuffs_jpeg__decoder* self, ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_gif__decoder__decode_frame( ++ wuffs_gif__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, + wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my); +- +-// ---------------- VTables +- +-const wuffs_base__image_decoder__func_ptrs +-wuffs_jpeg__decoder__func_ptrs_for__wuffs_base__image_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__pixel_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__pixel_blend, +- wuffs_base__slice_u8, +- wuffs_base__decode_frame_options*))(&wuffs_jpeg__decoder__decode_frame), +- (wuffs_base__status(*)(void*, +- wuffs_base__frame_config*, +- wuffs_base__io_buffer*))(&wuffs_jpeg__decoder__decode_frame_config), +- (wuffs_base__status(*)(void*, +- wuffs_base__image_config*, +- wuffs_base__io_buffer*))(&wuffs_jpeg__decoder__decode_image_config), +- (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_jpeg__decoder__frame_dirty_rect), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_jpeg__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_jpeg__decoder__history_retain_length), +- (uint32_t(*)(const void*))(&wuffs_jpeg__decoder__num_animation_loops), +- (uint64_t(*)(const void*))(&wuffs_jpeg__decoder__num_decoded_frame_configs), +- (uint64_t(*)(const void*))(&wuffs_jpeg__decoder__num_decoded_frames), +- (wuffs_base__status(*)(void*, +- uint64_t, +- uint64_t))(&wuffs_jpeg__decoder__restart_frame), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_jpeg__decoder__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- uint32_t, +- bool))(&wuffs_jpeg__decoder__set_report_metadata), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__more_information*, +- wuffs_base__io_buffer*))(&wuffs_jpeg__decoder__tell_me_more), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_jpeg__decoder__workbuf_len), +-}; +- +-// ---------------- Initializer Implementations +- +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_jpeg__decoder__initialize( +- wuffs_jpeg__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ ++ wuffs_base__decode_frame_options* a_opts) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); + } +- +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); +- } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); +- } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- self->private_impl.choosy_decode_idct = &wuffs_jpeg__decoder__decode_idct__choosy_default; +- self->private_impl.choosy_load_mcu_blocks_for_single_component = &wuffs_jpeg__decoder__load_mcu_blocks_for_single_component__choosy_default; +- self->private_impl.choosy_decode_mcu = &wuffs_jpeg__decoder__decode_mcu__choosy_default; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = +- wuffs_base__image_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = +- (const void*)(&wuffs_jpeg__decoder__func_ptrs_for__wuffs_base__image_decoder); +- return wuffs_base__make_status(NULL); +-} ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-wuffs_jpeg__decoder* +-wuffs_jpeg__decoder__alloc(void) { +- wuffs_jpeg__decoder* x = +- (wuffs_jpeg__decoder*)(calloc(sizeof(wuffs_jpeg__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_jpeg__decoder__initialize( +- x, sizeof(wuffs_jpeg__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_gif__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_gif__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame = 0; ++ goto exit; + } +- return x; +-} + +-size_t +-sizeof__wuffs_jpeg__decoder(void) { +- return sizeof(wuffs_jpeg__decoder); +-} ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0; + +-// ---------------- Function Implementations ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} + +-// -------- func jpeg.decoder.decode_idct ++// -------- func gif.decoder.do_decode_frame + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__decode_idct( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_dst_buffer, +- uint64_t a_dst_stride, +- uint32_t a_q) { +- return (*self->private_impl.choosy_decode_idct)(self, a_dst_buffer, a_dst_stride, a_q); +-} ++static wuffs_base__status ++wuffs_gif__decoder__do_decode_frame( ++ wuffs_gif__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__decode_idct__choosy_default( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_dst_buffer, +- uint64_t a_dst_stride, +- uint32_t a_q) { +- uint32_t v_bq0 = 0; +- uint32_t v_bq2 = 0; +- uint32_t v_bq4 = 0; +- uint32_t v_bq6 = 0; +- uint32_t v_ca = 0; +- uint32_t v_cb2 = 0; +- uint32_t v_cb6 = 0; +- uint32_t v_ccp = 0; +- uint32_t v_ccm = 0; +- uint32_t v_cd0 = 0; +- uint32_t v_cd1 = 0; +- uint32_t v_cd2 = 0; +- uint32_t v_cd3 = 0; +- uint32_t v_bq1 = 0; +- uint32_t v_bq3 = 0; +- uint32_t v_bq5 = 0; +- uint32_t v_bq7 = 0; +- uint32_t v_ci51 = 0; +- uint32_t v_ci53 = 0; +- uint32_t v_ci71 = 0; +- uint32_t v_ci73 = 0; +- uint32_t v_cj = 0; +- uint32_t v_ck1 = 0; +- uint32_t v_ck3 = 0; +- uint32_t v_ck5 = 0; +- uint32_t v_ck7 = 0; +- uint32_t v_cl51 = 0; +- uint32_t v_cl73 = 0; +- uint32_t v_in0 = 0; +- uint32_t v_in2 = 0; +- uint32_t v_in4 = 0; +- uint32_t v_in6 = 0; +- uint32_t v_ra = 0; +- uint32_t v_rb2 = 0; +- uint32_t v_rb6 = 0; +- uint32_t v_rcp = 0; +- uint32_t v_rcm = 0; +- uint32_t v_rd0 = 0; +- uint32_t v_rd1 = 0; +- uint32_t v_rd2 = 0; +- uint32_t v_rd3 = 0; +- uint32_t v_in1 = 0; +- uint32_t v_in3 = 0; +- uint32_t v_in5 = 0; +- uint32_t v_in7 = 0; +- uint32_t v_ri51 = 0; +- uint32_t v_ri53 = 0; +- uint32_t v_ri71 = 0; +- uint32_t v_ri73 = 0; +- uint32_t v_rj = 0; +- uint32_t v_rk1 = 0; +- uint32_t v_rk3 = 0; +- uint32_t v_rk5 = 0; +- uint32_t v_rk7 = 0; +- uint32_t v_rl51 = 0; +- uint32_t v_rl73 = 0; +- uint32_t v_intermediate[64] = {0}; ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (8u > a_dst_stride) { +- return wuffs_base__make_empty_struct(); +- } +- if (0u == (self->private_data.f_mcu_blocks[0u][8u] | +- self->private_data.f_mcu_blocks[0u][16u] | +- self->private_data.f_mcu_blocks[0u][24u] | +- self->private_data.f_mcu_blocks[0u][32u] | +- self->private_data.f_mcu_blocks[0u][40u] | +- self->private_data.f_mcu_blocks[0u][48u] | +- self->private_data.f_mcu_blocks[0u][56u])) { +- v_intermediate[0u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][0u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][0u])))) << 2u)); +- v_intermediate[8u] = v_intermediate[0u]; +- v_intermediate[16u] = v_intermediate[0u]; +- v_intermediate[24u] = v_intermediate[0u]; +- v_intermediate[32u] = v_intermediate[0u]; +- v_intermediate[40u] = v_intermediate[0u]; +- v_intermediate[48u] = v_intermediate[0u]; +- v_intermediate[56u] = v_intermediate[0u]; +- } else { +- v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][16u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][16u])))); +- v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][48u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][48u])))); +- v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); +- v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); +- v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); +- v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][0u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][0u])))); +- v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][32u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][32u])))); +- v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); +- v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); +- v_cd0 = ((uint32_t)(v_ccp + v_cb2)); +- v_cd1 = ((uint32_t)(v_ccm + v_cb6)); +- v_cd2 = ((uint32_t)(v_ccm - v_cb6)); +- v_cd3 = ((uint32_t)(v_ccp - v_cb2)); +- v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][8u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][8u])))); +- v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][24u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][24u])))); +- v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][40u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][40u])))); +- v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][56u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][56u])))); +- v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); +- v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); +- v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); +- v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); +- v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); +- v_ck1 = ((uint32_t)(v_bq1 * 12299u)); +- v_ck3 = ((uint32_t)(v_bq3 * 25172u)); +- v_ck5 = ((uint32_t)(v_bq5 * 16819u)); +- v_ck7 = ((uint32_t)(v_bq7 * 2446u)); +- v_ci51 *= 4294964100u; +- v_ci53 *= 4294946301u; +- v_ci71 *= 4294959923u; +- v_ci73 *= 4294951227u; +- v_cl51 = ((uint32_t)(v_ci51 + v_cj)); +- v_cl73 = ((uint32_t)(v_ci73 + v_cj)); +- v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); +- v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); +- v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); +- v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); +- v_intermediate[0u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); +- v_intermediate[56u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); +- v_intermediate[8u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); +- v_intermediate[48u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); +- v_intermediate[16u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); +- v_intermediate[40u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); +- v_intermediate[24u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); +- v_intermediate[32u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_gif__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ if (self->private_impl.f_quirks[5u] && ((self->private_impl.f_frame_rect_x0 == self->private_impl.f_frame_rect_x1) || (self->private_impl.f_frame_rect_y0 == self->private_impl.f_frame_rect_y1))) { ++ status = wuffs_base__make_status(wuffs_gif__error__bad_frame_size); ++ goto exit; ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_gif__decoder__decode_id_part1(self, a_dst, a_src, a_blend); ++ if (status.repr) { ++ goto suspend; ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_gif__decoder__decode_id_part2(self, a_dst, a_src, a_workbuf); ++ if (status.repr) { ++ goto suspend; ++ } ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); ++ wuffs_gif__decoder__reset_gc(self); ++ self->private_impl.f_call_sequence = 32u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame = 0; ++ goto exit; + } +- if (0u == (self->private_data.f_mcu_blocks[0u][9u] | +- self->private_data.f_mcu_blocks[0u][17u] | +- self->private_data.f_mcu_blocks[0u][25u] | +- self->private_data.f_mcu_blocks[0u][33u] | +- self->private_data.f_mcu_blocks[0u][41u] | +- self->private_data.f_mcu_blocks[0u][49u] | +- self->private_data.f_mcu_blocks[0u][57u])) { +- v_intermediate[1u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][1u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][1u])))) << 2u)); +- v_intermediate[9u] = v_intermediate[1u]; +- v_intermediate[17u] = v_intermediate[1u]; +- v_intermediate[25u] = v_intermediate[1u]; +- v_intermediate[33u] = v_intermediate[1u]; +- v_intermediate[41u] = v_intermediate[1u]; +- v_intermediate[49u] = v_intermediate[1u]; +- v_intermediate[57u] = v_intermediate[1u]; +- } else { +- v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][17u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][17u])))); +- v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][49u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][49u])))); +- v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); +- v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); +- v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); +- v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][1u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][1u])))); +- v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][33u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][33u])))); +- v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); +- v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); +- v_cd0 = ((uint32_t)(v_ccp + v_cb2)); +- v_cd1 = ((uint32_t)(v_ccm + v_cb6)); +- v_cd2 = ((uint32_t)(v_ccm - v_cb6)); +- v_cd3 = ((uint32_t)(v_ccp - v_cb2)); +- v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][9u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][9u])))); +- v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][25u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][25u])))); +- v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][41u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][41u])))); +- v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][57u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][57u])))); +- v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); +- v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); +- v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); +- v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); +- v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); +- v_ck1 = ((uint32_t)(v_bq1 * 12299u)); +- v_ck3 = ((uint32_t)(v_bq3 * 25172u)); +- v_ck5 = ((uint32_t)(v_bq5 * 16819u)); +- v_ck7 = ((uint32_t)(v_bq7 * 2446u)); +- v_ci51 *= 4294964100u; +- v_ci53 *= 4294946301u; +- v_ci71 *= 4294959923u; +- v_ci73 *= 4294951227u; +- v_cl51 = ((uint32_t)(v_ci51 + v_cj)); +- v_cl73 = ((uint32_t)(v_ci73 + v_cj)); +- v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); +- v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); +- v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); +- v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); +- v_intermediate[1u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); +- v_intermediate[57u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); +- v_intermediate[9u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); +- v_intermediate[49u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); +- v_intermediate[17u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); +- v_intermediate[41u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); +- v_intermediate[25u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); +- v_intermediate[33u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ return status; ++} ++ ++// -------- func gif.decoder.reset_gc ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_gif__decoder__reset_gc( ++ wuffs_gif__decoder* self) { ++ self->private_impl.f_gc_has_transparent_index = false; ++ self->private_impl.f_gc_transparent_index = 0u; ++ self->private_impl.f_gc_disposal = 0u; ++ self->private_impl.f_gc_duration = 0u; ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func gif.decoder.decode_up_to_id_part1 ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_up_to_id_part1( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_block_type = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- if (0u == (self->private_data.f_mcu_blocks[0u][10u] | +- self->private_data.f_mcu_blocks[0u][18u] | +- self->private_data.f_mcu_blocks[0u][26u] | +- self->private_data.f_mcu_blocks[0u][34u] | +- self->private_data.f_mcu_blocks[0u][42u] | +- self->private_data.f_mcu_blocks[0u][50u] | +- self->private_data.f_mcu_blocks[0u][58u])) { +- v_intermediate[2u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][2u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][2u])))) << 2u)); +- v_intermediate[10u] = v_intermediate[2u]; +- v_intermediate[18u] = v_intermediate[2u]; +- v_intermediate[26u] = v_intermediate[2u]; +- v_intermediate[34u] = v_intermediate[2u]; +- v_intermediate[42u] = v_intermediate[2u]; +- v_intermediate[50u] = v_intermediate[2u]; +- v_intermediate[58u] = v_intermediate[2u]; +- } else { +- v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][18u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][18u])))); +- v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][50u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][50u])))); +- v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); +- v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); +- v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); +- v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][2u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][2u])))); +- v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][34u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][34u])))); +- v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); +- v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); +- v_cd0 = ((uint32_t)(v_ccp + v_cb2)); +- v_cd1 = ((uint32_t)(v_ccm + v_cb6)); +- v_cd2 = ((uint32_t)(v_ccm - v_cb6)); +- v_cd3 = ((uint32_t)(v_ccp - v_cb2)); +- v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][10u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][10u])))); +- v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][26u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][26u])))); +- v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][42u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][42u])))); +- v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][58u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][58u])))); +- v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); +- v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); +- v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); +- v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); +- v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); +- v_ck1 = ((uint32_t)(v_bq1 * 12299u)); +- v_ck3 = ((uint32_t)(v_bq3 * 25172u)); +- v_ck5 = ((uint32_t)(v_bq5 * 16819u)); +- v_ck7 = ((uint32_t)(v_bq7 * 2446u)); +- v_ci51 *= 4294964100u; +- v_ci53 *= 4294946301u; +- v_ci71 *= 4294959923u; +- v_ci73 *= 4294951227u; +- v_cl51 = ((uint32_t)(v_ci51 + v_cj)); +- v_cl73 = ((uint32_t)(v_ci73 + v_cj)); +- v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); +- v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); +- v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); +- v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); +- v_intermediate[2u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); +- v_intermediate[58u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); +- v_intermediate[10u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); +- v_intermediate[50u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); +- v_intermediate[18u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); +- v_intermediate[42u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); +- v_intermediate[26u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); +- v_intermediate[34u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_up_to_id_part1; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if ((self->private_impl.f_frame_config_io_position == 0u) || (self->private_impl.f_num_decoded_frame_configs_value > 0u)) { ++ self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_block_type = t_0; ++ } ++ if (v_block_type == 33u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_gif__decoder__decode_extension(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (v_block_type == 44u) { ++ if (self->private_impl.f_delayed_num_decoded_frames) { ++ self->private_impl.f_delayed_num_decoded_frames = false; ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_gif__decoder__decode_id_part0(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ break; ++ } else { ++ if (self->private_impl.f_delayed_num_decoded_frames) { ++ self->private_impl.f_delayed_num_decoded_frames = false; ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); ++ } ++ self->private_impl.f_call_sequence = 96u; ++ break; ++ } ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_up_to_id_part1 = 0; ++ goto exit; + } +- if (0u == (self->private_data.f_mcu_blocks[0u][11u] | +- self->private_data.f_mcu_blocks[0u][19u] | +- self->private_data.f_mcu_blocks[0u][27u] | +- self->private_data.f_mcu_blocks[0u][35u] | +- self->private_data.f_mcu_blocks[0u][43u] | +- self->private_data.f_mcu_blocks[0u][51u] | +- self->private_data.f_mcu_blocks[0u][59u])) { +- v_intermediate[3u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][3u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][3u])))) << 2u)); +- v_intermediate[11u] = v_intermediate[3u]; +- v_intermediate[19u] = v_intermediate[3u]; +- v_intermediate[27u] = v_intermediate[3u]; +- v_intermediate[35u] = v_intermediate[3u]; +- v_intermediate[43u] = v_intermediate[3u]; +- v_intermediate[51u] = v_intermediate[3u]; +- v_intermediate[59u] = v_intermediate[3u]; +- } else { +- v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][19u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][19u])))); +- v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][51u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][51u])))); +- v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); +- v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); +- v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); +- v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][3u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][3u])))); +- v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][35u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][35u])))); +- v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); +- v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); +- v_cd0 = ((uint32_t)(v_ccp + v_cb2)); +- v_cd1 = ((uint32_t)(v_ccm + v_cb6)); +- v_cd2 = ((uint32_t)(v_ccm - v_cb6)); +- v_cd3 = ((uint32_t)(v_ccp - v_cb2)); +- v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][11u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][11u])))); +- v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][27u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][27u])))); +- v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][43u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][43u])))); +- v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][59u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][59u])))); +- v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); +- v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); +- v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); +- v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); +- v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); +- v_ck1 = ((uint32_t)(v_bq1 * 12299u)); +- v_ck3 = ((uint32_t)(v_bq3 * 25172u)); +- v_ck5 = ((uint32_t)(v_bq5 * 16819u)); +- v_ck7 = ((uint32_t)(v_bq7 * 2446u)); +- v_ci51 *= 4294964100u; +- v_ci53 *= 4294946301u; +- v_ci71 *= 4294959923u; +- v_ci73 *= 4294951227u; +- v_cl51 = ((uint32_t)(v_ci51 + v_cj)); +- v_cl73 = ((uint32_t)(v_ci73 + v_cj)); +- v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); +- v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); +- v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); +- v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); +- v_intermediate[3u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); +- v_intermediate[59u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); +- v_intermediate[11u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); +- v_intermediate[51u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); +- v_intermediate[19u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); +- v_intermediate[43u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); +- v_intermediate[27u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); +- v_intermediate[35u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_up_to_id_part1 = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- if (0u == (self->private_data.f_mcu_blocks[0u][12u] | +- self->private_data.f_mcu_blocks[0u][20u] | +- self->private_data.f_mcu_blocks[0u][28u] | +- self->private_data.f_mcu_blocks[0u][36u] | +- self->private_data.f_mcu_blocks[0u][44u] | +- self->private_data.f_mcu_blocks[0u][52u] | +- self->private_data.f_mcu_blocks[0u][60u])) { +- v_intermediate[4u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][4u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][4u])))) << 2u)); +- v_intermediate[12u] = v_intermediate[4u]; +- v_intermediate[20u] = v_intermediate[4u]; +- v_intermediate[28u] = v_intermediate[4u]; +- v_intermediate[36u] = v_intermediate[4u]; +- v_intermediate[44u] = v_intermediate[4u]; +- v_intermediate[52u] = v_intermediate[4u]; +- v_intermediate[60u] = v_intermediate[4u]; +- } else { +- v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][20u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][20u])))); +- v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][52u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][52u])))); +- v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); +- v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); +- v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); +- v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][4u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][4u])))); +- v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][36u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][36u])))); +- v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); +- v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); +- v_cd0 = ((uint32_t)(v_ccp + v_cb2)); +- v_cd1 = ((uint32_t)(v_ccm + v_cb6)); +- v_cd2 = ((uint32_t)(v_ccm - v_cb6)); +- v_cd3 = ((uint32_t)(v_ccp - v_cb2)); +- v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][12u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][12u])))); +- v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][28u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][28u])))); +- v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][44u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][44u])))); +- v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][60u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][60u])))); +- v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); +- v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); +- v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); +- v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); +- v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); +- v_ck1 = ((uint32_t)(v_bq1 * 12299u)); +- v_ck3 = ((uint32_t)(v_bq3 * 25172u)); +- v_ck5 = ((uint32_t)(v_bq5 * 16819u)); +- v_ck7 = ((uint32_t)(v_bq7 * 2446u)); +- v_ci51 *= 4294964100u; +- v_ci53 *= 4294946301u; +- v_ci71 *= 4294959923u; +- v_ci73 *= 4294951227u; +- v_cl51 = ((uint32_t)(v_ci51 + v_cj)); +- v_cl73 = ((uint32_t)(v_ci73 + v_cj)); +- v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); +- v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); +- v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); +- v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); +- v_intermediate[4u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); +- v_intermediate[60u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); +- v_intermediate[12u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); +- v_intermediate[52u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); +- v_intermediate[20u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); +- v_intermediate[44u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); +- v_intermediate[28u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); +- v_intermediate[36u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); ++ ++ return status; ++} ++ ++// -------- func gif.decoder.decode_header ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_header( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint64_t v_c48 = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- if (0u == (self->private_data.f_mcu_blocks[0u][13u] | +- self->private_data.f_mcu_blocks[0u][21u] | +- self->private_data.f_mcu_blocks[0u][29u] | +- self->private_data.f_mcu_blocks[0u][37u] | +- self->private_data.f_mcu_blocks[0u][45u] | +- self->private_data.f_mcu_blocks[0u][53u] | +- self->private_data.f_mcu_blocks[0u][61u])) { +- v_intermediate[5u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][5u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][5u])))) << 2u)); +- v_intermediate[13u] = v_intermediate[5u]; +- v_intermediate[21u] = v_intermediate[5u]; +- v_intermediate[29u] = v_intermediate[5u]; +- v_intermediate[37u] = v_intermediate[5u]; +- v_intermediate[45u] = v_intermediate[5u]; +- v_intermediate[53u] = v_intermediate[5u]; +- v_intermediate[61u] = v_intermediate[5u]; +- } else { +- v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][21u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][21u])))); +- v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][53u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][53u])))); +- v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); +- v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); +- v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); +- v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][5u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][5u])))); +- v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][37u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][37u])))); +- v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); +- v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); +- v_cd0 = ((uint32_t)(v_ccp + v_cb2)); +- v_cd1 = ((uint32_t)(v_ccm + v_cb6)); +- v_cd2 = ((uint32_t)(v_ccm - v_cb6)); +- v_cd3 = ((uint32_t)(v_ccp - v_cb2)); +- v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][13u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][13u])))); +- v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][29u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][29u])))); +- v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][45u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][45u])))); +- v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][61u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][61u])))); +- v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); +- v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); +- v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); +- v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); +- v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); +- v_ck1 = ((uint32_t)(v_bq1 * 12299u)); +- v_ck3 = ((uint32_t)(v_bq3 * 25172u)); +- v_ck5 = ((uint32_t)(v_bq5 * 16819u)); +- v_ck7 = ((uint32_t)(v_bq7 * 2446u)); +- v_ci51 *= 4294964100u; +- v_ci53 *= 4294946301u; +- v_ci71 *= 4294959923u; +- v_ci73 *= 4294951227u; +- v_cl51 = ((uint32_t)(v_ci51 + v_cj)); +- v_cl73 = ((uint32_t)(v_ci73 + v_cj)); +- v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); +- v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); +- v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); +- v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); +- v_intermediate[5u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); +- v_intermediate[61u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); +- v_intermediate[13u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); +- v_intermediate[53u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); +- v_intermediate[21u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); +- v_intermediate[45u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); +- v_intermediate[29u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); +- v_intermediate[37u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_header; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint64_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 6)) { ++ t_0 = ((uint64_t)(wuffs_base__peek_u48le__no_bounds_check(iop_a_src))); ++ iop_a_src += 6; ++ } else { ++ self->private_data.s_decode_header.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_header.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 40) { ++ t_0 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ v_c48 = t_0; ++ } ++ if ((v_c48 != 106889795225927u) && (v_c48 != 106898385160519u)) { ++ status = wuffs_base__make_status(wuffs_gif__error__bad_header); ++ goto exit; ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_header = 0; ++ goto exit; + } +- if (0u == (self->private_data.f_mcu_blocks[0u][14u] | +- self->private_data.f_mcu_blocks[0u][22u] | +- self->private_data.f_mcu_blocks[0u][30u] | +- self->private_data.f_mcu_blocks[0u][38u] | +- self->private_data.f_mcu_blocks[0u][46u] | +- self->private_data.f_mcu_blocks[0u][54u] | +- self->private_data.f_mcu_blocks[0u][62u])) { +- v_intermediate[6u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][6u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][6u])))) << 2u)); +- v_intermediate[14u] = v_intermediate[6u]; +- v_intermediate[22u] = v_intermediate[6u]; +- v_intermediate[30u] = v_intermediate[6u]; +- v_intermediate[38u] = v_intermediate[6u]; +- v_intermediate[46u] = v_intermediate[6u]; +- v_intermediate[54u] = v_intermediate[6u]; +- v_intermediate[62u] = v_intermediate[6u]; +- } else { +- v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][22u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][22u])))); +- v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][54u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][54u])))); +- v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); +- v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); +- v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); +- v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][6u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][6u])))); +- v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][38u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][38u])))); +- v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); +- v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); +- v_cd0 = ((uint32_t)(v_ccp + v_cb2)); +- v_cd1 = ((uint32_t)(v_ccm + v_cb6)); +- v_cd2 = ((uint32_t)(v_ccm - v_cb6)); +- v_cd3 = ((uint32_t)(v_ccp - v_cb2)); +- v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][14u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][14u])))); +- v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][30u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][30u])))); +- v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][46u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][46u])))); +- v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][62u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][62u])))); +- v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); +- v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); +- v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); +- v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); +- v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); +- v_ck1 = ((uint32_t)(v_bq1 * 12299u)); +- v_ck3 = ((uint32_t)(v_bq3 * 25172u)); +- v_ck5 = ((uint32_t)(v_bq5 * 16819u)); +- v_ck7 = ((uint32_t)(v_bq7 * 2446u)); +- v_ci51 *= 4294964100u; +- v_ci53 *= 4294946301u; +- v_ci71 *= 4294959923u; +- v_ci73 *= 4294951227u; +- v_cl51 = ((uint32_t)(v_ci51 + v_cj)); +- v_cl73 = ((uint32_t)(v_ci73 + v_cj)); +- v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); +- v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); +- v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); +- v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); +- v_intermediate[6u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); +- v_intermediate[62u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); +- v_intermediate[14u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); +- v_intermediate[54u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); +- v_intermediate[22u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); +- v_intermediate[46u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); +- v_intermediate[30u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); +- v_intermediate[38u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_header = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- if (0u == (self->private_data.f_mcu_blocks[0u][15u] | +- self->private_data.f_mcu_blocks[0u][23u] | +- self->private_data.f_mcu_blocks[0u][31u] | +- self->private_data.f_mcu_blocks[0u][39u] | +- self->private_data.f_mcu_blocks[0u][47u] | +- self->private_data.f_mcu_blocks[0u][55u] | +- self->private_data.f_mcu_blocks[0u][63u])) { +- v_intermediate[7u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][7u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][7u])))) << 2u)); +- v_intermediate[15u] = v_intermediate[7u]; +- v_intermediate[23u] = v_intermediate[7u]; +- v_intermediate[31u] = v_intermediate[7u]; +- v_intermediate[39u] = v_intermediate[7u]; +- v_intermediate[47u] = v_intermediate[7u]; +- v_intermediate[55u] = v_intermediate[7u]; +- v_intermediate[63u] = v_intermediate[7u]; +- } else { +- v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][23u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][23u])))); +- v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][55u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][55u])))); +- v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); +- v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); +- v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); +- v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][7u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][7u])))); +- v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][39u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][39u])))); +- v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); +- v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); +- v_cd0 = ((uint32_t)(v_ccp + v_cb2)); +- v_cd1 = ((uint32_t)(v_ccm + v_cb6)); +- v_cd2 = ((uint32_t)(v_ccm - v_cb6)); +- v_cd3 = ((uint32_t)(v_ccp - v_cb2)); +- v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][15u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][15u])))); +- v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][31u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][31u])))); +- v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][47u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][47u])))); +- v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][63u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][63u])))); +- v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); +- v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); +- v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); +- v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); +- v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); +- v_ck1 = ((uint32_t)(v_bq1 * 12299u)); +- v_ck3 = ((uint32_t)(v_bq3 * 25172u)); +- v_ck5 = ((uint32_t)(v_bq5 * 16819u)); +- v_ck7 = ((uint32_t)(v_bq7 * 2446u)); +- v_ci51 *= 4294964100u; +- v_ci53 *= 4294946301u; +- v_ci71 *= 4294959923u; +- v_ci73 *= 4294951227u; +- v_cl51 = ((uint32_t)(v_ci51 + v_cj)); +- v_cl73 = ((uint32_t)(v_ci73 + v_cj)); +- v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); +- v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); +- v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); +- v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); +- v_intermediate[7u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); +- v_intermediate[63u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); +- v_intermediate[15u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); +- v_intermediate[55u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); +- v_intermediate[23u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); +- v_intermediate[47u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); +- v_intermediate[31u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); +- v_intermediate[39u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); ++ ++ return status; ++} ++ ++// -------- func gif.decoder.decode_lsd ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_lsd( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_flags = 0; ++ uint8_t v_background_color_index = 0; ++ uint32_t v_num_palette_entries = 0; ++ uint32_t v_i = 0; ++ uint32_t v_j = 0; ++ uint32_t v_argb = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- if (0u == (v_intermediate[1u] | +- v_intermediate[2u] | +- v_intermediate[3u] | +- v_intermediate[4u] | +- v_intermediate[5u] | +- v_intermediate[6u] | +- v_intermediate[7u])) { +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[0u] + 16u)) >> 5u) & 1023u)]; +- a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } else { +- v_in2 = v_intermediate[2u]; +- v_in6 = v_intermediate[6u]; +- v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); +- v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); +- v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); +- v_in0 = v_intermediate[0u]; +- v_in4 = v_intermediate[4u]; +- v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); +- v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); +- v_rd0 = ((uint32_t)(v_rcp + v_rb2)); +- v_rd1 = ((uint32_t)(v_rcm + v_rb6)); +- v_rd2 = ((uint32_t)(v_rcm - v_rb6)); +- v_rd3 = ((uint32_t)(v_rcp - v_rb2)); +- v_in1 = v_intermediate[1u]; +- v_in3 = v_intermediate[3u]; +- v_in5 = v_intermediate[5u]; +- v_in7 = v_intermediate[7u]; +- v_ri51 = ((uint32_t)(v_in5 + v_in1)); +- v_ri53 = ((uint32_t)(v_in5 + v_in3)); +- v_ri71 = ((uint32_t)(v_in7 + v_in1)); +- v_ri73 = ((uint32_t)(v_in7 + v_in3)); +- v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); +- v_rk1 = ((uint32_t)(v_in1 * 12299u)); +- v_rk3 = ((uint32_t)(v_in3 * 25172u)); +- v_rk5 = ((uint32_t)(v_in5 * 16819u)); +- v_rk7 = ((uint32_t)(v_in7 * 2446u)); +- v_ri51 *= 4294964100u; +- v_ri53 *= 4294946301u; +- v_ri71 *= 4294959923u; +- v_ri73 *= 4294951227u; +- v_rl51 = ((uint32_t)(v_ri51 + v_rj)); +- v_rl73 = ((uint32_t)(v_ri73 + v_rj)); +- v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); +- v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); +- v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); +- v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_lsd; ++ if (coro_susp_point) { ++ v_flags = self->private_data.s_decode_lsd.v_flags; ++ v_background_color_index = self->private_data.s_decode_lsd.v_background_color_index; ++ v_num_palette_entries = self->private_data.s_decode_lsd.v_num_palette_entries; ++ v_i = self->private_data.s_decode_lsd.v_i; + } +- if (0u == (v_intermediate[9u] | +- v_intermediate[10u] | +- v_intermediate[11u] | +- v_intermediate[12u] | +- v_intermediate[13u] | +- v_intermediate[14u] | +- v_intermediate[15u])) { +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_lsd.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_lsd.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 8) { ++ t_0 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ self->private_impl.f_width = t_0; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[8u] + 16u)) >> 5u) & 1023u)]; +- a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } else { +- v_in2 = v_intermediate[10u]; +- v_in6 = v_intermediate[14u]; +- v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); +- v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); +- v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); +- v_in0 = v_intermediate[8u]; +- v_in4 = v_intermediate[12u]; +- v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); +- v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); +- v_rd0 = ((uint32_t)(v_rcp + v_rb2)); +- v_rd1 = ((uint32_t)(v_rcm + v_rb6)); +- v_rd2 = ((uint32_t)(v_rcm - v_rb6)); +- v_rd3 = ((uint32_t)(v_rcp - v_rb2)); +- v_in1 = v_intermediate[9u]; +- v_in3 = v_intermediate[11u]; +- v_in5 = v_intermediate[13u]; +- v_in7 = v_intermediate[15u]; +- v_ri51 = ((uint32_t)(v_in5 + v_in1)); +- v_ri53 = ((uint32_t)(v_in5 + v_in3)); +- v_ri71 = ((uint32_t)(v_in7 + v_in1)); +- v_ri73 = ((uint32_t)(v_in7 + v_in3)); +- v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); +- v_rk1 = ((uint32_t)(v_in1 * 12299u)); +- v_rk3 = ((uint32_t)(v_in3 * 25172u)); +- v_rk5 = ((uint32_t)(v_in5 * 16819u)); +- v_rk7 = ((uint32_t)(v_in7 * 2446u)); +- v_ri51 *= 4294964100u; +- v_ri53 *= 4294946301u; +- v_ri71 *= 4294959923u; +- v_ri73 *= 4294951227u; +- v_rl51 = ((uint32_t)(v_ri51 + v_rj)); +- v_rl73 = ((uint32_t)(v_ri73 + v_rj)); +- v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); +- v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); +- v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); +- v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_lsd.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_lsd.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 8) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ self->private_impl.f_height = t_1; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } +- if (0u == (v_intermediate[17u] | +- v_intermediate[18u] | +- v_intermediate[19u] | +- v_intermediate[20u] | +- v_intermediate[21u] | +- v_intermediate[22u] | +- v_intermediate[23u])) { +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_flags = t_2; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[16u] + 16u)) >> 5u) & 1023u)]; +- a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } else { +- v_in2 = v_intermediate[18u]; +- v_in6 = v_intermediate[22u]; +- v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); +- v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); +- v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); +- v_in0 = v_intermediate[16u]; +- v_in4 = v_intermediate[20u]; +- v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); +- v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); +- v_rd0 = ((uint32_t)(v_rcp + v_rb2)); +- v_rd1 = ((uint32_t)(v_rcm + v_rb6)); +- v_rd2 = ((uint32_t)(v_rcm - v_rb6)); +- v_rd3 = ((uint32_t)(v_rcp - v_rb2)); +- v_in1 = v_intermediate[17u]; +- v_in3 = v_intermediate[19u]; +- v_in5 = v_intermediate[21u]; +- v_in7 = v_intermediate[23u]; +- v_ri51 = ((uint32_t)(v_in5 + v_in1)); +- v_ri53 = ((uint32_t)(v_in5 + v_in3)); +- v_ri71 = ((uint32_t)(v_in7 + v_in1)); +- v_ri73 = ((uint32_t)(v_in7 + v_in3)); +- v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); +- v_rk1 = ((uint32_t)(v_in1 * 12299u)); +- v_rk3 = ((uint32_t)(v_in3 * 25172u)); +- v_rk5 = ((uint32_t)(v_in5 * 16819u)); +- v_rk7 = ((uint32_t)(v_in7 * 2446u)); +- v_ri51 *= 4294964100u; +- v_ri53 *= 4294946301u; +- v_ri71 *= 4294959923u; +- v_ri73 *= 4294951227u; +- v_rl51 = ((uint32_t)(v_ri51 + v_rj)); +- v_rl73 = ((uint32_t)(v_ri73 + v_rj)); +- v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); +- v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); +- v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); +- v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_background_color_index = t_3; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } +- if (0u == (v_intermediate[25u] | +- v_intermediate[26u] | +- v_intermediate[27u] | +- v_intermediate[28u] | +- v_intermediate[29u] | +- v_intermediate[30u] | +- v_intermediate[31u])) { +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[24u] + 16u)) >> 5u) & 1023u)]; +- a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } else { +- v_in2 = v_intermediate[26u]; +- v_in6 = v_intermediate[30u]; +- v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); +- v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); +- v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); +- v_in0 = v_intermediate[24u]; +- v_in4 = v_intermediate[28u]; +- v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); +- v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); +- v_rd0 = ((uint32_t)(v_rcp + v_rb2)); +- v_rd1 = ((uint32_t)(v_rcm + v_rb6)); +- v_rd2 = ((uint32_t)(v_rcm - v_rb6)); +- v_rd3 = ((uint32_t)(v_rcp - v_rb2)); +- v_in1 = v_intermediate[25u]; +- v_in3 = v_intermediate[27u]; +- v_in5 = v_intermediate[29u]; +- v_in7 = v_intermediate[31u]; +- v_ri51 = ((uint32_t)(v_in5 + v_in1)); +- v_ri53 = ((uint32_t)(v_in5 + v_in3)); +- v_ri71 = ((uint32_t)(v_in7 + v_in1)); +- v_ri73 = ((uint32_t)(v_in7 + v_in3)); +- v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); +- v_rk1 = ((uint32_t)(v_in1 * 12299u)); +- v_rk3 = ((uint32_t)(v_in3 * 25172u)); +- v_rk5 = ((uint32_t)(v_in5 * 16819u)); +- v_rk7 = ((uint32_t)(v_in7 * 2446u)); +- v_ri51 *= 4294964100u; +- v_ri53 *= 4294946301u; +- v_ri71 *= 4294959923u; +- v_ri73 *= 4294951227u; +- v_rl51 = ((uint32_t)(v_ri51 + v_rj)); +- v_rl73 = ((uint32_t)(v_ri73 + v_rj)); +- v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); +- v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); +- v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); +- v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } +- if (0u == (v_intermediate[33u] | +- v_intermediate[34u] | +- v_intermediate[35u] | +- v_intermediate[36u] | +- v_intermediate[37u] | +- v_intermediate[38u] | +- v_intermediate[39u])) { +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ iop_a_src++; ++ v_i = 0u; ++ self->private_impl.f_has_global_palette = (((uint8_t)(v_flags & 128u)) != 0u); ++ if (self->private_impl.f_has_global_palette) { ++ v_num_palette_entries = (((uint32_t)(1u)) << ((uint8_t)(1u + ((uint8_t)(v_flags & 7u))))); ++ while (v_i < v_num_palette_entries) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ uint32_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { ++ t_4 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src))); ++ iop_a_src += 3; ++ } else { ++ self->private_data.s_decode_lsd.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_lsd.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); ++ if (num_bits_4 == 16) { ++ t_4 = ((uint32_t)(*scratch >> 40)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)); ++ } ++ } ++ v_argb = t_4; ++ } ++ v_argb |= 4278190080u; ++ self->private_data.f_palettes[0u][((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); ++ self->private_data.f_palettes[0u][((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); ++ self->private_data.f_palettes[0u][((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); ++ self->private_data.f_palettes[0u][((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); ++ v_i += 1u; ++ } ++ if (self->private_impl.f_quirks[2u]) { ++ if ((v_background_color_index != 0u) && (((uint32_t)(v_background_color_index)) < v_num_palette_entries)) { ++ v_j = (4u * ((uint32_t)(v_background_color_index))); ++ self->private_impl.f_background_color_u32_argb_premul = ((((uint32_t)(self->private_data.f_palettes[0u][(v_j + 0u)])) << 0u) | ++ (((uint32_t)(self->private_data.f_palettes[0u][(v_j + 1u)])) << 8u) | ++ (((uint32_t)(self->private_data.f_palettes[0u][(v_j + 2u)])) << 16u) | ++ (((uint32_t)(self->private_data.f_palettes[0u][(v_j + 3u)])) << 24u)); ++ } else { ++ self->private_impl.f_background_color_u32_argb_premul = 77u; ++ } ++ } + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[32u] + 16u)) >> 5u) & 1023u)]; +- a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } else { +- v_in2 = v_intermediate[34u]; +- v_in6 = v_intermediate[38u]; +- v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); +- v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); +- v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); +- v_in0 = v_intermediate[32u]; +- v_in4 = v_intermediate[36u]; +- v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); +- v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); +- v_rd0 = ((uint32_t)(v_rcp + v_rb2)); +- v_rd1 = ((uint32_t)(v_rcm + v_rb6)); +- v_rd2 = ((uint32_t)(v_rcm - v_rb6)); +- v_rd3 = ((uint32_t)(v_rcp - v_rb2)); +- v_in1 = v_intermediate[33u]; +- v_in3 = v_intermediate[35u]; +- v_in5 = v_intermediate[37u]; +- v_in7 = v_intermediate[39u]; +- v_ri51 = ((uint32_t)(v_in5 + v_in1)); +- v_ri53 = ((uint32_t)(v_in5 + v_in3)); +- v_ri71 = ((uint32_t)(v_in7 + v_in1)); +- v_ri73 = ((uint32_t)(v_in7 + v_in3)); +- v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); +- v_rk1 = ((uint32_t)(v_in1 * 12299u)); +- v_rk3 = ((uint32_t)(v_in3 * 25172u)); +- v_rk5 = ((uint32_t)(v_in5 * 16819u)); +- v_rk7 = ((uint32_t)(v_in7 * 2446u)); +- v_ri51 *= 4294964100u; +- v_ri53 *= 4294946301u; +- v_ri71 *= 4294959923u; +- v_ri73 *= 4294951227u; +- v_rl51 = ((uint32_t)(v_ri51 + v_rj)); +- v_rl73 = ((uint32_t)(v_ri73 + v_rj)); +- v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); +- v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); +- v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); +- v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ while (v_i < 256u) { ++ self->private_data.f_palettes[0u][((4u * v_i) + 0u)] = 0u; ++ self->private_data.f_palettes[0u][((4u * v_i) + 1u)] = 0u; ++ self->private_data.f_palettes[0u][((4u * v_i) + 2u)] = 0u; ++ self->private_data.f_palettes[0u][((4u * v_i) + 3u)] = 255u; ++ v_i += 1u; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_lsd = 0; ++ goto exit; + } +- if (0u == (v_intermediate[41u] | +- v_intermediate[42u] | +- v_intermediate[43u] | +- v_intermediate[44u] | +- v_intermediate[45u] | +- v_intermediate[46u] | +- v_intermediate[47u])) { +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[40u] + 16u)) >> 5u) & 1023u)]; +- a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } else { +- v_in2 = v_intermediate[42u]; +- v_in6 = v_intermediate[46u]; +- v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); +- v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); +- v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); +- v_in0 = v_intermediate[40u]; +- v_in4 = v_intermediate[44u]; +- v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); +- v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); +- v_rd0 = ((uint32_t)(v_rcp + v_rb2)); +- v_rd1 = ((uint32_t)(v_rcm + v_rb6)); +- v_rd2 = ((uint32_t)(v_rcm - v_rb6)); +- v_rd3 = ((uint32_t)(v_rcp - v_rb2)); +- v_in1 = v_intermediate[41u]; +- v_in3 = v_intermediate[43u]; +- v_in5 = v_intermediate[45u]; +- v_in7 = v_intermediate[47u]; +- v_ri51 = ((uint32_t)(v_in5 + v_in1)); +- v_ri53 = ((uint32_t)(v_in5 + v_in3)); +- v_ri71 = ((uint32_t)(v_in7 + v_in1)); +- v_ri73 = ((uint32_t)(v_in7 + v_in3)); +- v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); +- v_rk1 = ((uint32_t)(v_in1 * 12299u)); +- v_rk3 = ((uint32_t)(v_in3 * 25172u)); +- v_rk5 = ((uint32_t)(v_in5 * 16819u)); +- v_rk7 = ((uint32_t)(v_in7 * 2446u)); +- v_ri51 *= 4294964100u; +- v_ri53 *= 4294946301u; +- v_ri71 *= 4294959923u; +- v_ri73 *= 4294951227u; +- v_rl51 = ((uint32_t)(v_ri51 + v_rj)); +- v_rl73 = ((uint32_t)(v_ri73 + v_rj)); +- v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); +- v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); +- v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); +- v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_lsd = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_lsd.v_flags = v_flags; ++ self->private_data.s_decode_lsd.v_background_color_index = v_background_color_index; ++ self->private_data.s_decode_lsd.v_num_palette_entries = v_num_palette_entries; ++ self->private_data.s_decode_lsd.v_i = v_i; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- if (0u == (v_intermediate[49u] | +- v_intermediate[50u] | +- v_intermediate[51u] | +- v_intermediate[52u] | +- v_intermediate[53u] | +- v_intermediate[54u] | +- v_intermediate[55u])) { +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ ++ return status; ++} ++ ++// -------- func gif.decoder.decode_extension ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_gif__decoder__decode_extension( ++ wuffs_gif__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_label = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_extension; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_label = t_0; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[48u] + 16u)) >> 5u) & 1023u)]; +- a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } else { +- v_in2 = v_intermediate[50u]; +- v_in6 = v_intermediate[54u]; +- v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); +- v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); +- v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); +- v_in0 = v_intermediate[48u]; +- v_in4 = v_intermediate[52u]; +- v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); +- v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); +- v_rd0 = ((uint32_t)(v_rcp + v_rb2)); +- v_rd1 = ((uint32_t)(v_rcm + v_rb6)); +- v_rd2 = ((uint32_t)(v_rcm - v_rb6)); +- v_rd3 = ((uint32_t)(v_rcp - v_rb2)); +- v_in1 = v_intermediate[49u]; +- v_in3 = v_intermediate[51u]; +- v_in5 = v_intermediate[53u]; +- v_in7 = v_intermediate[55u]; +- v_ri51 = ((uint32_t)(v_in5 + v_in1)); +- v_ri53 = ((uint32_t)(v_in5 + v_in3)); +- v_ri71 = ((uint32_t)(v_in7 + v_in1)); +- v_ri73 = ((uint32_t)(v_in7 + v_in3)); +- v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); +- v_rk1 = ((uint32_t)(v_in1 * 12299u)); +- v_rk3 = ((uint32_t)(v_in3 * 25172u)); +- v_rk5 = ((uint32_t)(v_in5 * 16819u)); +- v_rk7 = ((uint32_t)(v_in7 * 2446u)); +- v_ri51 *= 4294964100u; +- v_ri53 *= 4294946301u; +- v_ri71 *= 4294959923u; +- v_ri73 *= 4294951227u; +- v_rl51 = ((uint32_t)(v_ri51 + v_rj)); +- v_rl73 = ((uint32_t)(v_ri73 + v_rj)); +- v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); +- v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); +- v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); +- v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ if (v_label == 249u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_gif__decoder__decode_gc(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } else if (v_label == 255u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_gif__decoder__decode_ae(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ status = wuffs_base__make_status(NULL); ++ goto ok; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- } +- if (0u == (v_intermediate[57u] | +- v_intermediate[58u] | +- v_intermediate[59u] | +- v_intermediate[60u] | +- v_intermediate[61u] | +- v_intermediate[62u] | +- v_intermediate[63u])) { +- if (8u > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[56u] + 16u)) >> 5u) & 1023u)]; +- a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; +- a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; +- } else { +- v_in2 = v_intermediate[58u]; +- v_in6 = v_intermediate[62u]; +- v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); +- v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); +- v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); +- v_in0 = v_intermediate[56u]; +- v_in4 = v_intermediate[60u]; +- v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); +- v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); +- v_rd0 = ((uint32_t)(v_rcp + v_rb2)); +- v_rd1 = ((uint32_t)(v_rcm + v_rb6)); +- v_rd2 = ((uint32_t)(v_rcm - v_rb6)); +- v_rd3 = ((uint32_t)(v_rcp - v_rb2)); +- v_in1 = v_intermediate[57u]; +- v_in3 = v_intermediate[59u]; +- v_in5 = v_intermediate[61u]; +- v_in7 = v_intermediate[63u]; +- v_ri51 = ((uint32_t)(v_in5 + v_in1)); +- v_ri53 = ((uint32_t)(v_in5 + v_in3)); +- v_ri71 = ((uint32_t)(v_in7 + v_in1)); +- v_ri73 = ((uint32_t)(v_in7 + v_in3)); +- v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); +- v_rk1 = ((uint32_t)(v_in1 * 12299u)); +- v_rk3 = ((uint32_t)(v_in3 * 25172u)); +- v_rk5 = ((uint32_t)(v_in5 * 16819u)); +- v_rk7 = ((uint32_t)(v_in7 * 2446u)); +- v_ri51 *= 4294964100u; +- v_ri53 *= 4294946301u; +- v_ri71 *= 4294959923u; +- v_ri73 *= 4294951227u; +- v_rl51 = ((uint32_t)(v_ri51 + v_rj)); +- v_rl73 = ((uint32_t)(v_ri73 + v_rj)); +- v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); +- v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); +- v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); +- v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); +- if (8u > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_gif__decoder__skip_blocks(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; + } +- a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; +- a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ if (status.repr) { ++ goto suspend; ++ } ++ ++ ok: ++ self->private_impl.p_decode_extension = 0; ++ goto exit; + } +- return wuffs_base__make_empty_struct(); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_extension = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; + } + +-// ‼ WUFFS MULTI-FILE SECTION +x86_avx2 +-// -------- func jpeg.decoder.decode_idct_x86_avx2 ++// -------- func gif.decoder.skip_blocks + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_jpeg__decoder__decode_idct_x86_avx2( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_dst_buffer, +- uint64_t a_dst_stride, +- uint32_t a_q) { +- __m256i v_k_0000 = {0}; +- __m256i v_k_8080 = {0}; +- __m256i v_k_0000_0002 = {0}; +- __m256i v_k_0001_FFFF = {0}; +- __m256i v_k_0400_0000 = {0}; +- __m256i v_k_29CF_1151_D630_1151 = {0}; +- __m256i v_k_E333_133E_ADFD_1051 = {0}; +- __m256i v_k_E6DC_25A1_1925_25A1 = {0}; +- __m256i v_k_ECC1_E333_EFB0_ADFD = {0}; +- __m128i v_az_coeffs = {0}; +- __m256i v_az_ah00 = {0}; +- __m256i v_az_ad00 = {0}; +- __m256i v_az_eh00 = {0}; +- __m256i v_az_adeh = {0}; +- __m256i v_rows01 = {0}; +- __m256i v_rows23 = {0}; +- __m256i v_rows45 = {0}; +- __m256i v_rows67 = {0}; +- __m256i v_quants01 = {0}; +- __m256i v_quants23 = {0}; +- __m256i v_quants45 = {0}; +- __m256i v_quants67 = {0}; +- __m256i v_rows04 = {0}; +- __m256i v_rows31 = {0}; +- __m256i v_rows26 = {0}; +- __m256i v_rows75 = {0}; +- __m256i v_fp_rows62 = {0}; +- __m256i v_fp_bq2662ad = {0}; +- __m256i v_fp_bq2662eh = {0}; +- __m256i v_fp_cb26ad = {0}; +- __m256i v_fp_cb26eh = {0}; +- __m256i v_fp_rows40pos = {0}; +- __m256i v_fp_rows04neg = {0}; +- __m256i v_fp_rows0pm4 = {0}; +- __m256i v_fp_ccpmad = {0}; +- __m256i v_fp_ccpmeh = {0}; +- __m256i v_fp_cd01ad = {0}; +- __m256i v_fp_cd01eh = {0}; +- __m256i v_fp_cd32ad = {0}; +- __m256i v_fp_cd32eh = {0}; +- __m256i v_fp_sums7351 = {0}; +- __m256i v_fp_sums5173 = {0}; +- __m256i v_fp_ci73515173ad = {0}; +- __m256i v_fp_ci73515173eh = {0}; +- __m256i v_fp_cl7351ad = {0}; +- __m256i v_fp_cl7351eh = {0}; +- __m256i v_fp_rows13 = {0}; +- __m256i v_fp_bq7153ad = {0}; +- __m256i v_fp_bq7153eh = {0}; +- __m256i v_fp_ck75ad = {0}; +- __m256i v_fp_ck75eh = {0}; +- __m256i v_fp_cl5173ad = {0}; +- __m256i v_fp_cl5173eh = {0}; +- __m256i v_fp_ck13ad = {0}; +- __m256i v_fp_ck13eh = {0}; +- __m256i v_intermediate01ad = {0}; +- __m256i v_intermediate01eh = {0}; +- __m256i v_intermediate01 = {0}; +- __m256i v_intermediate32ad = {0}; +- __m256i v_intermediate32eh = {0}; +- __m256i v_intermediate32 = {0}; +- __m256i v_intermediate45ad = {0}; +- __m256i v_intermediate45eh = {0}; +- __m256i v_intermediate45 = {0}; +- __m256i v_intermediate76ad = {0}; +- __m256i v_intermediate76eh = {0}; +- __m256i v_intermediate76 = {0}; +- __m256i v_ita0a1e0e1 = {0}; +- __m256i v_ita2a3e2e3 = {0}; +- __m256i v_ita4a5e4e5 = {0}; +- __m256i v_ita6a7e6e7 = {0}; +- __m256i v_ita0c0e0g0 = {0}; +- __m256i v_ita1c1e1g1 = {0}; +- __m256i v_ita4c4e4g4 = {0}; +- __m256i v_ita5c5e5g5 = {0}; +- __m256i v_ita0b0e0f0 = {0}; +- __m256i v_ita4b4e4f4 = {0}; +- __m256i v_itc0d0g0h0 = {0}; +- __m256i v_itc4d4g4h4 = {0}; +- __m256i v_intermediateae = {0}; +- __m256i v_intermediatebf = {0}; +- __m256i v_intermediatecg = {0}; +- __m256i v_intermediatedh = {0}; +- __m256i v_intermediatedb = {0}; +- __m256i v_intermediatehf = {0}; +- __m256i v_sp_cols62 = {0}; +- __m256i v_sp_bq2662ad = {0}; +- __m256i v_sp_bq2662eh = {0}; +- __m256i v_sp_rb26ad = {0}; +- __m256i v_sp_rb26eh = {0}; +- __m256i v_sp_cols40pos = {0}; +- __m256i v_sp_cols04neg = {0}; +- __m256i v_sp_cols0pm4 = {0}; +- __m256i v_sp_rcpmad = {0}; +- __m256i v_sp_rcpmeh = {0}; +- __m256i v_sp_rd01ad = {0}; +- __m256i v_sp_rd01eh = {0}; +- __m256i v_sp_rd32ad = {0}; +- __m256i v_sp_rd32eh = {0}; +- __m256i v_sp_sums7351 = {0}; +- __m256i v_sp_sums5173 = {0}; +- __m256i v_sp_ri73515173ad = {0}; +- __m256i v_sp_ri73515173eh = {0}; +- __m256i v_sp_rl7351ad = {0}; +- __m256i v_sp_rl7351eh = {0}; +- __m256i v_sp_cols13 = {0}; +- __m256i v_sp_bq7153ad = {0}; +- __m256i v_sp_bq7153eh = {0}; +- __m256i v_sp_rk75ad = {0}; +- __m256i v_sp_rk75eh = {0}; +- __m256i v_sp_rl5173ad = {0}; +- __m256i v_sp_rl5173eh = {0}; +- __m256i v_sp_rk13ad = {0}; +- __m256i v_sp_rk13eh = {0}; +- __m256i v_final01ad = {0}; +- __m256i v_final01eh = {0}; +- __m256i v_final01 = {0}; +- __m256i v_final32ad = {0}; +- __m256i v_final32eh = {0}; +- __m256i v_final32 = {0}; +- __m256i v_final45ad = {0}; +- __m256i v_final45eh = {0}; +- __m256i v_final45 = {0}; +- __m256i v_final76ad = {0}; +- __m256i v_final76eh = {0}; +- __m256i v_final76 = {0}; +- __m256i v_fta0a1e0e1 = {0}; +- __m256i v_fta2a3e2e3 = {0}; +- __m256i v_fta4a5e4e5 = {0}; +- __m256i v_fta6a7e6e7 = {0}; +- __m256i v_fta0c0e0g0 = {0}; +- __m256i v_fta1c1e1g1 = {0}; +- __m256i v_fta4c4e4g4 = {0}; +- __m256i v_fta5c5e5g5 = {0}; +- __m256i v_fta0b0e0f0 = {0}; +- __m256i v_ftc0d0g0h0 = {0}; +- __m256i v_fta4b4e4f4 = {0}; +- __m256i v_ftc4d4g4h4 = {0}; +- __m256i v_finalae = {0}; +- __m256i v_finalbf = {0}; +- __m256i v_finalcg = {0}; +- __m256i v_finaldh = {0}; +- __m256i v_final0145 = {0}; +- __m256i v_final2367 = {0}; +- uint64_t v_final0 = 0; +- uint64_t v_final1 = 0; +- uint64_t v_final2 = 0; +- uint64_t v_final3 = 0; +- uint64_t v_final4 = 0; +- uint64_t v_final5 = 0; +- uint64_t v_final6 = 0; +- uint64_t v_final7 = 0; +- wuffs_base__slice_u8 v_remaining = {0}; +- +- if (8u > a_dst_stride) { +- return wuffs_base__make_empty_struct(); +- } +- v_k_0000 = _mm256_set_epi16((int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u)); +- v_k_8080 = _mm256_set_epi16((int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u)); +- v_k_0000_0002 = _mm256_set_epi16((int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u)); +- v_k_0001_FFFF = _mm256_set_epi16((int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u)); +- v_k_0400_0000 = _mm256_set_epi16((int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u)); +- v_k_29CF_1151_D630_1151 = _mm256_set_epi16((int16_t)(4433u), (int16_t)(54832u), (int16_t)(4433u), (int16_t)(54832u), (int16_t)(4433u), (int16_t)(54832u), (int16_t)(4433u), (int16_t)(54832u), (int16_t)(4433u), (int16_t)(10703u), (int16_t)(4433u), (int16_t)(10703u), (int16_t)(4433u), (int16_t)(10703u), (int16_t)(4433u), (int16_t)(10703u)); +- v_k_E333_133E_ADFD_1051 = _mm256_set_epi16((int16_t)(4177u), (int16_t)(44541u), (int16_t)(4177u), (int16_t)(44541u), (int16_t)(4177u), (int16_t)(44541u), (int16_t)(4177u), (int16_t)(44541u), (int16_t)(4926u), (int16_t)(58163u), (int16_t)(4926u), (int16_t)(58163u), (int16_t)(4926u), (int16_t)(58163u), (int16_t)(4926u), (int16_t)(58163u)); +- v_k_E6DC_25A1_1925_25A1 = _mm256_set_epi16((int16_t)(9633u), (int16_t)(6437u), (int16_t)(9633u), (int16_t)(6437u), (int16_t)(9633u), (int16_t)(6437u), (int16_t)(9633u), (int16_t)(6437u), (int16_t)(9633u), (int16_t)(59100u), (int16_t)(9633u), (int16_t)(59100u), (int16_t)(9633u), (int16_t)(59100u), (int16_t)(9633u), (int16_t)(59100u)); +- v_k_ECC1_E333_EFB0_ADFD = _mm256_set_epi16((int16_t)(44541u), (int16_t)(61360u), (int16_t)(44541u), (int16_t)(61360u), (int16_t)(44541u), (int16_t)(61360u), (int16_t)(44541u), (int16_t)(61360u), (int16_t)(58163u), (int16_t)(60609u), (int16_t)(58163u), (int16_t)(60609u), (int16_t)(58163u), (int16_t)(60609u), (int16_t)(58163u), (int16_t)(60609u)); +- do { +- if (0u == (wuffs_base__peek_u64le__no_bounds_check((const uint8_t*)(const void*)(self->private_data.f_mcu_blocks[0u] + 8u)) | wuffs_base__peek_u64le__no_bounds_check((const uint8_t*)(const void*)(self->private_data.f_mcu_blocks[0u] + 16u)))) { +- v_az_coeffs = _mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 8u)), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 16u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 24u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 32u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 40u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 48u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 56u))); +- if (0u == ((uint64_t)(_mm_cvtsi128_si64(_mm_packs_epi16(v_az_coeffs, v_az_coeffs))))) { +- v_rows01 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 0u)); +- v_quants01 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 0u)); +- v_rows01 = _mm256_mullo_epi16(v_rows01, v_quants01); +- v_az_ah00 = _mm256_slli_epi16(v_rows01, (int32_t)(2u)); +- v_az_ad00 = _mm256_unpacklo_epi16(v_az_ah00, v_az_ah00); +- v_az_eh00 = _mm256_unpackhi_epi16(v_az_ah00, v_az_ah00); +- v_az_adeh = _mm256_inserti128_si256(v_az_ad00, _mm256_castsi256_si128(v_az_eh00), (int32_t)(1u)); +- v_intermediateae = _mm256_shuffle_epi32(v_az_adeh, (int32_t)(0u)); +- v_intermediatebf = _mm256_shuffle_epi32(v_az_adeh, (int32_t)(85u)); +- v_intermediatecg = _mm256_shuffle_epi32(v_az_adeh, (int32_t)(170u)); +- v_intermediatedh = _mm256_shuffle_epi32(v_az_adeh, (int32_t)(255u)); +- break; +- } +- } +- v_rows01 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 0u)); +- v_rows23 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 16u)); +- v_rows45 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 32u)); +- v_rows67 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 48u)); +- v_quants01 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 0u)); +- v_quants23 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 16u)); +- v_quants45 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 32u)); +- v_quants67 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 48u)); +- v_rows01 = _mm256_mullo_epi16(v_rows01, v_quants01); +- v_rows23 = _mm256_mullo_epi16(v_rows23, v_quants23); +- v_rows45 = _mm256_mullo_epi16(v_rows45, v_quants45); +- v_rows67 = _mm256_mullo_epi16(v_rows67, v_quants67); +- v_rows04 = _mm256_permute2x128_si256(v_rows01, v_rows45, (int32_t)(32u)); +- v_rows31 = _mm256_permute2x128_si256(v_rows23, v_rows01, (int32_t)(49u)); +- v_rows26 = _mm256_permute2x128_si256(v_rows23, v_rows67, (int32_t)(32u)); +- v_rows75 = _mm256_permute2x128_si256(v_rows67, v_rows45, (int32_t)(49u)); +- v_fp_rows62 = _mm256_permute2x128_si256(v_rows26, v_rows26, (int32_t)(1u)); +- v_fp_bq2662ad = _mm256_unpacklo_epi16(v_rows26, v_fp_rows62); +- v_fp_bq2662eh = _mm256_unpackhi_epi16(v_rows26, v_fp_rows62); +- v_fp_cb26ad = _mm256_madd_epi16(v_fp_bq2662ad, v_k_29CF_1151_D630_1151); +- v_fp_cb26eh = _mm256_madd_epi16(v_fp_bq2662eh, v_k_29CF_1151_D630_1151); +- v_fp_rows40pos = _mm256_permute2x128_si256(v_rows04, v_rows04, (int32_t)(1u)); +- v_fp_rows04neg = _mm256_sign_epi16(v_rows04, v_k_0001_FFFF); +- v_fp_rows0pm4 = _mm256_add_epi16(v_fp_rows40pos, v_fp_rows04neg); +- v_fp_ccpmad = _mm256_srai_epi32(_mm256_unpacklo_epi16(v_k_0000, v_fp_rows0pm4), (int32_t)(3u)); +- v_fp_ccpmeh = _mm256_srai_epi32(_mm256_unpackhi_epi16(v_k_0000, v_fp_rows0pm4), (int32_t)(3u)); +- v_fp_cd01ad = _mm256_add_epi32(v_fp_ccpmad, v_fp_cb26ad); +- v_fp_cd01eh = _mm256_add_epi32(v_fp_ccpmeh, v_fp_cb26eh); +- v_fp_cd32ad = _mm256_sub_epi32(v_fp_ccpmad, v_fp_cb26ad); +- v_fp_cd32eh = _mm256_sub_epi32(v_fp_ccpmeh, v_fp_cb26eh); +- v_fp_sums7351 = _mm256_add_epi16(v_rows75, v_rows31); +- v_fp_sums5173 = _mm256_permute2x128_si256(v_fp_sums7351, v_fp_sums7351, (int32_t)(1u)); +- v_fp_ci73515173ad = _mm256_unpacklo_epi16(v_fp_sums7351, v_fp_sums5173); +- v_fp_ci73515173eh = _mm256_unpackhi_epi16(v_fp_sums7351, v_fp_sums5173); +- v_fp_cl7351ad = _mm256_madd_epi16(v_fp_ci73515173ad, v_k_E6DC_25A1_1925_25A1); +- v_fp_cl7351eh = _mm256_madd_epi16(v_fp_ci73515173eh, v_k_E6DC_25A1_1925_25A1); +- v_fp_rows13 = _mm256_permute2x128_si256(v_rows31, v_rows31, (int32_t)(1u)); +- v_fp_bq7153ad = _mm256_unpacklo_epi16(v_rows75, v_fp_rows13); +- v_fp_bq7153eh = _mm256_unpackhi_epi16(v_rows75, v_fp_rows13); +- v_fp_ck75ad = _mm256_add_epi32(_mm256_madd_epi16(v_fp_bq7153ad, v_k_ECC1_E333_EFB0_ADFD), v_fp_cl7351ad); +- v_fp_ck75eh = _mm256_add_epi32(_mm256_madd_epi16(v_fp_bq7153eh, v_k_ECC1_E333_EFB0_ADFD), v_fp_cl7351eh); +- v_fp_cl5173ad = _mm256_permute2x128_si256(v_fp_cl7351ad, v_fp_cl7351ad, (int32_t)(1u)); +- v_fp_cl5173eh = _mm256_permute2x128_si256(v_fp_cl7351eh, v_fp_cl7351eh, (int32_t)(1u)); +- v_fp_ck13ad = _mm256_add_epi32(v_fp_cl5173ad, _mm256_madd_epi16(v_fp_bq7153ad, v_k_E333_133E_ADFD_1051)); +- v_fp_ck13eh = _mm256_add_epi32(v_fp_cl5173eh, _mm256_madd_epi16(v_fp_bq7153eh, v_k_E333_133E_ADFD_1051)); +- v_intermediate01ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_fp_cd01ad, v_fp_ck13ad), v_k_0400_0000), (int32_t)(11u)); +- v_intermediate01eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_fp_cd01eh, v_fp_ck13eh), v_k_0400_0000), (int32_t)(11u)); +- v_intermediate01 = _mm256_packs_epi32(v_intermediate01ad, v_intermediate01eh); +- v_intermediate32ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_fp_cd32ad, v_fp_ck75ad), v_k_0400_0000), (int32_t)(11u)); +- v_intermediate32eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_fp_cd32eh, v_fp_ck75eh), v_k_0400_0000), (int32_t)(11u)); +- v_intermediate32 = _mm256_packs_epi32(v_intermediate32ad, v_intermediate32eh); +- v_intermediate45ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_fp_cd32ad, v_fp_ck75ad), v_k_0400_0000), (int32_t)(11u)); +- v_intermediate45eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_fp_cd32eh, v_fp_ck75eh), v_k_0400_0000), (int32_t)(11u)); +- v_intermediate45 = _mm256_packs_epi32(v_intermediate45ad, v_intermediate45eh); +- v_intermediate76ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_fp_cd01ad, v_fp_ck13ad), v_k_0400_0000), (int32_t)(11u)); +- v_intermediate76eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_fp_cd01eh, v_fp_ck13eh), v_k_0400_0000), (int32_t)(11u)); +- v_intermediate76 = _mm256_packs_epi32(v_intermediate76ad, v_intermediate76eh); +- v_ita0a1e0e1 = _mm256_permute4x64_epi64(v_intermediate01, (int32_t)(216u)); +- v_ita2a3e2e3 = _mm256_permute4x64_epi64(v_intermediate32, (int32_t)(114u)); +- v_ita4a5e4e5 = _mm256_permute4x64_epi64(v_intermediate45, (int32_t)(216u)); +- v_ita6a7e6e7 = _mm256_permute4x64_epi64(v_intermediate76, (int32_t)(114u)); +- v_ita0c0e0g0 = _mm256_unpacklo_epi16(v_ita0a1e0e1, v_ita2a3e2e3); +- v_ita1c1e1g1 = _mm256_unpackhi_epi16(v_ita0a1e0e1, v_ita2a3e2e3); +- v_ita4c4e4g4 = _mm256_unpacklo_epi16(v_ita4a5e4e5, v_ita6a7e6e7); +- v_ita5c5e5g5 = _mm256_unpackhi_epi16(v_ita4a5e4e5, v_ita6a7e6e7); +- v_ita0b0e0f0 = _mm256_unpacklo_epi16(v_ita0c0e0g0, v_ita1c1e1g1); +- v_itc0d0g0h0 = _mm256_unpackhi_epi16(v_ita0c0e0g0, v_ita1c1e1g1); +- v_ita4b4e4f4 = _mm256_unpacklo_epi16(v_ita4c4e4g4, v_ita5c5e5g5); +- v_itc4d4g4h4 = _mm256_unpackhi_epi16(v_ita4c4e4g4, v_ita5c5e5g5); +- v_intermediateae = _mm256_unpacklo_epi64(v_ita0b0e0f0, v_ita4b4e4f4); +- v_intermediatebf = _mm256_unpackhi_epi64(v_ita0b0e0f0, v_ita4b4e4f4); +- v_intermediatecg = _mm256_unpacklo_epi64(v_itc0d0g0h0, v_itc4d4g4h4); +- v_intermediatedh = _mm256_unpackhi_epi64(v_itc0d0g0h0, v_itc4d4g4h4); +- } while (0); +- v_intermediatedb = _mm256_permute2x128_si256(v_intermediatedh, v_intermediatebf, (int32_t)(32u)); +- v_intermediatehf = _mm256_permute2x128_si256(v_intermediatedh, v_intermediatebf, (int32_t)(49u)); +- v_sp_cols62 = _mm256_permute2x128_si256(v_intermediatecg, v_intermediatecg, (int32_t)(1u)); +- v_sp_bq2662ad = _mm256_unpacklo_epi16(v_intermediatecg, v_sp_cols62); +- v_sp_bq2662eh = _mm256_unpackhi_epi16(v_intermediatecg, v_sp_cols62); +- v_sp_rb26ad = _mm256_madd_epi16(v_sp_bq2662ad, v_k_29CF_1151_D630_1151); +- v_sp_rb26eh = _mm256_madd_epi16(v_sp_bq2662eh, v_k_29CF_1151_D630_1151); +- v_sp_cols40pos = _mm256_permute2x128_si256(v_intermediateae, v_intermediateae, (int32_t)(1u)); +- v_sp_cols04neg = _mm256_sign_epi16(v_intermediateae, v_k_0001_FFFF); +- v_sp_cols0pm4 = _mm256_add_epi16(v_sp_cols40pos, v_sp_cols04neg); +- v_sp_rcpmad = _mm256_srai_epi32(_mm256_unpacklo_epi16(v_k_0000, v_sp_cols0pm4), (int32_t)(3u)); +- v_sp_rcpmeh = _mm256_srai_epi32(_mm256_unpackhi_epi16(v_k_0000, v_sp_cols0pm4), (int32_t)(3u)); +- v_sp_rd01ad = _mm256_add_epi32(v_sp_rcpmad, v_sp_rb26ad); +- v_sp_rd01eh = _mm256_add_epi32(v_sp_rcpmeh, v_sp_rb26eh); +- v_sp_rd32ad = _mm256_sub_epi32(v_sp_rcpmad, v_sp_rb26ad); +- v_sp_rd32eh = _mm256_sub_epi32(v_sp_rcpmeh, v_sp_rb26eh); +- v_sp_sums7351 = _mm256_add_epi16(v_intermediatehf, v_intermediatedb); +- v_sp_sums5173 = _mm256_permute2x128_si256(v_sp_sums7351, v_sp_sums7351, (int32_t)(1u)); +- v_sp_ri73515173ad = _mm256_unpacklo_epi16(v_sp_sums7351, v_sp_sums5173); +- v_sp_ri73515173eh = _mm256_unpackhi_epi16(v_sp_sums7351, v_sp_sums5173); +- v_sp_rl7351ad = _mm256_madd_epi16(v_sp_ri73515173ad, v_k_E6DC_25A1_1925_25A1); +- v_sp_rl7351eh = _mm256_madd_epi16(v_sp_ri73515173eh, v_k_E6DC_25A1_1925_25A1); +- v_sp_cols13 = _mm256_permute2x128_si256(v_intermediatedb, v_intermediatedb, (int32_t)(1u)); +- v_sp_bq7153ad = _mm256_unpacklo_epi16(v_intermediatehf, v_sp_cols13); +- v_sp_bq7153eh = _mm256_unpackhi_epi16(v_intermediatehf, v_sp_cols13); +- v_sp_rk75ad = _mm256_add_epi32(_mm256_madd_epi16(v_sp_bq7153ad, v_k_ECC1_E333_EFB0_ADFD), v_sp_rl7351ad); +- v_sp_rk75eh = _mm256_add_epi32(_mm256_madd_epi16(v_sp_bq7153eh, v_k_ECC1_E333_EFB0_ADFD), v_sp_rl7351eh); +- v_sp_rl5173ad = _mm256_permute2x128_si256(v_sp_rl7351ad, v_sp_rl7351ad, (int32_t)(1u)); +- v_sp_rl5173eh = _mm256_permute2x128_si256(v_sp_rl7351eh, v_sp_rl7351eh, (int32_t)(1u)); +- v_sp_rk13ad = _mm256_add_epi32(v_sp_rl5173ad, _mm256_madd_epi16(v_sp_bq7153ad, v_k_E333_133E_ADFD_1051)); +- v_sp_rk13eh = _mm256_add_epi32(v_sp_rl5173eh, _mm256_madd_epi16(v_sp_bq7153eh, v_k_E333_133E_ADFD_1051)); +- v_final01ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_sp_rd01ad, v_sp_rk13ad), v_k_0000_0002), (int32_t)(18u)); +- v_final01eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_sp_rd01eh, v_sp_rk13eh), v_k_0000_0002), (int32_t)(18u)); +- v_final01 = _mm256_packs_epi32(v_final01ad, v_final01eh); +- v_final32ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_sp_rd32ad, v_sp_rk75ad), v_k_0000_0002), (int32_t)(18u)); +- v_final32eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_sp_rd32eh, v_sp_rk75eh), v_k_0000_0002), (int32_t)(18u)); +- v_final32 = _mm256_packs_epi32(v_final32ad, v_final32eh); +- v_final45ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_sp_rd32ad, v_sp_rk75ad), v_k_0000_0002), (int32_t)(18u)); +- v_final45eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_sp_rd32eh, v_sp_rk75eh), v_k_0000_0002), (int32_t)(18u)); +- v_final45 = _mm256_packs_epi32(v_final45ad, v_final45eh); +- v_final76ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_sp_rd01ad, v_sp_rk13ad), v_k_0000_0002), (int32_t)(18u)); +- v_final76eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_sp_rd01eh, v_sp_rk13eh), v_k_0000_0002), (int32_t)(18u)); +- v_final76 = _mm256_packs_epi32(v_final76ad, v_final76eh); +- v_fta0a1e0e1 = _mm256_permute4x64_epi64(v_final01, (int32_t)(216u)); +- v_fta2a3e2e3 = _mm256_permute4x64_epi64(v_final32, (int32_t)(114u)); +- v_fta4a5e4e5 = _mm256_permute4x64_epi64(v_final45, (int32_t)(216u)); +- v_fta6a7e6e7 = _mm256_permute4x64_epi64(v_final76, (int32_t)(114u)); +- v_fta0c0e0g0 = _mm256_unpacklo_epi16(v_fta0a1e0e1, v_fta2a3e2e3); +- v_fta1c1e1g1 = _mm256_unpackhi_epi16(v_fta0a1e0e1, v_fta2a3e2e3); +- v_fta4c4e4g4 = _mm256_unpacklo_epi16(v_fta4a5e4e5, v_fta6a7e6e7); +- v_fta5c5e5g5 = _mm256_unpackhi_epi16(v_fta4a5e4e5, v_fta6a7e6e7); +- v_fta0b0e0f0 = _mm256_unpacklo_epi16(v_fta0c0e0g0, v_fta1c1e1g1); +- v_ftc0d0g0h0 = _mm256_unpackhi_epi16(v_fta0c0e0g0, v_fta1c1e1g1); +- v_fta4b4e4f4 = _mm256_unpacklo_epi16(v_fta4c4e4g4, v_fta5c5e5g5); +- v_ftc4d4g4h4 = _mm256_unpackhi_epi16(v_fta4c4e4g4, v_fta5c5e5g5); +- v_finalae = _mm256_unpacklo_epi64(v_fta0b0e0f0, v_fta4b4e4f4); +- v_finalbf = _mm256_unpackhi_epi64(v_fta0b0e0f0, v_fta4b4e4f4); +- v_finalcg = _mm256_unpacklo_epi64(v_ftc0d0g0h0, v_ftc4d4g4h4); +- v_finaldh = _mm256_unpackhi_epi64(v_ftc0d0g0h0, v_ftc4d4g4h4); +- v_final0145 = _mm256_add_epi8(_mm256_packs_epi16(v_finalae, v_finalbf), v_k_8080); +- v_final2367 = _mm256_add_epi8(_mm256_packs_epi16(v_finalcg, v_finaldh), v_k_8080); +- v_final0 = ((uint64_t)(_mm256_extract_epi64(v_final0145, (int32_t)(0u)))); +- v_final1 = ((uint64_t)(_mm256_extract_epi64(v_final0145, (int32_t)(1u)))); +- v_final2 = ((uint64_t)(_mm256_extract_epi64(v_final2367, (int32_t)(0u)))); +- v_final3 = ((uint64_t)(_mm256_extract_epi64(v_final2367, (int32_t)(1u)))); +- v_final4 = ((uint64_t)(_mm256_extract_epi64(v_final0145, (int32_t)(2u)))); +- v_final5 = ((uint64_t)(_mm256_extract_epi64(v_final0145, (int32_t)(3u)))); +- v_final6 = ((uint64_t)(_mm256_extract_epi64(v_final2367, (int32_t)(2u)))); +- v_final7 = ((uint64_t)(_mm256_extract_epi64(v_final2367, (int32_t)(3u)))); +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final0); +- a_dst_buffer = v_remaining; +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final1); +- a_dst_buffer = v_remaining; +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final2); +- a_dst_buffer = v_remaining; +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final3); +- a_dst_buffer = v_remaining; +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final4); +- a_dst_buffer = v_remaining; +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final5); +- a_dst_buffer = v_remaining; +- if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); +- wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final6); +- a_dst_buffer = v_remaining; +- if (8u > ((uint64_t)(a_dst_buffer.len))) { +- return wuffs_base__make_empty_struct(); +- } +- wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final7); +- return wuffs_base__make_empty_struct(); +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_64) +-// ‼ WUFFS MULTI-FILE SECTION -x86_avx2 +- +-// -------- func jpeg.decoder.get_quirk +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_jpeg__decoder__get_quirk( +- const wuffs_jpeg__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func jpeg.decoder.set_quirk +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_jpeg__decoder__set_quirk( +- wuffs_jpeg__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); +-} +- +-// -------- func jpeg.decoder.decode_image_config +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_jpeg__decoder__decode_image_config( +- wuffs_jpeg__decoder* self, +- wuffs_base__image_config* a_dst, ++static wuffs_base__status ++wuffs_gif__decoder__skip_blocks( ++ wuffs_gif__decoder* self, + wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint8_t v_block_size = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_image_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_skip_blocks; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_jpeg__decoder__do_decode_image_config(self, a_dst, a_src); +- v_status = t_0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_block_size = t_0; + } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__truncated_input); +- goto exit; ++ if (v_block_size == 0u) { ++ status = wuffs_base__make_status(NULL); ++ goto ok; + } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ self->private_data.s_skip_blocks.scratch = ((uint32_t)(v_block_size)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (self->private_data.s_skip_blocks.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_skip_blocks.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_skip_blocks.scratch; + } + + ok: +- self->private_impl.p_decode_image_config[0] = 0; ++ self->private_impl.p_skip_blocks = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ self->private_impl.p_skip_blocks = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } ++ + return status; + } + +-// -------- func jpeg.decoder.do_decode_image_config ++// -------- func gif.decoder.decode_ae + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__do_decode_image_config( +- wuffs_jpeg__decoder* self, +- wuffs_base__image_config* a_dst, ++wuffs_gif__decoder__decode_ae( ++ wuffs_gif__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint8_t v_marker = 0; +- uint32_t v_pixfmt = 0; ++ uint8_t v_c8 = 0; ++ uint8_t v_block_size = 0; ++ bool v_is_animexts = false; ++ bool v_is_netscape = false; ++ bool v_is_iccp = false; ++ bool v_is_xmp = false; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -42362,253 +42476,191 @@ wuffs_jpeg__decoder__do_decode_image_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_ae; + if (coro_susp_point) { +- v_marker = self->private_data.s_do_decode_image_config[0].v_marker; ++ v_block_size = self->private_data.s_decode_ae.v_block_size; ++ v_is_animexts = self->private_data.s_decode_ae.v_is_animexts; ++ v_is_netscape = self->private_data.s_decode_ae.v_is_netscape; ++ v_is_iccp = self->private_data.s_decode_ae.v_is_iccp; ++ v_is_xmp = self->private_data.s_decode_ae.v_is_xmp; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ do { ++ if (self->private_impl.f_metadata_fourcc != 0u) { ++ status = wuffs_base__make_status(wuffs_base__note__metadata_reported); ++ goto ok; + } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if (v_c != 255u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_header); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_block_size = t_0; + } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; +- } +- if (v_c != 216u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_header); +- goto exit; +- } +- while (true) { +- while (true) { ++ if (v_block_size == 0u) { ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ if (v_block_size != 11u) { ++ self->private_data.s_decode_ae.scratch = ((uint32_t)(v_block_size)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (self->private_data.s_decode_ae.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_decode_ae.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_decode_ae.scratch; ++ break; ++ } ++ v_is_animexts = true; ++ v_is_netscape = true; ++ v_is_iccp = true; ++ v_is_xmp = true; ++ v_block_size = 0u; ++ while (v_block_size < 11u) { + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ v_is_animexts = (v_is_animexts && (v_c8 == WUFFS_GIF__ANIMEXTS1DOT0[v_block_size])); ++ v_is_netscape = (v_is_netscape && (v_c8 == WUFFS_GIF__NETSCAPE2DOT0[v_block_size])); ++ v_is_iccp = (v_is_iccp && (v_c8 == WUFFS_GIF__ICCRGBG1012[v_block_size])); ++ v_is_xmp = (v_is_xmp && (v_c8 == WUFFS_GIF__XMPDATAXMP[v_block_size])); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_block_size += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } ++ if (v_is_animexts || v_is_netscape) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } + uint8_t t_2 = *iop_a_src++; +- v_c = t_2; ++ v_block_size = t_2; + } +- if (v_c == 255u) { ++ if (v_block_size != 3u) { ++ self->private_data.s_decode_ae.scratch = ((uint32_t)(v_block_size)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (self->private_data.s_decode_ae.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_decode_ae.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_decode_ae.scratch; + break; + } +- } +- while (true) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } + uint8_t t_3 = *iop_a_src++; +- v_c = t_3; ++ v_c8 = t_3; + } +- if (v_c != 255u) { +- v_marker = v_c; ++ if (v_c8 != 1u) { ++ self->private_data.s_decode_ae.scratch = 2u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (self->private_data.s_decode_ae.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_decode_ae.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_decode_ae.scratch; + break; + } +- } +- if (v_marker == 0u) { +- continue; +- } else if ((208u <= v_marker) && (v_marker <= 217u)) { +- if (v_marker <= 215u) { +- continue; +- } +- } else { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); + uint32_t t_4; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_4 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ t_4 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); + iop_a_src += 2; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ self->private_data.s_decode_ae.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; ++ uint64_t* scratch = &self->private_data.s_decode_ae.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; + if (num_bits_4 == 8) { +- t_4 = ((uint32_t)(*scratch >> 48)); ++ t_4 = ((uint32_t)(*scratch)); + break; + } + num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)); ++ *scratch |= ((uint64_t)(num_bits_4)) << 56; + } + } +- self->private_impl.f_payload_length = t_4; +- } +- if (self->private_impl.f_payload_length < 2u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_marker); +- goto exit; +- } +- self->private_impl.f_payload_length -= 2u; +- } +- if (v_marker < 192u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); +- goto exit; +- } else if (v_marker < 208u) { +- if (v_marker <= 194u) { +- if (self->private_impl.f_sof_marker != 0u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); +- goto exit; +- } +- self->private_impl.f_sof_marker = v_marker; +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- status = wuffs_jpeg__decoder__decode_sof(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- break; +- } else if (v_marker == 195u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_lossless_coding); +- goto exit; +- } else if (v_marker == 196u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } else if ((197u <= v_marker) && (v_marker <= 199u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_hierarchical_coding); +- goto exit; +- } else if (v_marker == 200u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_arithmetic_coding); +- goto exit; +- } +- } else if (v_marker < 224u) { +- if (v_marker < 218u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_marker); +- goto exit; +- } else if (v_marker == 218u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } else if (v_marker == 219u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- status = wuffs_jpeg__decoder__decode_dqt(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- continue; +- } else if (v_marker == 221u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- status = wuffs_jpeg__decoder__decode_dri(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- continue; +- } else { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); +- goto exit; +- } +- } else if (v_marker < 240u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- status = wuffs_jpeg__decoder__decode_appn(self, a_src, v_marker); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; ++ self->private_impl.f_num_animation_loops_value = t_4; + } +- continue; +- } else { +- if (v_marker == 254u) { +- } else { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); +- goto exit; ++ self->private_impl.f_seen_num_animation_loops_value = true; ++ if ((0u < self->private_impl.f_num_animation_loops_value) && (self->private_impl.f_num_animation_loops_value <= 65535u)) { ++ self->private_impl.f_num_animation_loops_value += 1u; + } ++ } else if (self->private_impl.f_call_sequence >= 32u) { ++ } else if (v_is_iccp && self->private_impl.f_report_metadata_iccp) { ++ self->private_impl.f_metadata_fourcc = 1229144912u; ++ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ self->private_impl.f_call_sequence = 16u; ++ status = wuffs_base__make_status(wuffs_base__note__metadata_reported); ++ goto ok; ++ } else if (v_is_xmp && self->private_impl.f_report_metadata_xmp) { ++ self->private_impl.f_metadata_fourcc = 1481461792u; ++ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ self->private_impl.f_call_sequence = 16u; ++ status = wuffs_base__make_status(wuffs_base__note__metadata_reported); ++ goto ok; + } +- self->private_data.s_do_decode_image_config[0].scratch = self->private_impl.f_payload_length; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); +- if (self->private_data.s_do_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_image_config[0].scratch; +- self->private_impl.f_payload_length = 0u; ++ } while (0); ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- self->private_impl.choosy_decode_idct = ( +-#if defined(WUFFS_BASE__CPU_ARCH__X86_64) +- wuffs_base__cpu_arch__have_x86_avx2() ? &wuffs_jpeg__decoder__decode_idct_x86_avx2 : +-#endif +- self->private_impl.choosy_decode_idct); +- self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- if (a_dst != NULL) { +- v_pixfmt = 536870920u; +- if (self->private_impl.f_num_components > 1u) { +- v_pixfmt = 2415954056u; +- } +- wuffs_base__image_config__set( +- a_dst, +- v_pixfmt, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height, +- self->private_impl.f_frame_config_io_position, +- true); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ status = wuffs_gif__decoder__skip_blocks(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; + } +- self->private_impl.f_call_sequence = 32u; + +- goto ok; + ok: +- self->private_impl.p_do_decode_image_config[0] = 0; ++ self->private_impl.p_decode_ae = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_decode_image_config[0].v_marker = v_marker; ++ self->private_impl.p_decode_ae = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_ae.v_block_size = v_block_size; ++ self->private_data.s_decode_ae.v_is_animexts = v_is_animexts; ++ self->private_data.s_decode_ae.v_is_netscape = v_is_netscape; ++ self->private_data.s_decode_ae.v_is_iccp = v_is_iccp; ++ self->private_data.s_decode_ae.v_is_xmp = v_is_xmp; + + goto exit; + exit: +@@ -42619,18 +42671,18 @@ wuffs_jpeg__decoder__do_decode_image_config( + return status; + } + +-// -------- func jpeg.decoder.decode_dqt ++// -------- func gif.decoder.decode_gc + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__decode_dqt( +- wuffs_jpeg__decoder* self, ++wuffs_gif__decoder__decode_gc( ++ wuffs_gif__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint8_t v_q = 0; +- uint32_t v_i = 0; ++ uint8_t v_c8 = 0; ++ uint8_t v_flags = 0; ++ uint16_t v_gc_duration_centiseconds = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -42643,73 +42695,103 @@ wuffs_jpeg__decoder__decode_dqt( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_dqt[0]; +- if (coro_susp_point) { +- v_q = self->private_data.s_decode_dqt[0].v_q; +- v_i = self->private_data.s_decode_dqt[0].v_i; +- } ++ uint32_t coro_susp_point = self->private_impl.p_decode_gc; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- while (self->private_impl.f_payload_length > 0u) { +- self->private_impl.f_payload_length -= 1u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if ((v_c & 15u) > 3u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dqt_marker); +- goto exit; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- v_q = (v_c & 15u); +- if ((v_c >> 4u) == 1u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_precision); +- goto exit; +- } else if (((v_c >> 4u) > 1u) || (self->private_impl.f_payload_length < 64u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dqt_marker); +- goto exit; ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (v_c8 != 4u) { ++ status = wuffs_base__make_status(wuffs_gif__error__bad_graphic_control); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- self->private_impl.f_payload_length -= 64u; +- v_i = 0u; +- while (v_i < 64u) { +- v_i += 1u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ uint8_t t_1 = *iop_a_src++; ++ v_flags = t_1; ++ } ++ self->private_impl.f_gc_has_transparent_index = (((uint8_t)(v_flags & 1u)) != 0u); ++ v_flags = ((uint8_t)(((uint8_t)(v_flags >> 2u)) & 7u)); ++ if (v_flags == 2u) { ++ self->private_impl.f_gc_disposal = 1u; ++ } else if ((v_flags == 3u) || (v_flags == 4u)) { ++ self->private_impl.f_gc_disposal = 2u; ++ } else { ++ self->private_impl.f_gc_disposal = 0u; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint16_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_gc.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint16_t t_1 = *iop_a_src++; +- self->private_impl.f_quant_tables[v_q][WUFFS_JPEG__UNZIG[v_i]] = t_1; ++ uint64_t* scratch = &self->private_data.s_decode_gc.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ if (num_bits_2 == 8) { ++ t_2 = ((uint16_t)(*scratch)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)) << 56; + } + } +- self->private_impl.f_seen_dqt[v_q] = true; +- if (self->private_impl.f_sof_marker == 0u) { +- v_i = 0u; +- while (v_i < 64u) { +- self->private_impl.f_saved_quant_tables[v_q][v_i] = self->private_impl.f_quant_tables[v_q][v_i]; +- v_i += 1u; +- } +- self->private_impl.f_saved_seen_dqt[v_q] = true; ++ v_gc_duration_centiseconds = t_2; ++ } ++ self->private_impl.f_gc_duration = (((uint64_t)(v_gc_duration_centiseconds)) * 7056000u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ self->private_impl.f_gc_transparent_index = t_3; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; ++ } ++ if (v_c8 != 0u) { ++ status = wuffs_base__make_status(wuffs_gif__error__bad_graphic_control); ++ goto exit; + } + + goto ok; + ok: +- self->private_impl.p_decode_dqt[0] = 0; ++ self->private_impl.p_decode_gc = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_dqt[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_dqt[0].v_q = v_q; +- self->private_data.s_decode_dqt[0].v_i = v_i; ++ self->private_impl.p_decode_gc = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +@@ -42720,12 +42802,12 @@ wuffs_jpeg__decoder__decode_dqt( + return status; + } + +-// -------- func jpeg.decoder.decode_dri ++// -------- func gif.decoder.decode_id_part0 + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__decode_dri( +- wuffs_jpeg__decoder* self, ++wuffs_gif__decoder__decode_id_part0( ++ wuffs_gif__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +@@ -42740,57 +42822,144 @@ wuffs_jpeg__decoder__decode_dri( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_dri[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_id_part0; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_payload_length != 2u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dri_marker); +- goto exit; +- } +- self->private_impl.f_payload_length = 0u; + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint16_t t_0; ++ uint32_t t_0; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_0 = wuffs_base__peek_u16be__no_bounds_check(iop_a_src); ++ t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); + iop_a_src += 2; + } else { +- self->private_data.s_decode_dri[0].scratch = 0; ++ self->private_data.s_decode_id_part0.scratch = 0; + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_dri[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; ++ uint64_t* scratch = &self->private_data.s_decode_id_part0.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; + if (num_bits_0 == 8) { +- t_0 = ((uint16_t)(*scratch >> 48)); ++ t_0 = ((uint32_t)(*scratch)); + break; + } + num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; + } + } +- self->private_impl.f_restart_interval = t_0; ++ self->private_impl.f_frame_rect_x0 = t_0; + } +- if (self->private_impl.f_sof_marker == 0u) { +- self->private_impl.f_saved_restart_interval = self->private_impl.f_restart_interval; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_id_part0.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_id_part0.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 8) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ self->private_impl.f_frame_rect_y0 = t_1; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_2 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_id_part0.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_id_part0.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ if (num_bits_2 == 8) { ++ t_2 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)) << 56; ++ } ++ } ++ self->private_impl.f_frame_rect_x1 = t_2; ++ } ++ self->private_impl.f_frame_rect_x1 += self->private_impl.f_frame_rect_x0; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_3 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_id_part0.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_id_part0.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; ++ if (num_bits_3 == 8) { ++ t_3 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ } ++ } ++ self->private_impl.f_frame_rect_y1 = t_3; ++ } ++ self->private_impl.f_frame_rect_y1 += self->private_impl.f_frame_rect_y0; ++ self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0; ++ self->private_impl.f_dst_y = self->private_impl.f_frame_rect_y0; ++ if ((self->private_impl.f_num_decoded_frame_configs_value == 0u) && ! self->private_impl.f_quirks[4u]) { ++ self->private_impl.f_width = wuffs_base__u32__max(self->private_impl.f_width, self->private_impl.f_frame_rect_x1); ++ self->private_impl.f_height = wuffs_base__u32__max(self->private_impl.f_height, self->private_impl.f_frame_rect_y1); + } + + goto ok; + ok: +- self->private_impl.p_decode_dri[0] = 0; ++ self->private_impl.p_decode_id_part0 = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_dri[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_id_part0 = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +@@ -42801,18 +42970,24 @@ wuffs_jpeg__decoder__decode_dri( + return status; + } + +-// -------- func jpeg.decoder.decode_appn ++// -------- func gif.decoder.decode_id_part1 + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__decode_appn( +- wuffs_jpeg__decoder* self, ++wuffs_gif__decoder__decode_id_part1( ++ wuffs_gif__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, + wuffs_base__io_buffer* a_src, +- uint8_t a_marker) { ++ wuffs_base__pixel_blend a_blend) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c8 = 0; +- uint32_t v_c32 = 0; ++ uint8_t v_flags = 0; ++ uint8_t v_which_palette = 0; ++ uint32_t v_num_palette_entries = 0; ++ uint32_t v_i = 0; ++ uint32_t v_argb = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint8_t v_lw = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -42825,184 +43000,136 @@ wuffs_jpeg__decoder__decode_appn( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_appn[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_id_part1; ++ if (coro_susp_point) { ++ v_which_palette = self->private_data.s_decode_id_part1.v_which_palette; ++ v_num_palette_entries = self->private_data.s_decode_id_part1.v_num_palette_entries; ++ v_i = self->private_data.s_decode_id_part1.v_i; ++ } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- do { +- if (a_marker == 224u) { +- if (self->private_impl.f_payload_length >= 5u) { +- self->private_impl.f_payload_length -= 5u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_appn[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_appn[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; +- if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)) << 56; +- } +- } +- v_c32 = t_0; +- } +- if (v_c32 != 1179207242u) { +- self->private_impl.f_payload_length = (65535u & (self->private_impl.f_payload_length + 1u)); +- break; +- } +- { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_flags = t_0; ++ } ++ if (((uint8_t)(v_flags & 64u)) != 0u) { ++ self->private_impl.f_interlace = 4u; ++ } else { ++ self->private_impl.f_interlace = 0u; ++ } ++ v_which_palette = 1u; ++ if (((uint8_t)(v_flags & 128u)) != 0u) { ++ v_num_palette_entries = (((uint32_t)(1u)) << ((uint8_t)(1u + ((uint8_t)(v_flags & 7u))))); ++ v_i = 0u; ++ while (v_i < v_num_palette_entries) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { ++ t_1 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src))); ++ iop_a_src += 3; ++ } else { ++ self->private_data.s_decode_id_part1.scratch = 0; + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- v_c8 = t_1; +- } +- self->private_impl.f_is_jfif = (v_c8 == 0u); +- } +- } else if (a_marker == 238u) { +- if (self->private_impl.f_payload_length >= 12u) { +- self->private_impl.f_payload_length -= 12u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- uint32_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_appn[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_appn[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; +- if (num_bits_2 == 24) { +- t_2 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)) << 56; +- } +- } +- v_c32 = t_2; +- } +- if (v_c32 != 1651467329u) { +- self->private_impl.f_payload_length = (65535u & (self->private_impl.f_payload_length + 8u)); +- break; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- uint32_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_3 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_appn[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_appn[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; +- if (num_bits_3 == 24) { +- t_3 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- } +- v_c32 = t_3; +- } +- if ((255u & v_c32) != 101u) { +- self->private_impl.f_payload_length = (65535u & (self->private_impl.f_payload_length + 4u)); +- break; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- uint32_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_appn[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_appn[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; +- if (num_bits_4 == 24) { +- t_4 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)) << 56; ++ uint64_t* scratch = &self->private_data.s_decode_id_part1.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); ++ if (num_bits_1 == 16) { ++ t_1 = ((uint32_t)(*scratch >> 40)); ++ break; + } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)); + } +- v_c32 = t_4; +- } +- if ((v_c32 >> 24u) == 0u) { +- self->private_impl.f_is_adobe = 1u; +- } else { +- self->private_impl.f_is_adobe = 2u; + } ++ v_argb = t_1; + } ++ v_argb |= 4278190080u; ++ self->private_data.f_palettes[1u][((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); ++ self->private_data.f_palettes[1u][((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); ++ self->private_data.f_palettes[1u][((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); ++ self->private_data.f_palettes[1u][((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); ++ v_i += 1u; + } +- } while (0); +- self->private_data.s_decode_appn[0].scratch = self->private_impl.f_payload_length; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- if (self->private_data.s_decode_appn[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_decode_appn[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ while (v_i < 256u) { ++ self->private_data.f_palettes[1u][((4u * v_i) + 0u)] = 0u; ++ self->private_data.f_palettes[1u][((4u * v_i) + 1u)] = 0u; ++ self->private_data.f_palettes[1u][((4u * v_i) + 2u)] = 0u; ++ self->private_data.f_palettes[1u][((4u * v_i) + 3u)] = 255u; ++ v_i += 1u; ++ } ++ } else if (self->private_impl.f_quirks[6u] && ! self->private_impl.f_has_global_palette) { ++ status = wuffs_base__make_status(wuffs_gif__error__bad_palette); ++ goto exit; ++ } else if (self->private_impl.f_gc_has_transparent_index) { ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_palettes[1u], 1024), wuffs_base__make_slice_u8(self->private_data.f_palettes[0u], 1024)); ++ } else { ++ v_which_palette = 0u; + } +- iop_a_src += self->private_data.s_decode_appn[0].scratch; +- self->private_impl.f_payload_length = 0u; ++ if (self->private_impl.f_gc_has_transparent_index) { ++ self->private_data.f_palettes[1u][((4u * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 0u)] = 0u; ++ self->private_data.f_palettes[1u][((4u * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 1u)] = 0u; ++ self->private_data.f_palettes[1u][((4u * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 2u)] = 0u; ++ self->private_data.f_palettes[1u][((4u * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 3u)] = 0u; ++ } ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), ++ wuffs_base__utility__make_pixel_format(2198077448u), ++ wuffs_base__make_slice_u8(self->private_data.f_palettes[v_which_palette], 1024), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ if (self->private_impl.f_ignored_but_affects_benchmarks) { ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_lw = t_2; ++ } ++ if (v_lw > 8u) { ++ status = wuffs_base__make_status(wuffs_gif__error__bad_literal_width); ++ goto exit; ++ } ++ self->private_impl.f_lzw_pending_literal_width_plus_one = ((uint32_t)(((uint8_t)(1u + v_lw)))); ++ self->private_impl.f_ignored_but_affects_benchmarks = true; + +- goto ok; + ok: +- self->private_impl.p_decode_appn[0] = 0; ++ self->private_impl.p_decode_id_part1 = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_appn[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_id_part1 = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_id_part1.v_which_palette = v_which_palette; ++ self->private_data.s_decode_id_part1.v_num_palette_entries = v_num_palette_entries; ++ self->private_data.s_decode_id_part1.v_i = v_i; + + goto exit; + exit: +@@ -43013,30 +43140,29 @@ wuffs_jpeg__decoder__decode_appn( + return status; + } + +-// -------- func jpeg.decoder.decode_sof ++// -------- func gif.decoder.decode_id_part2 + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__decode_sof( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src) { ++wuffs_gif__decoder__decode_id_part2( ++ wuffs_gif__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint8_t v_comp_h = 0; +- uint8_t v_comp_v = 0; +- uint32_t v_i = 0; +- uint32_t v_j = 0; +- bool v_has_h24 = false; +- bool v_has_h3 = false; +- bool v_has_v24 = false; +- bool v_has_v3 = false; +- uint32_t v_upper_bound = 0; +- uint64_t v_wh0 = 0; +- uint64_t v_wh1 = 0; +- uint64_t v_wh2 = 0; +- uint64_t v_wh3 = 0; +- uint64_t v_progressive = 0; ++ uint64_t v_block_size = 0; ++ bool v_need_block_size = false; ++ uint32_t v_n_copied = 0; ++ uint64_t v_n_compressed = 0; ++ wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_r = &u_r; ++ const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint64_t v_mark = 0; ++ wuffs_base__status v_copy_status = wuffs_base__make_status(NULL); + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -43049,269 +43175,185 @@ wuffs_jpeg__decoder__decode_sof( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_sof[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_id_part2; + if (coro_susp_point) { +- v_i = self->private_data.s_decode_sof[0].v_i; ++ v_block_size = self->private_data.s_decode_id_part2.v_block_size; ++ v_need_block_size = self->private_data.s_decode_id_part2.v_need_block_size; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_payload_length < 6u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); +- goto exit; +- } +- self->private_impl.f_payload_length -= 6u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if (v_c == 8u) { +- } else if (v_c == 12u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_precision_12_bits); +- goto exit; +- } else if (v_c == 16u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_precision_16_bits); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_precision); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_1 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_sof[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- while (true) { ++ wuffs_gif__decoder__lzw_init(self); ++ v_need_block_size = true; ++ label__outer__continue:; ++ while (true) { ++ if (v_need_block_size) { ++ v_need_block_size = false; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_sof[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); +- if (num_bits_1 == 8) { +- t_1 = ((uint32_t)(*scratch >> 48)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)); ++ uint64_t t_0 = *iop_a_src++; ++ v_block_size = t_0; + } + } +- self->private_impl.f_height = t_1; +- } +- if (self->private_impl.f_height == 0u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_implicit_height); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- uint32_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_2 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_sof[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_sof[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); +- if (num_bits_2 == 8) { +- t_2 = ((uint32_t)(*scratch >> 48)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)); +- } ++ if (v_block_size == 0u) { ++ break; + } +- self->private_impl.f_width = t_2; +- } +- if (self->private_impl.f_width == 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ while (((uint64_t)(io2_a_src - iop_a_src)) == 0u) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); + } +- uint8_t t_3 = *iop_a_src++; +- v_c = t_3; +- } +- if ((v_c == 0u) || (v_c > 4u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); +- goto exit; +- } else if (v_c == 2u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_color_model); +- goto exit; +- } +- self->private_impl.f_num_components = ((uint32_t)(v_c)); +- if (self->private_impl.f_payload_length != (3u * self->private_impl.f_num_components)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); +- goto exit; +- } +- self->private_impl.f_payload_length = 0u; +- v_i = 0u; +- while (v_i < self->private_impl.f_num_components) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_4 = *iop_a_src++; +- self->private_impl.f_components_c[v_i] = t_4; ++ if (self->private_impl.f_compressed_ri == self->private_impl.f_compressed_wi) { ++ self->private_impl.f_compressed_ri = 0u; ++ self->private_impl.f_compressed_wi = 0u; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ while (self->private_impl.f_compressed_wi <= 3841u) { ++ v_n_compressed = wuffs_base__u64__min(v_block_size, ((uint64_t)(io2_a_src - iop_a_src))); ++ if (v_n_compressed <= 0u) { ++ break; + } +- uint8_t t_5 = *iop_a_src++; +- v_c = t_5; +- } +- v_comp_h = (v_c >> 4u); +- v_comp_v = (v_c & 15u); +- if ((v_comp_h == 0u) || +- (v_comp_h > 4u) || +- (v_comp_v == 0u) || +- (v_comp_v > 4u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); +- goto exit; +- } +- self->private_impl.f_components_h[v_i] = v_comp_h; +- if (self->private_impl.f_max_incl_components_h < self->private_impl.f_components_h[v_i]) { +- self->private_impl.f_max_incl_components_h = self->private_impl.f_components_h[v_i]; +- } +- self->private_impl.f_components_v[v_i] = v_comp_v; +- if (self->private_impl.f_max_incl_components_v < self->private_impl.f_components_v[v_i]) { +- self->private_impl.f_max_incl_components_v = self->private_impl.f_components_v[v_i]; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ v_n_copied = wuffs_private_impl__io_reader__limited_copy_u32_to_slice( ++ &iop_a_src, io2_a_src,((uint32_t)(v_n_compressed)), wuffs_base__make_slice_u8_ij(self->private_data.f_compressed, self->private_impl.f_compressed_wi, 4096)); ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_compressed_wi, ((uint64_t)(v_n_copied))); ++ wuffs_private_impl__u64__sat_sub_indirect(&v_block_size, ((uint64_t)(v_n_copied))); ++ if (v_block_size > 0u) { ++ break; + } +- uint8_t t_6 = *iop_a_src++; +- v_c = t_6; +- } +- if (v_c >= 4u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); +- goto exit; ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ v_need_block_size = true; ++ break; ++ } ++ v_block_size = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))); ++ iop_a_src += 1u; + } +- self->private_impl.f_components_tq[v_i] = v_c; +- v_j = 0u; +- while (v_j < v_i) { +- if (self->private_impl.f_components_c[v_j] == self->private_impl.f_components_c[v_i]) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ while (true) { ++ if ((self->private_impl.f_compressed_ri > self->private_impl.f_compressed_wi) || (self->private_impl.f_compressed_wi > 4096u)) { ++ status = wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_i_o); + goto exit; + } +- v_j += 1u; +- } +- v_i += 1u; +- } +- if (self->private_impl.f_num_components == 1u) { +- self->private_impl.f_max_incl_components_h = 1u; +- self->private_impl.f_max_incl_components_v = 1u; +- self->private_impl.f_components_h[0u] = 1u; +- self->private_impl.f_components_v[0u] = 1u; +- } else { +- v_has_h24 = false; +- v_has_h3 = false; +- v_has_v24 = false; +- v_has_v3 = false; +- v_i = 0u; +- while (v_i < self->private_impl.f_num_components) { +- v_has_h24 = (v_has_h24 || (self->private_impl.f_components_h[v_i] == 2u) || (self->private_impl.f_components_h[v_i] == 4u)); +- v_has_h3 = (v_has_h3 || (self->private_impl.f_components_h[v_i] == 3u)); +- v_has_v24 = (v_has_v24 || (self->private_impl.f_components_v[v_i] == 2u) || (self->private_impl.f_components_v[v_i] == 4u)); +- v_has_v3 = (v_has_v3 || (self->private_impl.f_components_v[v_i] == 3u)); +- v_i += 1u; +- } +- if ((v_has_h24 && v_has_h3) || (v_has_v24 && v_has_v3)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_fractional_sampling); +- goto exit; +- } +- if (self->private_impl.f_num_components == 4u) { +- self->private_impl.f_is_rgb_or_cmyk = (self->private_impl.f_is_adobe < 2u); +- } else { +- if (self->private_impl.f_is_jfif) { +- self->private_impl.f_is_rgb_or_cmyk = false; +- } else if (self->private_impl.f_is_adobe > 0u) { +- self->private_impl.f_is_rgb_or_cmyk = (self->private_impl.f_is_adobe == 1u); +- } else { +- self->private_impl.f_is_rgb_or_cmyk = ((self->private_impl.f_components_c[0u] == 82u) && (self->private_impl.f_components_c[1u] == 71u) && (self->private_impl.f_components_c[2u] == 66u)); ++ { ++ wuffs_base__io_buffer* o_0_v_r = v_r; ++ const uint8_t* o_0_iop_v_r = iop_v_r; ++ const uint8_t* o_0_io0_v_r = io0_v_r; ++ const uint8_t* o_0_io1_v_r = io1_v_r; ++ const uint8_t* o_0_io2_v_r = io2_v_r; ++ v_r = wuffs_private_impl__io_reader__set( ++ &u_r, ++ &iop_v_r, ++ &io0_v_r, ++ &io1_v_r, ++ &io2_v_r, ++ wuffs_base__make_slice_u8_ij(self->private_data.f_compressed, ++ self->private_impl.f_compressed_ri, ++ self->private_impl.f_compressed_wi), ++ 0u); ++ v_mark = ((uint64_t)(iop_v_r - io0_v_r)); ++ u_r.meta.ri = ((size_t)(iop_v_r - u_r.data.ptr)); ++ wuffs_gif__decoder__lzw_read_from(self, v_r); ++ iop_v_r = u_r.data.ptr + u_r.meta.ri; ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_compressed_ri, wuffs_private_impl__io__count_since(v_mark, ((uint64_t)(iop_v_r - io0_v_r)))); ++ v_r = o_0_v_r; ++ iop_v_r = o_0_iop_v_r; ++ io0_v_r = o_0_io0_v_r; ++ io1_v_r = o_0_io1_v_r; ++ io2_v_r = o_0_io2_v_r; + } +- } +- } +- self->private_impl.f_width_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_width, 1u, self->private_impl.f_max_incl_components_h); +- self->private_impl.f_height_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_height, 1u, self->private_impl.f_max_incl_components_v); +- v_upper_bound = 65544u; +- self->private_impl.f_components_workbuf_widths[0u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_width_in_mcus * ((uint32_t)(self->private_impl.f_components_h[0u])))); +- self->private_impl.f_components_workbuf_widths[1u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_width_in_mcus * ((uint32_t)(self->private_impl.f_components_h[1u])))); +- self->private_impl.f_components_workbuf_widths[2u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_width_in_mcus * ((uint32_t)(self->private_impl.f_components_h[2u])))); +- self->private_impl.f_components_workbuf_widths[3u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_width_in_mcus * ((uint32_t)(self->private_impl.f_components_h[3u])))); +- self->private_impl.f_components_workbuf_heights[0u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_height_in_mcus * ((uint32_t)(self->private_impl.f_components_v[0u])))); +- self->private_impl.f_components_workbuf_heights[1u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_height_in_mcus * ((uint32_t)(self->private_impl.f_components_v[1u])))); +- self->private_impl.f_components_workbuf_heights[2u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_height_in_mcus * ((uint32_t)(self->private_impl.f_components_v[2u])))); +- self->private_impl.f_components_workbuf_heights[3u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_height_in_mcus * ((uint32_t)(self->private_impl.f_components_v[3u])))); +- v_wh0 = (((uint64_t)(self->private_impl.f_components_workbuf_widths[0u])) * ((uint64_t)(self->private_impl.f_components_workbuf_heights[0u]))); +- v_wh1 = (((uint64_t)(self->private_impl.f_components_workbuf_widths[1u])) * ((uint64_t)(self->private_impl.f_components_workbuf_heights[1u]))); +- v_wh2 = (((uint64_t)(self->private_impl.f_components_workbuf_widths[2u])) * ((uint64_t)(self->private_impl.f_components_workbuf_heights[2u]))); +- v_wh3 = (((uint64_t)(self->private_impl.f_components_workbuf_widths[3u])) * ((uint64_t)(self->private_impl.f_components_workbuf_heights[3u]))); +- v_progressive = 0u; +- if (self->private_impl.f_sof_marker >= 194u) { +- v_progressive = 2u; +- v_i = 0u; +- while (v_i < 4u) { +- v_j = 0u; +- while (v_j < 10u) { +- self->private_impl.f_block_smoothing_lowest_scan_al[v_i][v_j] = 16u; +- v_j += 1u; ++ if (self->private_impl.f_lzw_output_ri < self->private_impl.f_lzw_output_wi) { ++ v_copy_status = wuffs_gif__decoder__copy_to_image_buffer(self, a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_lzw_output, ++ self->private_impl.f_lzw_output_ri, ++ self->private_impl.f_lzw_output_wi)); ++ if (wuffs_base__status__is_error(&v_copy_status)) { ++ status = v_copy_status; ++ goto exit; ++ } ++ self->private_impl.f_lzw_output_ri = 0u; ++ self->private_impl.f_lzw_output_wi = 0u; + } +- v_i += 1u; ++ if (self->private_impl.f_lzw_read_from_return_value == 0u) { ++ self->private_impl.f_ignored_but_affects_benchmarks = false; ++ if (v_need_block_size || (v_block_size > 0u)) { ++ self->private_data.s_decode_id_part2.scratch = ((uint32_t)(v_block_size)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (self->private_data.s_decode_id_part2.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_decode_id_part2.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_decode_id_part2.scratch; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_gif__decoder__skip_blocks(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ goto label__outer__break; ++ } else if (self->private_impl.f_lzw_read_from_return_value == 1u) { ++ continue; ++ } else if (self->private_impl.f_lzw_read_from_return_value == 2u) { ++ goto label__outer__continue; ++ } else if (self->private_impl.f_quirks[3u] && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1) && (self->private_impl.f_interlace == 0u)) { ++ if (v_need_block_size || (v_block_size > 0u)) { ++ self->private_data.s_decode_id_part2.scratch = ((uint32_t)(v_block_size)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (self->private_data.s_decode_id_part2.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_decode_id_part2.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_decode_id_part2.scratch; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ status = wuffs_gif__decoder__skip_blocks(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ goto label__outer__break; ++ } else if (self->private_impl.f_lzw_read_from_return_value == 3u) { ++ status = wuffs_base__make_status(wuffs_gif__error__truncated_input); ++ goto exit; ++ } else if (self->private_impl.f_lzw_read_from_return_value == 4u) { ++ status = wuffs_base__make_status(wuffs_gif__error__bad_lzw_code); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_i_o); ++ goto exit; + } + } +- self->private_impl.f_components_workbuf_offsets[0u] = 0u; +- self->private_impl.f_components_workbuf_offsets[1u] = (self->private_impl.f_components_workbuf_offsets[0u] + v_wh0); +- self->private_impl.f_components_workbuf_offsets[2u] = (self->private_impl.f_components_workbuf_offsets[1u] + v_wh1); +- self->private_impl.f_components_workbuf_offsets[3u] = (self->private_impl.f_components_workbuf_offsets[2u] + v_wh2); +- self->private_impl.f_components_workbuf_offsets[4u] = (self->private_impl.f_components_workbuf_offsets[3u] + v_wh3); +- self->private_impl.f_components_workbuf_offsets[5u] = (self->private_impl.f_components_workbuf_offsets[4u] + (v_wh0 * v_progressive)); +- self->private_impl.f_components_workbuf_offsets[6u] = (self->private_impl.f_components_workbuf_offsets[5u] + (v_wh1 * v_progressive)); +- self->private_impl.f_components_workbuf_offsets[7u] = (self->private_impl.f_components_workbuf_offsets[6u] + (v_wh2 * v_progressive)); +- self->private_impl.f_components_workbuf_offsets[8u] = (self->private_impl.f_components_workbuf_offsets[7u] + (v_wh3 * v_progressive)); ++ label__outer__break:; ++ self->private_impl.f_compressed_ri = 0u; ++ self->private_impl.f_compressed_wi = 0u; ++ if ((self->private_impl.f_dst_y < self->private_impl.f_frame_rect_y1) && (self->private_impl.f_frame_rect_x0 != self->private_impl.f_frame_rect_x1) && (self->private_impl.f_frame_rect_y0 != self->private_impl.f_frame_rect_y1)) { ++ status = wuffs_base__make_status(wuffs_base__error__not_enough_data); ++ goto exit; ++ } + +- goto ok; + ok: +- self->private_impl.p_decode_sof[0] = 0; ++ self->private_impl.p_decode_id_part2 = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_sof[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_sof[0].v_i = v_i; ++ self->private_impl.p_decode_id_part2 = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_id_part2.v_block_size = v_block_size; ++ self->private_data.s_decode_id_part2.v_need_block_size = v_need_block_size; + + goto exit; + exit: +@@ -43322,106 +43364,182 @@ wuffs_jpeg__decoder__decode_sof( + return status; + } + +-// -------- func jpeg.decoder.quantize_dimension ++// -------- func gif.decoder.copy_to_image_buffer + + WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__quantize_dimension( +- const wuffs_jpeg__decoder* self, +- uint32_t a_width, +- uint8_t a_h, +- uint8_t a_max_incl_h) { +- uint32_t v_ratio = 0; ++static wuffs_base__status ++wuffs_gif__decoder__copy_to_image_buffer( ++ wuffs_gif__decoder* self, ++ wuffs_base__pixel_buffer* a_pb, ++ wuffs_base__slice_u8 a_src) { ++ wuffs_base__slice_u8 v_dst = {0}; ++ wuffs_base__slice_u8 v_src = {0}; ++ uint64_t v_width_in_bytes = 0; ++ uint64_t v_n = 0; ++ uint64_t v_src_ri = 0; ++ wuffs_base__pixel_format v_pixfmt = {0}; ++ uint32_t v_bytes_per_pixel = 0; ++ uint32_t v_bits_per_pixel = 0; ++ wuffs_base__table_u8 v_tab = {0}; ++ uint64_t v_i = 0; ++ uint64_t v_j = 0; ++ uint32_t v_replicate_y0 = 0; ++ uint32_t v_replicate_y1 = 0; ++ wuffs_base__slice_u8 v_replicate_dst = {0}; ++ wuffs_base__slice_u8 v_replicate_src = {0}; + +- v_ratio = 0u; +- if (a_h > 0u) { +- v_ratio = ((uint32_t)((a_max_incl_h / a_h))); ++ v_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_pb); ++ v_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_pixfmt); ++ if ((v_bits_per_pixel & 7u) != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } +- if (v_ratio == 1u) { +- return ((a_width + 7u) / 8u); +- } else if (v_ratio == 2u) { +- return ((a_width + 15u) / 16u); +- } else if (v_ratio == 3u) { +- return ((a_width + 23u) / 24u); ++ v_bytes_per_pixel = (v_bits_per_pixel >> 3u); ++ v_width_in_bytes = ((uint64_t)((self->private_impl.f_width * v_bytes_per_pixel))); ++ v_tab = wuffs_base__pixel_buffer__plane(a_pb, 0u); ++ while (v_src_ri < ((uint64_t)(a_src.len))) { ++ v_src = wuffs_base__slice_u8__subslice_i(a_src, v_src_ri); ++ if (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1) { ++ if (self->private_impl.f_quirks[3u]) { ++ return wuffs_base__make_status(NULL); ++ } ++ return wuffs_base__make_status(wuffs_base__error__too_much_data); ++ } ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (self->private_impl.f_dst_y >= self->private_impl.f_height) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, 0u); ++ } else if (v_width_in_bytes < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_width_in_bytes); ++ } ++ v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_bytes_per_pixel))); ++ if (v_i < ((uint64_t)(v_dst.len))) { ++ v_j = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * ((uint64_t)(v_bytes_per_pixel))); ++ if ((v_i <= v_j) && (v_j <= ((uint64_t)(v_dst.len)))) { ++ v_dst = wuffs_base__slice_u8__subslice_ij(v_dst, v_i, v_j); ++ } else { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i); ++ } ++ v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024), v_src); ++ wuffs_private_impl__u64__sat_add_indirect(&v_src_ri, v_n); ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); ++ self->private_impl.f_dirty_max_excl_y = wuffs_base__u32__max(self->private_impl.f_dirty_max_excl_y, wuffs_base__u32__sat_add(self->private_impl.f_dst_y, 1u)); ++ } ++ if (self->private_impl.f_frame_rect_x1 <= self->private_impl.f_dst_x) { ++ self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0; ++ if (self->private_impl.f_interlace == 0u) { ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_y, 1u); ++ continue; ++ } ++ if ((self->private_impl.f_num_decoded_frames_value == 0u) && ! self->private_impl.f_gc_has_transparent_index && (self->private_impl.f_interlace > 1u)) { ++ v_replicate_src = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ v_replicate_y0 = wuffs_base__u32__sat_add(self->private_impl.f_dst_y, 1u); ++ v_replicate_y1 = wuffs_base__u32__sat_add(self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_COUNT[self->private_impl.f_interlace]))); ++ v_replicate_y1 = wuffs_base__u32__min(v_replicate_y1, self->private_impl.f_frame_rect_y1); ++ while (v_replicate_y0 < v_replicate_y1) { ++ v_replicate_dst = wuffs_private_impl__table_u8__row_u32(v_tab, v_replicate_y0); ++ wuffs_private_impl__slice_u8__copy_from_slice(v_replicate_dst, v_replicate_src); ++ v_replicate_y0 += 1u; ++ } ++ self->private_impl.f_dirty_max_excl_y = wuffs_base__u32__max(self->private_impl.f_dirty_max_excl_y, v_replicate_y1); ++ } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_DELTA[self->private_impl.f_interlace]))); ++ while ((self->private_impl.f_interlace > 0u) && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1)) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_interlace -= 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ self->private_impl.f_dst_y = wuffs_base__u32__sat_add(self->private_impl.f_frame_rect_y0, WUFFS_GIF__INTERLACE_START[self->private_impl.f_interlace]); ++ } ++ continue; ++ } ++ if (((uint64_t)(a_src.len)) == v_src_ri) { ++ break; ++ } else if (((uint64_t)(a_src.len)) < v_src_ri) { ++ return wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_i_o); ++ } ++ v_n = ((uint64_t)((self->private_impl.f_frame_rect_x1 - self->private_impl.f_dst_x))); ++ v_n = wuffs_base__u64__min(v_n, (((uint64_t)(a_src.len)) - v_src_ri)); ++ wuffs_private_impl__u64__sat_add_indirect(&v_src_ri, v_n); ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); ++ if (self->private_impl.f_frame_rect_x1 <= self->private_impl.f_dst_x) { ++ self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0; ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_DELTA[self->private_impl.f_interlace]))); ++ while ((self->private_impl.f_interlace > 0u) && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1)) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_interlace -= 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ self->private_impl.f_dst_y = wuffs_base__u32__sat_add(self->private_impl.f_frame_rect_y0, WUFFS_GIF__INTERLACE_START[self->private_impl.f_interlace]); ++ } ++ continue; ++ } ++ if (v_src_ri != ((uint64_t)(a_src.len))) { ++ return wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_i_o); ++ } ++ break; + } +- return ((a_width + 31u) / 32u); ++ return wuffs_base__make_status(NULL); + } + +-// -------- func jpeg.decoder.decode_frame_config ++// -------- func gif.decoder.lzw_init + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_jpeg__decoder__decode_frame_config( +- wuffs_jpeg__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 2)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_jpeg__decoder__do_decode_frame_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++static wuffs_base__empty_struct ++wuffs_gif__decoder__lzw_init( ++ wuffs_gif__decoder* self) { ++ uint32_t v_i = 0; + +- ok: +- self->private_impl.p_decode_frame_config[0] = 0; +- goto exit; ++ self->private_impl.f_lzw_literal_width = 8u; ++ if (self->private_impl.f_lzw_pending_literal_width_plus_one > 0u) { ++ self->private_impl.f_lzw_literal_width = (self->private_impl.f_lzw_pending_literal_width_plus_one - 1u); + } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; +- +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ self->private_impl.f_lzw_clear_code = (((uint32_t)(1u)) << self->private_impl.f_lzw_literal_width); ++ self->private_impl.f_lzw_end_code = (self->private_impl.f_lzw_clear_code + 1u); ++ self->private_impl.f_lzw_save_code = self->private_impl.f_lzw_end_code; ++ self->private_impl.f_lzw_prev_code = self->private_impl.f_lzw_end_code; ++ self->private_impl.f_lzw_width = (self->private_impl.f_lzw_literal_width + 1u); ++ self->private_impl.f_lzw_bits = 0u; ++ self->private_impl.f_lzw_n_bits = 0u; ++ self->private_impl.f_lzw_output_ri = 0u; ++ self->private_impl.f_lzw_output_wi = 0u; ++ v_i = 0u; ++ while (v_i < self->private_impl.f_lzw_clear_code) { ++ self->private_data.f_lzw_lm1s[v_i] = 0u; ++ self->private_data.f_lzw_suffixes[v_i][0u] = ((uint8_t)(v_i)); ++ v_i += 1u; + } +- return status; ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func jpeg.decoder.do_decode_frame_config ++// -------- func gif.decoder.lzw_read_from + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__do_decode_frame_config( +- wuffs_jpeg__decoder* self, +- wuffs_base__frame_config* a_dst, ++static wuffs_base__empty_struct ++wuffs_gif__decoder__lzw_read_from( ++ wuffs_gif__decoder* self, + wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++ uint32_t v_clear_code = 0; ++ uint32_t v_end_code = 0; ++ uint32_t v_save_code = 0; ++ uint32_t v_prev_code = 0; ++ uint32_t v_width = 0; ++ uint32_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint32_t v_output_wi = 0; ++ uint32_t v_code = 0; ++ uint32_t v_c = 0; ++ uint32_t v_o = 0; ++ uint32_t v_steps = 0; ++ uint8_t v_first_byte = 0; ++ uint16_t v_lm1_b = 0; ++ uint16_t v_lm1_a = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -43434,83 +43552,370 @@ wuffs_jpeg__decoder__do_decode_frame_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- if (self->private_impl.f_call_sequence == 32u) { +- } else if (self->private_impl.f_call_sequence < 32u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ v_clear_code = self->private_impl.f_lzw_clear_code; ++ v_end_code = self->private_impl.f_lzw_end_code; ++ v_save_code = self->private_impl.f_lzw_save_code; ++ v_prev_code = self->private_impl.f_lzw_prev_code; ++ v_width = self->private_impl.f_lzw_width; ++ v_bits = self->private_impl.f_lzw_bits; ++ v_n_bits = self->private_impl.f_lzw_n_bits; ++ v_output_wi = self->private_impl.f_lzw_output_wi; ++ while (true) { ++ if (v_n_bits < v_width) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= 4u) { ++ v_bits |= ((uint32_t)(wuffs_base__peek_u32le__no_bounds_check(iop_a_src) << v_n_bits)); ++ iop_a_src += ((31u - v_n_bits) >> 3u); ++ v_n_bits |= 24u; ++ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ self->private_impl.f_lzw_read_from_return_value = 3u; ++ } else { ++ self->private_impl.f_lzw_read_from_return_value = 2u; ++ } ++ break; ++ } else { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ if (v_n_bits >= v_width) { ++ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ self->private_impl.f_lzw_read_from_return_value = 3u; ++ } else { ++ self->private_impl.f_lzw_read_from_return_value = 2u; ++ } ++ break; ++ } else { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ if (v_n_bits < v_width) { ++ self->private_impl.f_lzw_read_from_return_value = 5u; ++ break; ++ } ++ } + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_jpeg__decoder__do_decode_image_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ v_code = ((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(v_width)); ++ v_bits >>= v_width; ++ v_n_bits -= v_width; ++ if (v_code < v_clear_code) { ++ self->private_data.f_lzw_output[v_output_wi] = ((uint8_t)(v_code)); ++ v_output_wi = ((v_output_wi + 1u) & 8191u); ++ if (v_save_code <= 4095u) { ++ v_lm1_a = ((uint16_t)(((uint16_t)(self->private_data.f_lzw_lm1s[v_prev_code] + 1u)) & 4095u)); ++ self->private_data.f_lzw_lm1s[v_save_code] = v_lm1_a; ++ if (((uint16_t)(v_lm1_a % 8u)) != 0u) { ++ self->private_impl.f_lzw_prefixes[v_save_code] = self->private_impl.f_lzw_prefixes[v_prev_code]; ++ memcpy(self->private_data.f_lzw_suffixes[v_save_code],self->private_data.f_lzw_suffixes[v_prev_code], sizeof(self->private_data.f_lzw_suffixes[v_save_code])); ++ self->private_data.f_lzw_suffixes[v_save_code][((uint16_t)(v_lm1_a % 8u))] = ((uint8_t)(v_code)); ++ } else { ++ self->private_impl.f_lzw_prefixes[v_save_code] = ((uint16_t)(v_prev_code)); ++ self->private_data.f_lzw_suffixes[v_save_code][0u] = ((uint8_t)(v_code)); ++ } ++ v_save_code += 1u; ++ if (v_width < 12u) { ++ v_width += (1u & (v_save_code >> v_width)); ++ } ++ v_prev_code = v_code; + } +- if (status.repr) { +- goto suspend; ++ } else if (v_code <= v_end_code) { ++ if (v_code == v_end_code) { ++ self->private_impl.f_lzw_read_from_return_value = 0u; ++ break; + } +- } else if (self->private_impl.f_call_sequence == 40u) { +- if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_restart); +- goto exit; ++ v_save_code = v_end_code; ++ v_prev_code = v_end_code; ++ v_width = (self->private_impl.f_lzw_literal_width + 1u); ++ } else if (v_code <= v_save_code) { ++ v_c = v_code; ++ if (v_code == v_save_code) { ++ v_c = v_prev_code; ++ } ++ v_o = ((v_output_wi + (((uint32_t)(self->private_data.f_lzw_lm1s[v_c])) & 4294967288u)) & 8191u); ++ v_output_wi = ((v_output_wi + 1u + ((uint32_t)(self->private_data.f_lzw_lm1s[v_c]))) & 8191u); ++ v_steps = (((uint32_t)(self->private_data.f_lzw_lm1s[v_c])) >> 3u); ++ while (true) { ++ memcpy((self->private_data.f_lzw_output)+(v_o), (self->private_data.f_lzw_suffixes[v_c]), 8u); ++ if (v_steps <= 0u) { ++ break; ++ } ++ v_steps -= 1u; ++ v_o = (((uint32_t)(v_o - 8u)) & 8191u); ++ v_c = ((uint32_t)(self->private_impl.f_lzw_prefixes[v_c])); ++ } ++ v_first_byte = self->private_data.f_lzw_suffixes[v_c][0u]; ++ if (v_code == v_save_code) { ++ self->private_data.f_lzw_output[v_output_wi] = v_first_byte; ++ v_output_wi = ((v_output_wi + 1u) & 8191u); ++ } ++ if (v_save_code <= 4095u) { ++ v_lm1_b = ((uint16_t)(((uint16_t)(self->private_data.f_lzw_lm1s[v_prev_code] + 1u)) & 4095u)); ++ self->private_data.f_lzw_lm1s[v_save_code] = v_lm1_b; ++ if (((uint16_t)(v_lm1_b % 8u)) != 0u) { ++ self->private_impl.f_lzw_prefixes[v_save_code] = self->private_impl.f_lzw_prefixes[v_prev_code]; ++ memcpy(self->private_data.f_lzw_suffixes[v_save_code],self->private_data.f_lzw_suffixes[v_prev_code], sizeof(self->private_data.f_lzw_suffixes[v_save_code])); ++ self->private_data.f_lzw_suffixes[v_save_code][((uint16_t)(v_lm1_b % 8u))] = v_first_byte; ++ } else { ++ self->private_impl.f_lzw_prefixes[v_save_code] = ((uint16_t)(v_prev_code)); ++ self->private_data.f_lzw_suffixes[v_save_code][0u] = ((uint8_t)(v_first_byte)); ++ } ++ v_save_code += 1u; ++ if (v_width < 12u) { ++ v_width += (1u & (v_save_code >> v_width)); ++ } ++ v_prev_code = v_code; + } +- } else if (self->private_impl.f_call_sequence == 64u) { +- self->private_impl.f_call_sequence = 96u; +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; + } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; ++ self->private_impl.f_lzw_read_from_return_value = 4u; ++ break; + } +- if (a_dst != NULL) { +- wuffs_base__frame_config__set( +- a_dst, +- wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height), +- ((wuffs_base__flicks)(0u)), +- 0u, +- self->private_impl.f_frame_config_io_position, +- 0u, +- true, +- false, +- 4278190080u); ++ if (v_output_wi > 4095u) { ++ self->private_impl.f_lzw_read_from_return_value = 1u; ++ break; + } +- self->private_impl.f_call_sequence = 64u; +- +- ok: +- self->private_impl.p_do_decode_frame_config[0] = 0; +- goto exit; + } +- +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: ++ if (self->private_impl.f_lzw_read_from_return_value != 2u) { ++ while (v_n_bits >= 8u) { ++ v_n_bits -= 8u; ++ if (iop_a_src > io1_a_src) { ++ iop_a_src--; ++ } else { ++ self->private_impl.f_lzw_read_from_return_value = 5u; ++ break; ++ } ++ } ++ } ++ self->private_impl.f_lzw_save_code = v_save_code; ++ self->private_impl.f_lzw_prev_code = v_prev_code; ++ self->private_impl.f_lzw_width = v_width; ++ self->private_impl.f_lzw_bits = v_bits; ++ self->private_impl.f_lzw_n_bits = v_n_bits; ++ self->private_impl.f_lzw_output_wi = v_output_wi; + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- return status; ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func jpeg.decoder.decode_frame ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_gzip__error__bad_checksum[] = "#gzip: bad checksum"; ++const char wuffs_gzip__error__bad_compression_method[] = "#gzip: bad compression method"; ++const char wuffs_gzip__error__bad_encoding_flags[] = "#gzip: bad encoding flags"; ++const char wuffs_gzip__error__bad_header[] = "#gzip: bad header"; ++const char wuffs_gzip__error__truncated_input[] = "#gzip: truncated input"; ++ ++// ---------------- Private Consts ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_jpeg__decoder__decode_frame( +- wuffs_jpeg__decoder* self, +- wuffs_base__pixel_buffer* a_dst, ++static wuffs_base__status ++wuffs_gzip__decoder__do_transform_io( ++ wuffs_gzip__decoder* self, ++ wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__slice_u8 a_workbuf); ++ ++// ---------------- VTables ++ ++const wuffs_base__io_transformer__func_ptrs ++wuffs_gzip__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++ (wuffs_base__optional_u63(*)(const void*))(&wuffs_gzip__decoder__dst_history_retain_length), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_gzip__decoder__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_gzip__decoder__set_quirk), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_gzip__decoder__transform_io), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_gzip__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_gzip__decoder__initialize( ++ wuffs_gzip__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ { ++ wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize( ++ &self->private_data.f_checksum, sizeof(self->private_data.f_checksum), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ { ++ wuffs_base__status z = wuffs_deflate__decoder__initialize( ++ &self->private_data.f_flate, sizeof(self->private_data.f_flate), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = ++ wuffs_base__io_transformer__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = ++ (const void*)(&wuffs_gzip__decoder__func_ptrs_for__wuffs_base__io_transformer); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_gzip__decoder* ++wuffs_gzip__decoder__alloc(void) { ++ wuffs_gzip__decoder* x = ++ (wuffs_gzip__decoder*)(calloc(1, sizeof(wuffs_gzip__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_gzip__decoder__initialize( ++ x, sizeof(wuffs_gzip__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_gzip__decoder(void) { ++ return sizeof(wuffs_gzip__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func gzip.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_gzip__decoder__get_quirk( ++ const wuffs_gzip__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if ((a_key == 1u) && self->private_impl.f_ignore_checksum) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func gzip.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_gzip__decoder__set_quirk( ++ wuffs_gzip__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (a_key == 1u) { ++ self->private_impl.f_ignore_checksum = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func gzip.decoder.dst_history_retain_length ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_gzip__decoder__dst_history_retain_length( ++ const wuffs_gzip__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ ++ return wuffs_base__utility__make_optional_u63(true, 0u); ++} ++ ++// -------- func gzip.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_gzip__decoder__workbuf_len( ++ const wuffs_gzip__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__make_range_ii_u64(1u, 1u); ++} ++ ++// -------- func gzip.decoder.transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_gzip__decoder__transform_io( ++ wuffs_gzip__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +@@ -43525,65 +43930,41 @@ wuffs_jpeg__decoder__decode_frame( + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 3)) { ++ (self->private_impl.active_coroutine != 1)) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } + self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__status v_ddf_status = wuffs_base__make_status(NULL); +- wuffs_base__status v_swizzle_status = wuffs_base__make_status(NULL); +- uint32_t v_scan_count = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_frame[0]; ++ uint32_t coro_susp_point = self->private_impl.p_transform_io; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { +- v_scan_count = self->private_impl.f_scan_count; + { +- wuffs_base__status t_0 = wuffs_jpeg__decoder__do_decode_frame(self, +- a_dst, +- a_src, +- a_blend, +- a_workbuf, +- a_opts); +- v_ddf_status = t_0; +- } +- if ((v_ddf_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- v_ddf_status = wuffs_base__make_status(wuffs_jpeg__error__truncated_input); ++ wuffs_base__status t_0 = wuffs_gzip__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); ++ v_status = t_0; + } +- if (wuffs_base__status__is_error(&v_ddf_status) || (v_scan_count < self->private_impl.f_scan_count)) { +- if (self->private_impl.f_sof_marker >= 194u) { +- wuffs_jpeg__decoder__apply_progressive_idct(self, a_workbuf); +- } +- if (self->private_impl.f_num_components == 1u) { +- v_swizzle_status = wuffs_jpeg__decoder__swizzle_gray(self, a_dst, a_workbuf); +- } else { +- v_swizzle_status = wuffs_jpeg__decoder__swizzle_colorful(self, a_dst, a_workbuf); +- } +- if (wuffs_base__status__is_error(&v_ddf_status)) { +- status = v_ddf_status; +- goto exit; +- } else if (wuffs_base__status__is_error(&v_swizzle_status)) { +- status = v_swizzle_status; +- goto exit; +- } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_gzip__error__truncated_input); ++ goto exit; + } +- status = v_ddf_status; ++ status = v_status; + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } + + ok: +- self->private_impl.p_decode_frame[0] = 0; ++ self->private_impl.p_transform_io = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ self->private_impl.p_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; + + goto exit; + exit: +@@ -43593,24 +43974,40 @@ wuffs_jpeg__decoder__decode_frame( + return status; + } + +-// -------- func jpeg.decoder.do_decode_frame ++// -------- func gzip.decoder.do_transform_io + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__do_decode_frame( +- wuffs_jpeg__decoder* self, +- wuffs_base__pixel_buffer* a_dst, ++wuffs_gzip__decoder__do_transform_io( ++ wuffs_gzip__decoder* self, ++ wuffs_base__io_buffer* a_dst, + wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__slice_u8 a_workbuf) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_pixfmt = 0; ++ uint8_t v_c8 = 0; ++ uint8_t v_flags = 0; ++ uint16_t v_xlen = 0; ++ uint64_t v_mark = 0; ++ uint32_t v_checksum_have = 0; ++ uint32_t v_decoded_length_have = 0; + wuffs_base__status v_status = wuffs_base__make_status(NULL); +- uint8_t v_c = 0; +- uint8_t v_marker = 0; ++ uint32_t v_checksum_want = 0; ++ uint32_t v_decoded_length_want = 0; + ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -43622,236 +44019,269 @@ wuffs_jpeg__decoder__do_decode_frame( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame[0]; ++ uint32_t coro_susp_point = self->private_impl.p_do_transform_io; + if (coro_susp_point) { +- v_marker = self->private_data.s_do_decode_frame[0].v_marker; ++ v_flags = self->private_data.s_do_transform_io.v_flags; ++ v_checksum_have = self->private_data.s_do_transform_io.v_checksum_have; ++ v_decoded_length_have = self->private_data.s_do_transform_io.v_decoded_length_have; ++ v_checksum_want = self->private_data.s_do_transform_io.v_checksum_want; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence == 64u) { +- } else if (self->private_impl.f_call_sequence < 64u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++ { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_jpeg__decoder__do_decode_frame_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- if (status.repr) { ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (v_c8 != 31u) { ++ status = wuffs_base__make_status(wuffs_gzip__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; + } +- v_pixfmt = 536870920u; +- if (self->private_impl.f_num_components > 1u) { +- v_pixfmt = 2415954056u; ++ if (v_c8 != 139u) { ++ status = wuffs_base__make_status(wuffs_gzip__error__bad_header); ++ goto exit; + } +- v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, +- wuffs_base__pixel_buffer__pixel_format(a_dst), +- wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), +- wuffs_base__utility__make_pixel_format(v_pixfmt), +- wuffs_base__utility__empty_slice_u8(), +- a_blend); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- goto ok; ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; + } +- if (self->private_impl.f_components_workbuf_offsets[8u] > ((uint64_t)(a_workbuf.len))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ if (v_c8 != 8u) { ++ status = wuffs_base__make_status(wuffs_gzip__error__bad_compression_method); + goto exit; +- } else if (self->private_impl.f_components_workbuf_offsets[4u] < self->private_impl.f_components_workbuf_offsets[8u]) { +- wuffs_base__bulk_memset(a_workbuf.ptr + self->private_impl.f_components_workbuf_offsets[4u], (self->private_impl.f_components_workbuf_offsets[8u] - self->private_impl.f_components_workbuf_offsets[4u]), 0u); + } +- if (self->private_impl.f_components_workbuf_offsets[4u] <= ((uint64_t)(a_workbuf.len))) { +- wuffs_base__bulk_memset(a_workbuf.ptr, self->private_impl.f_components_workbuf_offsets[4u], 128u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_flags = t_3; + } +- while (true) { ++ self->private_data.s_do_transform_io.scratch = 6u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (self->private_data.s_do_transform_io.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_transform_io.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_transform_io.scratch; ++ if (((uint8_t)(v_flags & 4u)) != 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ uint16_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_4 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; ++ if (num_bits_4 == 8) { ++ t_4 = ((uint16_t)(*scratch)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)) << 56; ++ } ++ } ++ v_xlen = t_4; ++ } ++ self->private_data.s_do_transform_io.scratch = ((uint32_t)(v_xlen)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (self->private_data.s_do_transform_io.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_transform_io.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_transform_io.scratch; ++ } ++ if (((uint8_t)(v_flags & 8u)) != 0u) { + while (true) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; + } +- if (v_c == 255u) { ++ if (v_c8 == 0u) { + break; + } + } ++ } ++ if (((uint8_t)(v_flags & 16u)) != 0u) { + while (true) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; + } +- if (v_c != 255u) { +- v_marker = v_c; ++ if (v_c8 == 0u) { + break; + } + } +- if (v_marker == 0u) { +- continue; +- } else if ((208u <= v_marker) && (v_marker <= 217u)) { +- if (v_marker <= 215u) { +- continue; ++ } ++ if (((uint8_t)(v_flags & 2u)) != 0u) { ++ self->private_data.s_do_transform_io.scratch = 2u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ if (self->private_data.s_do_transform_io.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_transform_io.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_transform_io.scratch; ++ } ++ if (((uint8_t)(v_flags & 224u)) != 0u) { ++ status = wuffs_base__make_status(wuffs_gzip__error__bad_encoding_flags); ++ goto exit; ++ } ++ while (true) { ++ v_mark = ((uint64_t)(iop_a_dst - io0_a_dst)); ++ { ++ if (a_dst) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); + } +- } else { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- uint32_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_2 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_frame[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_frame[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); +- if (num_bits_2 == 8) { +- t_2 = ((uint32_t)(*scratch >> 48)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)); +- } +- } +- self->private_impl.f_payload_length = t_2; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- if (self->private_impl.f_payload_length < 2u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_marker); +- goto exit; ++ wuffs_base__status t_7 = wuffs_deflate__decoder__transform_io(&self->private_data.f_flate, a_dst, a_src, a_workbuf); ++ v_status = t_7; ++ 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; + } +- self->private_impl.f_payload_length -= 2u; + } +- if (v_marker < 192u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); +- goto exit; +- } else if (v_marker < 208u) { +- if (v_marker == 196u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- status = wuffs_jpeg__decoder__decode_dht(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { ++ if ( ! self->private_impl.f_ignore_checksum) { ++ v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_checksum, wuffs_private_impl__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); ++ v_decoded_length_have += ((uint32_t)(wuffs_private_impl__io__count_since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst))))); ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ uint32_t t_8; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- continue; +- } else if (v_marker == 200u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); +- goto exit; +- } else if (v_marker < 224u) { +- if (v_marker < 217u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_marker); +- goto exit; +- } else if (v_marker == 217u) { +- break; +- } else if (v_marker == 218u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- status = wuffs_jpeg__decoder__decode_sos(self, a_src, a_workbuf); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8; ++ if (num_bits_8 == 24) { ++ t_8 = ((uint32_t)(*scratch)); ++ break; + } +- if (status.repr) { ++ num_bits_8 += 8u; ++ *scratch |= ((uint64_t)(num_bits_8)) << 56; ++ } ++ } ++ v_checksum_want = t_8; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ uint32_t t_9; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_9 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- continue; +- } else if (v_marker == 219u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- status = wuffs_jpeg__decoder__decode_dqt(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- continue; +- } else if (v_marker == 221u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- status = wuffs_jpeg__decoder__decode_dri(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9; ++ if (num_bits_9 == 24) { ++ t_9 = ((uint32_t)(*scratch)); ++ break; + } +- continue; +- } else { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); +- goto exit; +- } +- } else if (v_marker < 240u) { +- } else { +- if (v_marker == 254u) { +- } else { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); +- goto exit; ++ num_bits_9 += 8u; ++ *scratch |= ((uint64_t)(num_bits_9)) << 56; + } + } +- self->private_data.s_do_decode_frame[0].scratch = self->private_impl.f_payload_length; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- if (self->private_data.s_do_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_frame[0].scratch; +- self->private_impl.f_payload_length = 0u; ++ v_decoded_length_want = t_9; ++ } ++ if ( ! self->private_impl.f_ignore_checksum && ((v_checksum_have != v_checksum_want) || (v_decoded_length_have != v_decoded_length_want))) { ++ status = wuffs_base__make_status(wuffs_gzip__error__bad_checksum); ++ goto exit; + } +- self->private_impl.f_call_sequence = 96u; + + ok: +- self->private_impl.p_do_decode_frame[0] = 0; ++ self->private_impl.p_do_transform_io = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_decode_frame[0].v_marker = v_marker; ++ self->private_impl.p_do_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_transform_io.v_flags = v_flags; ++ self->private_data.s_do_transform_io.v_checksum_have = v_checksum_have; ++ self->private_data.s_do_transform_io.v_decoded_length_have = v_decoded_length_have; ++ self->private_data.s_do_transform_io.v_checksum_want = v_checksum_want; + + goto exit; + exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -43859,891 +44289,398 @@ wuffs_jpeg__decoder__do_decode_frame( + return status; + } + +-// -------- func jpeg.decoder.decode_dht ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP) + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_jpeg__decoder__decode_dht( +- wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JPEG) + +- uint8_t v_c = 0; +- uint8_t v_tc = 0; +- uint8_t v_th = 0; +- uint8_t v_tc4_th = 0; +- uint32_t v_working_total_count = 0; +- uint32_t v_total_count = 0; +- uint32_t v_i = 0; +- bool v_failed = false; ++// ---------------- Status Codes Implementations + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++const char wuffs_jpeg__error__bad_dht_marker[] = "#jpeg: bad DHT marker"; ++const char wuffs_jpeg__error__bad_dqt_marker[] = "#jpeg: bad DQT marker"; ++const char wuffs_jpeg__error__bad_dri_marker[] = "#jpeg: bad DRI marker"; ++const char wuffs_jpeg__error__bad_sof_marker[] = "#jpeg: bad SOF marker"; ++const char wuffs_jpeg__error__bad_sos_marker[] = "#jpeg: bad SOS marker"; ++const char wuffs_jpeg__error__bad_header[] = "#jpeg: bad header"; ++const char wuffs_jpeg__error__bad_marker[] = "#jpeg: bad marker"; ++const char wuffs_jpeg__error__bad_scan_count[] = "#jpeg: bad scan count"; ++const char wuffs_jpeg__error__missing_huffman_table[] = "#jpeg: missing Huffman table"; ++const char wuffs_jpeg__error__missing_quantization_table[] = "#jpeg: missing Quantization table"; ++const char wuffs_jpeg__error__rejected_progressive_jpeg[] = "#jpeg: rejected progressive JPEG"; ++const char wuffs_jpeg__error__truncated_input[] = "#jpeg: truncated input"; ++const char wuffs_jpeg__error__unsupported_arithmetic_coding[] = "#jpeg: unsupported arithmetic coding"; ++const char wuffs_jpeg__error__unsupported_color_model[] = "#jpeg: unsupported color model"; ++const char wuffs_jpeg__error__unsupported_fractional_sampling[] = "#jpeg: unsupported fractional sampling"; ++const char wuffs_jpeg__error__unsupported_hierarchical_coding[] = "#jpeg: unsupported hierarchical coding"; ++const char wuffs_jpeg__error__unsupported_implicit_height[] = "#jpeg: unsupported implicit height"; ++const char wuffs_jpeg__error__unsupported_lossless_coding[] = "#jpeg: unsupported lossless coding"; ++const char wuffs_jpeg__error__unsupported_marker[] = "#jpeg: unsupported marker"; ++const char wuffs_jpeg__error__unsupported_precision_12_bits[] = "#jpeg: unsupported precision (12 bits)"; ++const char wuffs_jpeg__error__unsupported_precision_16_bits[] = "#jpeg: unsupported precision (16 bits)"; ++const char wuffs_jpeg__error__unsupported_precision[] = "#jpeg: unsupported precision"; ++const char wuffs_jpeg__error__unsupported_scan_count[] = "#jpeg: unsupported scan count"; ++const char wuffs_jpeg__error__internal_error_inconsistent_decoder_state[] = "#jpeg: internal error: inconsistent decoder state"; + +- uint32_t coro_susp_point = self->private_impl.p_decode_dht[0]; +- if (coro_susp_point) { +- v_tc4_th = self->private_data.s_decode_dht[0].v_tc4_th; +- v_total_count = self->private_data.s_decode_dht[0].v_total_count; +- v_i = self->private_data.s_decode_dht[0].v_i; +- } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++// ---------------- Private Consts + +- if (self->private_impl.f_sof_marker == 0u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } +- while (self->private_impl.f_payload_length > 0u) { +- if (self->private_impl.f_payload_length < 17u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } +- self->private_impl.f_payload_length -= 17u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if (((v_c >> 4u) > 1u) || ((v_c & 15u) > 3u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } +- v_tc = (v_c >> 4u); +- v_th = (v_c & 15u); +- v_tc4_th = ((uint8_t)(((v_tc * 4u) | v_th))); +- if ((self->private_impl.f_sof_marker == 192u) && ((v_tc4_th & 3u) > 1u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } +- v_i = 0u; +- while (v_i < 16u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- self->private_data.f_dht_temp_counts[v_i] = t_1; +- } +- v_i += 1u; +- } +- v_working_total_count = 0u; +- v_i = 0u; +- while (v_i < 16u) { +- v_working_total_count = ((v_working_total_count + ((uint32_t)(self->private_data.f_dht_temp_counts[v_i]))) & 65535u); +- v_i += 1u; +- } +- if ((v_working_total_count <= 0u) || (256u < v_working_total_count)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } +- v_total_count = v_working_total_count; +- if (self->private_impl.f_payload_length < v_total_count) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } +- self->private_impl.f_payload_length -= v_total_count; +- v_i = 0u; +- while (v_i < v_total_count) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_2 = *iop_a_src++; +- self->private_impl.f_huff_tables_symbols[v_tc4_th][v_i] = t_2; +- } +- v_i += 1u; +- } +- while (v_i < 256u) { +- self->private_impl.f_huff_tables_symbols[v_tc4_th][v_i] = 0u; +- v_i += 1u; +- } +- if ((v_tc4_th & 4u) == 0u) { +- v_i = 0u; +- while (v_i < v_total_count) { +- if (self->private_impl.f_huff_tables_symbols[v_tc4_th][v_i] > 15u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } +- v_i += 1u; +- } +- } +- v_failed = wuffs_jpeg__decoder__calculate_huff_tables(self, v_tc4_th, v_total_count); +- if (v_failed) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); +- goto exit; +- } +- self->private_impl.f_seen_dht[v_tc4_th] = true; +- } ++static const uint8_t ++WUFFS_JPEG__UNZIG[80] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 1u, 8u, 16u, 9u, 2u, 3u, ++ 10u, 17u, 24u, 32u, 25u, 18u, 11u, 4u, ++ 5u, 12u, 19u, 26u, 33u, 40u, 48u, 41u, ++ 34u, 27u, 20u, 13u, 6u, 7u, 14u, 21u, ++ 28u, 35u, 42u, 49u, 56u, 57u, 50u, 43u, ++ 36u, 29u, 22u, 15u, 23u, 30u, 37u, 44u, ++ 51u, 58u, 59u, 52u, 45u, 38u, 31u, 39u, ++ 46u, 53u, 60u, 61u, 54u, 47u, 55u, 62u, ++ 63u, 63u, 63u, 63u, 63u, 63u, 63u, 63u, ++ 63u, 63u, 63u, 63u, 63u, 63u, 63u, 63u, ++}; + +- goto ok; +- ok: +- self->private_impl.p_decode_dht[0] = 0; +- goto exit; +- } ++static const uint8_t ++WUFFS_JPEG__BIAS_AND_CLAMP[1024] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 128u, 129u, 130u, 131u, 132u, 133u, 134u, 135u, ++ 136u, 137u, 138u, 139u, 140u, 141u, 142u, 143u, ++ 144u, 145u, 146u, 147u, 148u, 149u, 150u, 151u, ++ 152u, 153u, 154u, 155u, 156u, 157u, 158u, 159u, ++ 160u, 161u, 162u, 163u, 164u, 165u, 166u, 167u, ++ 168u, 169u, 170u, 171u, 172u, 173u, 174u, 175u, ++ 176u, 177u, 178u, 179u, 180u, 181u, 182u, 183u, ++ 184u, 185u, 186u, 187u, 188u, 189u, 190u, 191u, ++ 192u, 193u, 194u, 195u, 196u, 197u, 198u, 199u, ++ 200u, 201u, 202u, 203u, 204u, 205u, 206u, 207u, ++ 208u, 209u, 210u, 211u, 212u, 213u, 214u, 215u, ++ 216u, 217u, 218u, 219u, 220u, 221u, 222u, 223u, ++ 224u, 225u, 226u, 227u, 228u, 229u, 230u, 231u, ++ 232u, 233u, 234u, 235u, 236u, 237u, 238u, 239u, ++ 240u, 241u, 242u, 243u, 244u, 245u, 246u, 247u, ++ 248u, 249u, 250u, 251u, 252u, 253u, 254u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, ++ 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, ++ 16u, 17u, 18u, 19u, 20u, 21u, 22u, 23u, ++ 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, ++ 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, ++ 40u, 41u, 42u, 43u, 44u, 45u, 46u, 47u, ++ 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, ++ 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, ++ 64u, 65u, 66u, 67u, 68u, 69u, 70u, 71u, ++ 72u, 73u, 74u, 75u, 76u, 77u, 78u, 79u, ++ 80u, 81u, 82u, 83u, 84u, 85u, 86u, 87u, ++ 88u, 89u, 90u, 91u, 92u, 93u, 94u, 95u, ++ 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, ++ 104u, 105u, 106u, 107u, 108u, 109u, 110u, 111u, ++ 112u, 113u, 114u, 115u, 116u, 117u, 118u, 119u, ++ 120u, 121u, 122u, 123u, 124u, 125u, 126u, 127u, ++}; + +- goto suspend; +- suspend: +- self->private_impl.p_decode_dht[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_dht[0].v_tc4_th = v_tc4_th; +- self->private_data.s_decode_dht[0].v_total_count = v_total_count; +- self->private_data.s_decode_dht[0].v_i = v_i; ++static const uint16_t ++WUFFS_JPEG__EXTEND[16] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 65535u, 65533u, 65529u, 65521u, 65505u, 65473u, 65409u, ++ 65281u, 65025u, 64513u, 63489u, 61441u, 57345u, 49153u, 32769u, ++}; + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++static const uint8_t ++WUFFS_JPEG__DEFAULT_HUFF_TABLE_DC_LUMA[29] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 1u, 5u, 1u, 1u, 1u, 1u, ++ 1u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 1u, 2u, 3u, 4u, 5u, 6u, ++ 7u, 8u, 9u, 10u, 11u, ++}; + +- return status; +-} ++static const uint8_t ++WUFFS_JPEG__DEFAULT_HUFF_TABLE_DC_CHROMA[29] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1u, 0u, 3u, 1u, 1u, 1u, 1u, 1u, ++ 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 1u, 2u, 3u, 4u, 5u, 6u, ++ 7u, 8u, 9u, 10u, 11u, ++}; + +-// -------- func jpeg.decoder.calculate_huff_tables ++static const uint8_t ++WUFFS_JPEG__DEFAULT_HUFF_TABLE_AC_LUMA[179] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 16u, 0u, 2u, 1u, 3u, 3u, 2u, 4u, ++ 3u, 5u, 5u, 4u, 4u, 0u, 0u, 1u, ++ 125u, 1u, 2u, 3u, 0u, 4u, 17u, 5u, ++ 18u, 33u, 49u, 65u, 6u, 19u, 81u, 97u, ++ 7u, 34u, 113u, 20u, 50u, 129u, 145u, 161u, ++ 8u, 35u, 66u, 177u, 193u, 21u, 82u, 209u, ++ 240u, 36u, 51u, 98u, 114u, 130u, 9u, 10u, ++ 22u, 23u, 24u, 25u, 26u, 37u, 38u, 39u, ++ 40u, 41u, 42u, 52u, 53u, 54u, 55u, 56u, ++ 57u, 58u, 67u, 68u, 69u, 70u, 71u, 72u, ++ 73u, 74u, 83u, 84u, 85u, 86u, 87u, 88u, ++ 89u, 90u, 99u, 100u, 101u, 102u, 103u, 104u, ++ 105u, 106u, 115u, 116u, 117u, 118u, 119u, 120u, ++ 121u, 122u, 131u, 132u, 133u, 134u, 135u, 136u, ++ 137u, 138u, 146u, 147u, 148u, 149u, 150u, 151u, ++ 152u, 153u, 154u, 162u, 163u, 164u, 165u, 166u, ++ 167u, 168u, 169u, 170u, 178u, 179u, 180u, 181u, ++ 182u, 183u, 184u, 185u, 186u, 194u, 195u, 196u, ++ 197u, 198u, 199u, 200u, 201u, 202u, 210u, 211u, ++ 212u, 213u, 214u, 215u, 216u, 217u, 218u, 225u, ++ 226u, 227u, 228u, 229u, 230u, 231u, 232u, 233u, ++ 234u, 241u, 242u, 243u, 244u, 245u, 246u, 247u, ++ 248u, 249u, 250u, ++}; ++ ++static const uint8_t ++WUFFS_JPEG__DEFAULT_HUFF_TABLE_AC_CHROMA[179] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 17u, 0u, 2u, 1u, 2u, 4u, 4u, 3u, ++ 4u, 7u, 5u, 4u, 4u, 0u, 1u, 2u, ++ 119u, 0u, 1u, 2u, 3u, 17u, 4u, 5u, ++ 33u, 49u, 6u, 18u, 65u, 81u, 7u, 97u, ++ 113u, 19u, 34u, 50u, 129u, 8u, 20u, 66u, ++ 145u, 161u, 177u, 193u, 9u, 35u, 51u, 82u, ++ 240u, 21u, 98u, 114u, 209u, 10u, 22u, 36u, ++ 52u, 225u, 37u, 241u, 23u, 24u, 25u, 26u, ++ 38u, 39u, 40u, 41u, 42u, 53u, 54u, 55u, ++ 56u, 57u, 58u, 67u, 68u, 69u, 70u, 71u, ++ 72u, 73u, 74u, 83u, 84u, 85u, 86u, 87u, ++ 88u, 89u, 90u, 99u, 100u, 101u, 102u, 103u, ++ 104u, 105u, 106u, 115u, 116u, 117u, 118u, 119u, ++ 120u, 121u, 122u, 130u, 131u, 132u, 133u, 134u, ++ 135u, 136u, 137u, 138u, 146u, 147u, 148u, 149u, ++ 150u, 151u, 152u, 153u, 154u, 162u, 163u, 164u, ++ 165u, 166u, 167u, 168u, 169u, 170u, 178u, 179u, ++ 180u, 181u, 182u, 183u, 184u, 185u, 186u, 194u, ++ 195u, 196u, 197u, 198u, 199u, 200u, 201u, 202u, ++ 210u, 211u, 212u, 213u, 214u, 215u, 216u, 217u, ++ 218u, 226u, 227u, 228u, 229u, 230u, 231u, 232u, ++ 233u, 234u, 242u, 243u, 244u, 245u, 246u, 247u, ++ 248u, 249u, 250u, ++}; ++ ++#define WUFFS_JPEG__QUIRKS_BASE 1220532224u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE +-static bool +-wuffs_jpeg__decoder__calculate_huff_tables( ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__decode_idct( + wuffs_jpeg__decoder* self, +- uint8_t a_tc4_th, +- uint32_t a_total_count) { +- uint32_t v_i = 0; +- uint8_t v_j = 0; +- uint8_t v_k = 0; +- uint32_t v_bit_length_minus_one = 0; +- uint8_t v_bit_length = 0; +- uint32_t v_bit_string = 0; +- uint32_t v_slow = 0; +- uint8_t v_prefix = 0; +- uint16_t v_fast = 0; +- uint32_t v_reps = 0; ++ wuffs_base__slice_u8 a_dst_buffer, ++ uint64_t a_dst_stride, ++ uint32_t a_q); + +- v_i = 0u; +- v_k = 0u; +- v_bit_length_minus_one = 0u; +- while (v_i < a_total_count) { +- while (v_k >= self->private_data.f_dht_temp_counts[v_bit_length_minus_one]) { +- v_k = 0u; +- v_bit_length_minus_one = ((v_bit_length_minus_one + 1u) & 15u); +- } +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_k += 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- self->private_data.f_dht_temp_bit_lengths[v_i] = ((uint8_t)((v_bit_length_minus_one + 1u))); +- v_i += 1u; +- } +- v_bit_length = 0u; +- v_bit_string = 0u; +- v_i = 0u; +- while (v_i < a_total_count) { +- while (v_bit_length < self->private_data.f_dht_temp_bit_lengths[v_i]) { +- if (v_bit_length >= 16u) { +- return true; +- } +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_bit_length += 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- v_bit_string <<= 1u; +- } +- self->private_data.f_dht_temp_bit_strings[v_i] = ((uint16_t)(v_bit_string)); +- v_bit_string += 1u; +- if ((v_bit_string >> v_bit_length) > 0u) { +- return true; +- } +- v_i += 1u; +- } +- v_k = 0u; +- v_bit_length_minus_one = 0u; +- while (true) { +- if (self->private_data.f_dht_temp_counts[v_bit_length_minus_one] == 0u) { +- self->private_impl.f_huff_tables_slow[a_tc4_th][v_bit_length_minus_one] = 0u; +- } else { +- v_slow = (255u & ((uint32_t)(((uint32_t)(v_k)) - ((uint32_t)(self->private_data.f_dht_temp_bit_strings[v_k]))))); +- v_k += self->private_data.f_dht_temp_counts[v_bit_length_minus_one]; +- self->private_impl.f_huff_tables_slow[a_tc4_th][v_bit_length_minus_one] = (v_slow | ((((uint32_t)(self->private_data.f_dht_temp_bit_strings[((uint8_t)(v_k - 1u))])) + 1u) << 8u)); +- } +- v_bit_length_minus_one = ((v_bit_length_minus_one + 1u) & 15u); +- if (v_bit_length_minus_one == 0u) { +- break; +- } +- } +- v_i = 0u; +- while (v_i < 256u) { +- self->private_impl.f_huff_tables_fast[a_tc4_th][v_i] = 65535u; +- v_i += 1u; +- } +- v_j = 0u; +- v_bit_length_minus_one = 0u; +- while (v_bit_length_minus_one < 8u) { +- v_k = 0u; +- while (v_k < self->private_data.f_dht_temp_counts[v_bit_length_minus_one]) { +- v_prefix = ((uint8_t)((((uint32_t)(self->private_data.f_dht_temp_bit_strings[v_j])) << (7u - v_bit_length_minus_one)))); +- v_fast = ((uint16_t)(((((uint32_t)((v_bit_length_minus_one + 1u))) << 8u) | ((uint32_t)(self->private_impl.f_huff_tables_symbols[a_tc4_th][v_j]))))); +- v_reps = (((uint32_t)(1u)) << (7u - v_bit_length_minus_one)); +- while (v_reps > 0u) { +- self->private_impl.f_huff_tables_fast[a_tc4_th][v_prefix] = v_fast; +- v_prefix += 1u; +- v_reps -= 1u; +- } +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- v_k += 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- v_j += 1u; +- } +- v_bit_length_minus_one += 1u; +- } +- return false; +-} ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__decode_idct__choosy_default( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__slice_u8 a_dst_buffer, ++ uint64_t a_dst_stride, ++ uint32_t a_q); + +-// -------- func jpeg.decoder.decode_sos ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__decode_idct_x86_avx2( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__slice_u8 a_dst_buffer, ++ uint64_t a_dst_stride, ++ uint32_t a_q); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__decode_sos( ++wuffs_jpeg__decoder__do_decode_image_config( + wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_my = 0; +- uint32_t v_mx = 0; +- uint32_t v_decode_mcu_result = 0; +- uint32_t v_bitstream_length = 0; +- +- uint32_t coro_susp_point = self->private_impl.p_decode_sos[0]; +- if (coro_susp_point) { +- v_my = self->private_data.s_decode_sos[0].v_my; +- v_mx = self->private_data.s_decode_sos[0].v_mx; +- } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- if (self->private_impl.f_scan_count >= 64u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_scan_count); +- goto exit; +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_jpeg__decoder__prepare_scan(self, a_src); +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_next_restart_marker = 0u; +- self->private_impl.f_mcu_previous_dc_values[0u] = 0u; +- self->private_impl.f_mcu_previous_dc_values[1u] = 0u; +- self->private_impl.f_mcu_previous_dc_values[2u] = 0u; +- self->private_impl.f_mcu_previous_dc_values[3u] = 0u; +- self->private_impl.f_restarts_remaining = self->private_impl.f_restart_interval; +- self->private_impl.f_eob_run = 0u; +- self->private_impl.f_bitstream_bits = 0u; +- self->private_impl.f_bitstream_n_bits = 0u; +- self->private_impl.f_bitstream_ri = 0u; +- self->private_impl.f_bitstream_wi = 0u; +- self->private_impl.f_bitstream_padding = 12345u; +- wuffs_jpeg__decoder__fill_bitstream(self, a_src); +- v_my = 0u; +- while (v_my < self->private_impl.f_scan_height_in_mcus) { +- v_mx = 0u; +- while (v_mx < self->private_impl.f_scan_width_in_mcus) { +- self->private_impl.f_mcu_current_block = 0u; +- self->private_impl.f_mcu_zig_index = ((uint32_t)(self->private_impl.f_scan_ss)); +- if (self->private_impl.f_sof_marker >= 194u) { +- wuffs_jpeg__decoder__load_mcu_blocks(self, v_mx, v_my, a_workbuf); +- } +- while (true) { +- v_decode_mcu_result = wuffs_jpeg__decoder__decode_mcu(self, a_workbuf, v_mx, v_my); +- if (v_decode_mcu_result == 0u) { +- break; +- } else if (v_decode_mcu_result != 1u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__internal_error_inconsistent_decoder_state); +- goto exit; +- } +- while (true) { +- v_bitstream_length = ((uint32_t)(self->private_impl.f_bitstream_wi - self->private_impl.f_bitstream_ri)); +- wuffs_jpeg__decoder__fill_bitstream(self, a_src); +- if (v_bitstream_length < ((uint32_t)(self->private_impl.f_bitstream_wi - self->private_impl.f_bitstream_ri))) { +- break; +- } else if (self->private_impl.f_bitstream_padding == 0u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } else if ((a_src && a_src->meta.closed) && ! self->private_impl.f_bitstream_is_closed) { +- if (self->private_impl.f_bitstream_wi < 1024u) { +- wuffs_base__bulk_memset(&self->private_data.f_bitstream_buffer[self->private_impl.f_bitstream_wi], 264u, 0u); +- self->private_impl.f_bitstream_wi += 264u; +- self->private_impl.f_bitstream_is_closed = true; +- } +- break; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- } +- } +- if (self->private_impl.f_sof_marker >= 194u) { +- wuffs_jpeg__decoder__save_mcu_blocks(self, v_mx, v_my, a_workbuf); +- } +- if (self->private_impl.f_restarts_remaining > 0u) { +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_impl.f_restarts_remaining -= 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- if (self->private_impl.f_restarts_remaining == 0u) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_jpeg__decoder__skip_past_the_next_restart_marker(self, a_src); +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_mcu_previous_dc_values[0u] = 0u; +- self->private_impl.f_mcu_previous_dc_values[1u] = 0u; +- self->private_impl.f_mcu_previous_dc_values[2u] = 0u; +- self->private_impl.f_mcu_previous_dc_values[3u] = 0u; +- self->private_impl.f_restarts_remaining = self->private_impl.f_restart_interval; +- self->private_impl.f_eob_run = 0u; +- self->private_impl.f_bitstream_bits = 0u; +- self->private_impl.f_bitstream_n_bits = 0u; +- self->private_impl.f_bitstream_ri = 0u; +- self->private_impl.f_bitstream_wi = 0u; +- self->private_impl.f_bitstream_padding = 12345u; +- } +- } +- v_mx += 1u; +- } +- v_my += 1u; +- } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_scan_count, 1u); ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_dqt( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src); + +- ok: +- self->private_impl.p_decode_sos[0] = 0; +- goto exit; +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_dri( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src); + +- goto suspend; +- suspend: +- self->private_impl.p_decode_sos[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_sos[0].v_my = v_my; +- self->private_data.s_decode_sos[0].v_mx = v_mx; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_appn( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint8_t a_marker); + +- goto exit; +- exit: +- return status; +-} ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_sof( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src); + +-// -------- func jpeg.decoder.prepare_scan ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__quantize_dimension( ++ const wuffs_jpeg__decoder* self, ++ uint32_t a_width, ++ uint8_t a_h, ++ uint8_t a_max_incl_h); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_jpeg__decoder__prepare_scan( ++wuffs_jpeg__decoder__do_decode_frame_config( + wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint8_t v_c = 0; +- uint32_t v_i = 0; +- uint32_t v_j = 0; +- uint32_t v_j_max_incl = 0; +- bool v_failed = false; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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_prepare_scan[0]; +- if (coro_susp_point) { +- v_i = self->private_data.s_prepare_scan[0].v_i; +- } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- if ((self->private_impl.f_payload_length < 6u) || (self->private_impl.f_payload_length > 12u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if ((v_c < 1u) || (v_c > 4u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- self->private_impl.f_scan_num_components = ((uint32_t)(v_c)); +- if ((self->private_impl.f_scan_num_components > self->private_impl.f_num_components) || (self->private_impl.f_payload_length != (4u + (2u * self->private_impl.f_scan_num_components)))) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- self->private_impl.f_payload_length = 0u; +- v_i = 0u; +- while (v_i < self->private_impl.f_scan_num_components) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; +- } +- v_j = 0u; +- while (true) { +- if (v_j >= self->private_impl.f_num_components) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- if (v_c == self->private_impl.f_components_c[v_j]) { +- if ( ! self->private_impl.f_seen_dqt[self->private_impl.f_components_tq[v_j]]) { +- status = wuffs_base__make_status(wuffs_jpeg__error__missing_quantization_table); +- goto exit; +- } +- self->private_impl.f_scan_comps_cselector[v_i] = ((uint8_t)(v_j)); +- break; +- } +- v_j += 1u; +- } +- v_j = 0u; +- while (v_j < v_i) { +- if (self->private_impl.f_scan_comps_cselector[v_i] == self->private_impl.f_scan_comps_cselector[v_j]) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- v_j += 1u; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_2 = *iop_a_src++; +- v_c = t_2; +- } +- if (((v_c >> 4u) > 3u) || ((v_c & 15u) > 3u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- self->private_impl.f_scan_comps_td[v_i] = (v_c >> 4u); +- self->private_impl.f_scan_comps_ta[v_i] = (v_c & 15u); +- if (self->private_impl.f_sof_marker == 192u) { +- if ((self->private_impl.f_scan_comps_td[v_i] > 1u) || (self->private_impl.f_scan_comps_ta[v_i] > 1u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- } +- v_i += 1u; +- } +- if (self->private_impl.f_sof_marker < 194u) { +- self->private_data.s_prepare_scan[0].scratch = 3u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (self->private_data.s_prepare_scan[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_prepare_scan[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_prepare_scan[0].scratch; +- self->private_impl.f_scan_ss = 0u; +- self->private_impl.f_scan_se = 63u; +- self->private_impl.f_scan_ah = 0u; +- self->private_impl.f_scan_al = 0u; +- } else { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_3 = *iop_a_src++; +- v_c = t_3; +- } +- if (v_c > 63u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- self->private_impl.f_scan_ss = v_c; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_4 = *iop_a_src++; +- v_c = t_4; +- } +- if ((v_c > 63u) || (v_c < self->private_impl.f_scan_ss)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- self->private_impl.f_scan_se = v_c; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_5 = *iop_a_src++; +- v_c = t_5; +- } +- if (((v_c >> 4u) > 14u) || ((v_c & 15u) > 13u)) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- self->private_impl.f_scan_ah = (v_c >> 4u); +- self->private_impl.f_scan_al = (v_c & 15u); +- if (self->private_impl.f_scan_ah > 0u) { +- if ((self->private_impl.f_scan_ah - 1u) != self->private_impl.f_scan_al) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- } +- if (self->private_impl.f_scan_ss == 0u) { +- if (self->private_impl.f_scan_se != 0u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } else if (self->private_impl.f_scan_ah == 0u) { +- self->private_impl.choosy_decode_mcu = ( +- &wuffs_jpeg__decoder__decode_mcu_progressive_dc_high_bits); +- } else { +- self->private_impl.choosy_decode_mcu = ( +- &wuffs_jpeg__decoder__decode_mcu_progressive_dc_low_bit); +- } +- } else { +- if (self->private_impl.f_scan_num_components != 1u) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } else if (self->private_impl.f_scan_ah == 0u) { +- self->private_impl.choosy_decode_mcu = ( +- &wuffs_jpeg__decoder__decode_mcu_progressive_ac_high_bits); +- } else { +- self->private_impl.choosy_decode_mcu = ( +- &wuffs_jpeg__decoder__decode_mcu_progressive_ac_low_bit); +- } +- } +- } +- v_i = 0u; +- while (v_i < self->private_impl.f_scan_num_components) { +- if ((self->private_impl.f_scan_ss == 0u) && ! self->private_impl.f_seen_dht[(0u | self->private_impl.f_scan_comps_td[v_i])]) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- status = wuffs_jpeg__decoder__use_default_huffman_table(self, (0u | self->private_impl.f_scan_comps_td[v_i])); +- if (status.repr) { +- goto suspend; +- } +- } +- if ((self->private_impl.f_scan_se != 0u) && ! self->private_impl.f_seen_dht[(4u | self->private_impl.f_scan_comps_ta[v_i])]) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- status = wuffs_jpeg__decoder__use_default_huffman_table(self, (4u | self->private_impl.f_scan_comps_ta[v_i])); +- if (status.repr) { +- goto suspend; +- } +- } +- v_j = ((uint32_t)(self->private_impl.f_scan_ss)); +- v_j_max_incl = ((uint32_t)(wuffs_base__u8__min(self->private_impl.f_scan_se, 9u))); +- while (v_j <= v_j_max_incl) { +- self->private_impl.f_block_smoothing_lowest_scan_al[self->private_impl.f_scan_comps_cselector[v_i]][v_j] = self->private_impl.f_scan_al; +- v_j += 1u; +- } +- v_i += 1u; +- } +- if (self->private_impl.f_scan_num_components == 1u) { +- wuffs_jpeg__decoder__calculate_single_component_scan_fields(self); +- } else { +- v_failed = wuffs_jpeg__decoder__calculate_multiple_component_scan_fields(self); +- if (v_failed) { +- status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); +- goto exit; +- } +- } ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- goto ok; +- ok: +- self->private_impl.p_prepare_scan[0] = 0; +- goto exit; +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__do_decode_frame( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); + +- goto suspend; +- suspend: +- self->private_impl.p_prepare_scan[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_prepare_scan[0].v_i = v_i; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_dht( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src); + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++WUFFS_BASE__GENERATED_C_CODE ++static bool ++wuffs_jpeg__decoder__calculate_huff_tables( ++ wuffs_jpeg__decoder* self, ++ uint8_t a_tc4_th, ++ uint32_t a_total_count); + +- return status; +-} ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_sos( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); + +-// -------- func jpeg.decoder.use_default_huffman_table ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__prepare_scan( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status + wuffs_jpeg__decoder__use_default_huffman_table( + wuffs_jpeg__decoder* self, +- uint8_t a_tc4_th) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__slice_u8 v_data = {0}; +- wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_r = &u_r; +- const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- if (a_tc4_th == 0u) { +- v_data = wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_JPEG__DEFAULT_HUFF_TABLE_DC_LUMA), 29); +- } else if (a_tc4_th == 1u) { +- v_data = wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_JPEG__DEFAULT_HUFF_TABLE_DC_CHROMA), 29); +- } else if (a_tc4_th == 4u) { +- v_data = wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_JPEG__DEFAULT_HUFF_TABLE_AC_LUMA), 179); +- } else if (a_tc4_th == 5u) { +- v_data = wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_JPEG__DEFAULT_HUFF_TABLE_AC_CHROMA), 179); +- } else { +- status = wuffs_base__make_status(wuffs_jpeg__error__missing_huffman_table); +- goto exit; +- } +- { +- wuffs_base__io_buffer* o_0_v_r = v_r; +- const uint8_t *o_0_iop_v_r = iop_v_r; +- const uint8_t *o_0_io0_v_r = io0_v_r; +- const uint8_t *o_0_io1_v_r = io1_v_r; +- const uint8_t *o_0_io2_v_r = io2_v_r; +- v_r = wuffs_base__io_reader__set( +- &u_r, +- &iop_v_r, +- &io0_v_r, +- &io1_v_r, +- &io2_v_r, +- v_data, +- 0u); +- self->private_impl.f_payload_length = ((uint32_t)((((uint64_t)(v_data.len)) & 65535u))); +- { +- wuffs_base__status t_0 = wuffs_jpeg__decoder__decode_dht(self, v_r); +- v_status = t_0; +- } +- v_r = o_0_v_r; +- iop_v_r = o_0_iop_v_r; +- io0_v_r = o_0_io0_v_r; +- io1_v_r = o_0_io1_v_r; +- io2_v_r = o_0_io2_v_r; +- } +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- +- ok: +- goto exit; +- exit: +- return status; +-} +- +-// -------- func jpeg.decoder.calculate_single_component_scan_fields ++ uint8_t a_tc4_th); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct + wuffs_jpeg__decoder__calculate_single_component_scan_fields( +- wuffs_jpeg__decoder* self) { +- uint8_t v_csel = 0; +- +- self->private_impl.f_scan_comps_bx_offset[0u] = 0u; +- self->private_impl.f_scan_comps_by_offset[0u] = 0u; +- self->private_impl.f_mcu_num_blocks = 1u; +- self->private_impl.f_mcu_blocks_sselector[0u] = 0u; +- v_csel = self->private_impl.f_scan_comps_cselector[0u]; +- self->private_impl.f_mcu_blocks_offset[0u] = self->private_impl.f_components_workbuf_offsets[v_csel]; +- self->private_impl.f_mcu_blocks_mx_mul[0u] = 8u; +- self->private_impl.f_mcu_blocks_my_mul[0u] = (8u * self->private_impl.f_components_workbuf_widths[v_csel]); +- self->private_impl.f_mcu_blocks_dc_hselector[0u] = (0u | self->private_impl.f_scan_comps_td[0u]); +- self->private_impl.f_mcu_blocks_ac_hselector[0u] = (4u | self->private_impl.f_scan_comps_ta[0u]); +- self->private_impl.f_scan_width_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_width, self->private_impl.f_components_h[v_csel], self->private_impl.f_max_incl_components_h); +- self->private_impl.f_scan_height_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_height, self->private_impl.f_components_v[v_csel], self->private_impl.f_max_incl_components_v); +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func jpeg.decoder.calculate_multiple_component_scan_fields ++ wuffs_jpeg__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + static bool + wuffs_jpeg__decoder__calculate_multiple_component_scan_fields( +- wuffs_jpeg__decoder* self) { +- uint32_t v_i = 0; +- uint32_t v_h = 0; +- uint32_t v_v = 0; +- uint32_t v_hv = 0; +- uint32_t v_total_hv = 0; +- uint32_t v_b = 0; +- uint32_t v_bx_offset = 0; +- uint32_t v_by_offset = 0; +- uint8_t v_ssel = 0; +- uint8_t v_csel = 0; +- +- v_total_hv = 0u; +- v_i = 0u; +- v_b = 0u; +- v_bx_offset = 0u; +- v_by_offset = 0u; +- while (v_i < self->private_impl.f_scan_num_components) { +- v_h = ((uint32_t)(self->private_impl.f_components_h[self->private_impl.f_scan_comps_cselector[v_i]])); +- v_v = ((uint32_t)(self->private_impl.f_components_v[self->private_impl.f_scan_comps_cselector[v_i]])); +- v_hv = (((uint32_t)(self->private_impl.f_components_h[self->private_impl.f_scan_comps_cselector[v_i]])) * ((uint32_t)(self->private_impl.f_components_v[self->private_impl.f_scan_comps_cselector[v_i]]))); +- v_total_hv += v_hv; +- while (v_hv > 0u) { +- self->private_impl.f_scan_comps_bx_offset[(v_b & 15u)] = ((uint8_t)((v_bx_offset & 3u))); +- self->private_impl.f_scan_comps_by_offset[(v_b & 15u)] = ((uint8_t)((v_by_offset & 3u))); +- self->private_impl.f_mcu_blocks_sselector[(v_b & 15u)] = ((uint8_t)(v_i)); +- v_b += 1u; +- v_bx_offset += 1u; +- if (v_bx_offset == v_h) { +- v_bx_offset = 0u; +- v_by_offset += 1u; +- if (v_by_offset == v_v) { +- v_by_offset = 0u; +- } +- } +- v_hv -= 1u; +- } +- v_i += 1u; +- } +- if (v_total_hv > 10u) { +- return true; +- } +- self->private_impl.f_mcu_num_blocks = v_total_hv; +- v_b = 0u; +- while (v_b < self->private_impl.f_mcu_num_blocks) { +- v_ssel = self->private_impl.f_mcu_blocks_sselector[v_b]; +- v_csel = self->private_impl.f_scan_comps_cselector[v_ssel]; +- self->private_impl.f_mcu_blocks_offset[v_b] = (self->private_impl.f_components_workbuf_offsets[v_csel] + (8u * ((uint64_t)(self->private_impl.f_scan_comps_bx_offset[v_b]))) + (8u * ((uint64_t)(self->private_impl.f_scan_comps_by_offset[v_b])) * ((uint64_t)(self->private_impl.f_components_workbuf_widths[v_csel])))); +- self->private_impl.f_mcu_blocks_mx_mul[v_b] = (8u * ((uint32_t)(self->private_impl.f_components_h[v_csel]))); +- self->private_impl.f_mcu_blocks_my_mul[v_b] = (8u * ((uint32_t)(self->private_impl.f_components_v[v_csel])) * self->private_impl.f_components_workbuf_widths[v_csel]); +- self->private_impl.f_mcu_blocks_dc_hselector[v_b] = (0u | self->private_impl.f_scan_comps_td[v_ssel]); +- self->private_impl.f_mcu_blocks_ac_hselector[v_b] = (4u | self->private_impl.f_scan_comps_ta[v_ssel]); +- v_b += 1u; +- } +- self->private_impl.f_scan_width_in_mcus = self->private_impl.f_width_in_mcus; +- self->private_impl.f_scan_height_in_mcus = self->private_impl.f_height_in_mcus; +- return false; +-} +- +-// -------- func jpeg.decoder.fill_bitstream ++ wuffs_jpeg__decoder* self); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct + wuffs_jpeg__decoder__fill_bitstream( + wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src) { +- uint32_t v_wi = 0; +- uint8_t v_c = 0; +- uint32_t v_new_wi = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } +- +- if (self->private_impl.f_bitstream_ri <= 0u) { +- } else if (self->private_impl.f_bitstream_ri >= self->private_impl.f_bitstream_wi) { +- self->private_impl.f_bitstream_ri = 0u; +- self->private_impl.f_bitstream_wi = 0u; +- } else { +- v_wi = (self->private_impl.f_bitstream_wi - self->private_impl.f_bitstream_ri); +- wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_bitstream_buffer, 2048), wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, +- self->private_impl.f_bitstream_ri, +- self->private_impl.f_bitstream_wi)); +- self->private_impl.f_bitstream_ri = 0u; +- self->private_impl.f_bitstream_wi = v_wi; +- } +- v_wi = self->private_impl.f_bitstream_wi; +- while ((v_wi < 2048u) && (((uint64_t)(io2_a_src - iop_a_src)) > 0u)) { +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if (v_c < 255u) { +- self->private_data.f_bitstream_buffer[v_wi] = v_c; +- v_wi += 1u; +- iop_a_src += 1u; +- continue; +- } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 1u) { +- break; +- } else if ((wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8u) > 0u) { +- break; +- } else { +- self->private_data.f_bitstream_buffer[v_wi] = 255u; +- v_wi += 1u; +- iop_a_src += 2u; +- } +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) > 1u) { +- if ((wuffs_base__peek_u8be__no_bounds_check(iop_a_src) >= 255u) && ((wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8u) > 0u)) { +- v_new_wi = (wuffs_base__u32__min(v_wi, 1784u) + 264u); +- v_new_wi = wuffs_base__u32__min(v_new_wi, (v_wi + self->private_impl.f_bitstream_padding)); +- if (v_wi < v_new_wi) { +- wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_bitstream_padding, (v_new_wi - v_wi)); +- wuffs_base__bulk_memset(&self->private_data.f_bitstream_buffer[v_wi], (v_new_wi - v_wi), 0u); +- v_wi = v_new_wi; +- } +- } +- } +- self->private_impl.f_bitstream_wi = v_wi; +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func jpeg.decoder.load_mcu_blocks_for_single_component ++ wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +@@ -44752,9 +44689,7 @@ wuffs_jpeg__decoder__load_mcu_blocks_for_single_component( + uint32_t a_mx, + uint32_t a_my, + wuffs_base__slice_u8 a_workbuf, +- uint32_t a_csel) { +- return (*self->private_impl.choosy_load_mcu_blocks_for_single_component)(self, a_mx, a_my, a_workbuf, a_csel); +-} ++ uint32_t a_csel); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +@@ -44763,19 +44698,7 @@ wuffs_jpeg__decoder__load_mcu_blocks_for_single_component__choosy_default( + uint32_t a_mx, + uint32_t a_my, + wuffs_base__slice_u8 a_workbuf, +- uint32_t a_csel) { +- uint64_t v_stride16 = 0; +- uint64_t v_offset = 0; +- +- v_stride16 = ((uint64_t)((self->private_impl.f_components_workbuf_widths[a_csel] * 16u))); +- v_offset = (self->private_impl.f_components_workbuf_offsets[(a_csel | 4u)] + (((uint64_t)(a_mx)) * 128u) + (((uint64_t)(a_my)) * v_stride16)); +- if (v_offset <= ((uint64_t)(a_workbuf.len))) { +- wuffs_base__bulk_load_host_endian(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); +- } +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func jpeg.decoder.load_mcu_blocks ++ uint32_t a_csel); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +@@ -44783,34 +44706,7 @@ wuffs_jpeg__decoder__load_mcu_blocks( + wuffs_jpeg__decoder* self, + uint32_t a_mx, + uint32_t a_my, +- wuffs_base__slice_u8 a_workbuf) { +- uint32_t v_b = 0; +- uint8_t v_csel = 0; +- uint64_t v_h = 0; +- uint64_t v_v = 0; +- uint64_t v_stride16 = 0; +- uint64_t v_offset = 0; +- +- v_h = 1u; +- v_v = 1u; +- v_b = 0u; +- while (v_b < self->private_impl.f_mcu_num_blocks) { +- v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[v_b]]; +- if (self->private_impl.f_scan_num_components > 1u) { +- v_h = ((uint64_t)(self->private_impl.f_components_h[v_csel])); +- v_v = ((uint64_t)(self->private_impl.f_components_v[v_csel])); +- } +- v_stride16 = ((uint64_t)((self->private_impl.f_components_workbuf_widths[v_csel] * 16u))); +- v_offset = (self->private_impl.f_components_workbuf_offsets[(v_csel | 4u)] + (((v_h * ((uint64_t)(a_mx))) + ((uint64_t)(self->private_impl.f_scan_comps_bx_offset[v_b]))) * 128u) + (((v_v * ((uint64_t)(a_my))) + ((uint64_t)(self->private_impl.f_scan_comps_by_offset[v_b]))) * v_stride16)); +- if (v_offset <= ((uint64_t)(a_workbuf.len))) { +- wuffs_base__bulk_load_host_endian(&self->private_data.f_mcu_blocks[v_b], 1u * (size_t)128u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); +- } +- v_b += 1u; +- } +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func jpeg.decoder.save_mcu_blocks ++ wuffs_base__slice_u8 a_workbuf); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +@@ -44818,4983 +44714,17911 @@ wuffs_jpeg__decoder__save_mcu_blocks( + wuffs_jpeg__decoder* self, + uint32_t a_mx, + uint32_t a_my, +- wuffs_base__slice_u8 a_workbuf) { +- uint32_t v_b = 0; +- uint8_t v_csel = 0; +- uint64_t v_h = 0; +- uint64_t v_v = 0; +- uint64_t v_stride16 = 0; +- uint64_t v_offset = 0; +- +- v_h = 1u; +- v_v = 1u; +- v_b = 0u; +- while (v_b < self->private_impl.f_mcu_num_blocks) { +- v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[v_b]]; +- if (self->private_impl.f_scan_num_components > 1u) { +- v_h = ((uint64_t)(self->private_impl.f_components_h[v_csel])); +- v_v = ((uint64_t)(self->private_impl.f_components_v[v_csel])); +- } +- v_stride16 = ((uint64_t)((self->private_impl.f_components_workbuf_widths[v_csel] * 16u))); +- v_offset = (self->private_impl.f_components_workbuf_offsets[(v_csel | 4u)] + (((v_h * ((uint64_t)(a_mx))) + ((uint64_t)(self->private_impl.f_scan_comps_bx_offset[v_b]))) * 128u) + (((v_v * ((uint64_t)(a_my))) + ((uint64_t)(self->private_impl.f_scan_comps_by_offset[v_b]))) * v_stride16)); +- if (v_offset <= ((uint64_t)(a_workbuf.len))) { +- wuffs_base__bulk_save_host_endian(&self->private_data.f_mcu_blocks[v_b], 1u * (size_t)128u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); +- } +- v_b += 1u; +- } +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func jpeg.decoder.skip_past_the_next_restart_marker ++ wuffs_base__slice_u8 a_workbuf); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status + wuffs_jpeg__decoder__skip_past_the_next_restart_marker( + wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint8_t v_c = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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_skip_past_the_next_restart_marker[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- continue; +- } else if (wuffs_base__peek_u8be__no_bounds_check(iop_a_src) < 255u) { +- iop_a_src += 1u; +- continue; +- } +- v_c = ((uint8_t)((wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8u))); +- if (v_c < 192u) { +- iop_a_src += 2u; +- continue; +- } else if ((v_c < 208u) || (215u < v_c)) { +- break; +- } +- v_c &= 7u; +- if ((self->private_impl.f_next_restart_marker == ((v_c + 1u) & 7u)) || (self->private_impl.f_next_restart_marker == ((v_c + 2u) & 7u))) { +- break; +- } else if ((self->private_impl.f_next_restart_marker == ((v_c + 7u) & 7u)) || (self->private_impl.f_next_restart_marker == ((v_c + 6u) & 7u))) { +- iop_a_src += 2u; +- continue; +- } else { +- iop_a_src += 2u; +- break; +- } +- } +- self->private_impl.f_next_restart_marker = (((uint8_t)(self->private_impl.f_next_restart_marker + 1u)) & 7u); +- +- ok: +- self->private_impl.p_skip_past_the_next_restart_marker[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_skip_past_the_next_restart_marker[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func jpeg.decoder.apply_progressive_idct ++ wuffs_base__io_buffer* a_src); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct + wuffs_jpeg__decoder__apply_progressive_idct( + wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf) { +- uint32_t v_csel = 0; +- bool v_block_smoothing_applicable = false; +- uint32_t v_scan_width_in_mcus = 0; +- uint32_t v_scan_height_in_mcus = 0; +- uint32_t v_mcu_blocks_mx_mul_0 = 0; +- uint32_t v_mcu_blocks_my_mul_0 = 0; +- uint32_t v_my = 0; +- uint32_t v_mx = 0; +- uint64_t v_stride = 0; +- uint64_t v_offset = 0; +- uint8_t v_stashed_mcu_blocks_0[128] = {0}; +- +- wuffs_base__bulk_save_host_endian(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, wuffs_base__make_slice_u8(v_stashed_mcu_blocks_0, 128)); +- v_block_smoothing_applicable = true; +- v_csel = 0u; +- while (v_csel < self->private_impl.f_num_components) { +- if ((self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][0u] >= 16u) || wuffs_jpeg__decoder__top_left_quants_has_zero(self, ((uint32_t)(self->private_impl.f_components_tq[v_csel])))) { +- v_block_smoothing_applicable = false; +- } +- v_csel += 1u; +- } +- v_csel = 0u; +- while (v_csel < self->private_impl.f_num_components) { +- v_scan_width_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_width, self->private_impl.f_components_h[v_csel], self->private_impl.f_max_incl_components_h); +- v_scan_height_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_height, self->private_impl.f_components_v[v_csel], self->private_impl.f_max_incl_components_v); +- v_mcu_blocks_mx_mul_0 = 8u; +- v_mcu_blocks_my_mul_0 = (8u * self->private_impl.f_components_workbuf_widths[v_csel]); +- if (v_block_smoothing_applicable && (0u != (self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][1u] | +- self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][2u] | +- self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][3u] | +- self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][4u] | +- self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][5u] | +- self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][6u] | +- self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][8u] | +- self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][8u] | +- self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][9u]))) { +- self->private_impl.choosy_load_mcu_blocks_for_single_component = ( +- &wuffs_jpeg__decoder__load_mcu_blocks_for_single_component_smooth); +- self->private_impl.f_block_smoothing_mx_max_incl = wuffs_base__u32__sat_sub(v_scan_width_in_mcus, 1u); +- self->private_impl.f_block_smoothing_my_max_incl = wuffs_base__u32__sat_sub(v_scan_height_in_mcus, 1u); +- } else { +- self->private_impl.choosy_load_mcu_blocks_for_single_component = ( +- &wuffs_jpeg__decoder__load_mcu_blocks_for_single_component__choosy_default); +- } +- v_my = 0u; +- while (v_my < v_scan_height_in_mcus) { +- v_mx = 0u; +- while (v_mx < v_scan_width_in_mcus) { +- wuffs_jpeg__decoder__load_mcu_blocks_for_single_component(self, +- v_mx, +- v_my, +- a_workbuf, +- v_csel); +- v_stride = ((uint64_t)(self->private_impl.f_components_workbuf_widths[v_csel])); +- v_offset = (self->private_impl.f_components_workbuf_offsets[v_csel] + (((uint64_t)(v_mcu_blocks_mx_mul_0)) * ((uint64_t)(v_mx))) + (((uint64_t)(v_mcu_blocks_my_mul_0)) * ((uint64_t)(v_my)))); +- if (v_offset <= ((uint64_t)(a_workbuf.len))) { +- wuffs_jpeg__decoder__decode_idct(self, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset), v_stride, ((uint32_t)(self->private_impl.f_components_tq[v_csel]))); +- } +- v_mx += 1u; +- } +- v_my += 1u; +- } +- v_csel += 1u; +- } +- wuffs_base__bulk_load_host_endian(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, wuffs_base__make_slice_u8(v_stashed_mcu_blocks_0, 128)); +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func jpeg.decoder.swizzle_gray ++ wuffs_base__slice_u8 a_workbuf); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status + wuffs_jpeg__decoder__swizzle_gray( + wuffs_jpeg__decoder* self, + wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf) { +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint32_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_length = 0; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint32_t v_y = 0; +- uint64_t v_stride = 0; +- +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); +- } +- v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); +- v_dst_length = ((uint64_t)((v_dst_bytes_per_pixel * self->private_impl.f_width))); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- v_y = 0u; +- while (v_y < self->private_impl.f_height) { +- v_dst = wuffs_base__table_u8__row_u32(v_tab, v_y); +- if (v_dst_length < ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_length); +- } +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), a_workbuf); +- v_stride = ((uint64_t)(self->private_impl.f_components_workbuf_widths[0u])); +- if (v_stride <= ((uint64_t)(a_workbuf.len))) { +- a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, v_stride); +- } else { +- a_workbuf = wuffs_base__utility__empty_slice_u8(); +- } +- v_y += 1u; +- } +- return wuffs_base__make_status(NULL); +-} +- +-// -------- func jpeg.decoder.swizzle_colorful ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_x0, ++ uint32_t a_x1, ++ uint32_t a_y0, ++ uint32_t a_y1, ++ uint64_t a_stride); + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status + wuffs_jpeg__decoder__swizzle_colorful( + wuffs_jpeg__decoder* self, + wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf) { +- wuffs_base__slice_u8 v_src0 = {0}; +- wuffs_base__slice_u8 v_src1 = {0}; +- wuffs_base__slice_u8 v_src2 = {0}; +- wuffs_base__slice_u8 v_src3 = {0}; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- if ((self->private_impl.f_components_workbuf_offsets[0u] <= self->private_impl.f_components_workbuf_offsets[1u]) && (self->private_impl.f_components_workbuf_offsets[1u] <= ((uint64_t)(a_workbuf.len)))) { +- v_src0 = wuffs_base__slice_u8__subslice_ij(a_workbuf, +- self->private_impl.f_components_workbuf_offsets[0u], +- self->private_impl.f_components_workbuf_offsets[1u]); +- } +- if ((self->private_impl.f_components_workbuf_offsets[1u] <= self->private_impl.f_components_workbuf_offsets[2u]) && (self->private_impl.f_components_workbuf_offsets[2u] <= ((uint64_t)(a_workbuf.len)))) { +- v_src1 = wuffs_base__slice_u8__subslice_ij(a_workbuf, +- self->private_impl.f_components_workbuf_offsets[1u], +- self->private_impl.f_components_workbuf_offsets[2u]); +- } +- if ((self->private_impl.f_components_workbuf_offsets[2u] <= self->private_impl.f_components_workbuf_offsets[3u]) && (self->private_impl.f_components_workbuf_offsets[3u] <= ((uint64_t)(a_workbuf.len)))) { +- v_src2 = wuffs_base__slice_u8__subslice_ij(a_workbuf, +- self->private_impl.f_components_workbuf_offsets[2u], +- self->private_impl.f_components_workbuf_offsets[3u]); +- } +- if ((self->private_impl.f_components_workbuf_offsets[3u] <= self->private_impl.f_components_workbuf_offsets[4u]) && (self->private_impl.f_components_workbuf_offsets[4u] <= ((uint64_t)(a_workbuf.len)))) { +- v_src3 = wuffs_base__slice_u8__subslice_ij(a_workbuf, +- self->private_impl.f_components_workbuf_offsets[3u], +- self->private_impl.f_components_workbuf_offsets[4u]); +- } +- v_status = wuffs_base__pixel_swizzler__swizzle_ycck(&self->private_impl.f_swizzler, +- a_dst, +- wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), +- self->private_impl.f_width, +- self->private_impl.f_height, +- v_src0, +- v_src1, +- v_src2, +- v_src3, +- self->private_impl.f_components_workbuf_widths[0u], +- self->private_impl.f_components_workbuf_widths[1u], +- self->private_impl.f_components_workbuf_widths[2u], +- self->private_impl.f_components_workbuf_widths[3u], +- self->private_impl.f_components_workbuf_heights[0u], +- self->private_impl.f_components_workbuf_heights[1u], +- self->private_impl.f_components_workbuf_heights[2u], +- self->private_impl.f_components_workbuf_heights[3u], +- self->private_impl.f_components_workbuf_widths[0u], +- self->private_impl.f_components_workbuf_widths[1u], +- self->private_impl.f_components_workbuf_widths[2u], +- self->private_impl.f_components_workbuf_widths[3u], +- self->private_impl.f_components_h[0u], +- self->private_impl.f_components_h[1u], +- self->private_impl.f_components_h[2u], +- self->private_impl.f_components_h[3u], +- self->private_impl.f_components_v[0u], +- self->private_impl.f_components_v[1u], +- self->private_impl.f_components_v[2u], +- self->private_impl.f_components_v[3u], +- self->private_impl.f_is_rgb_or_cmyk, +- true, +- wuffs_base__make_slice_u8(self->private_data.f_swizzle_ycck_scratch_buffer_2k, 2048)); +- return wuffs_base__status__ensure_not_a_suspension(v_status); +-} +- +-// -------- func jpeg.decoder.frame_dirty_rect ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_x0, ++ uint32_t a_x1, ++ uint32_t a_y0, ++ uint32_t a_y1); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_jpeg__decoder__frame_dirty_rect( +- const wuffs_jpeg__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- +- return wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height); +-} +- +-// -------- func jpeg.decoder.num_animation_loops ++static bool ++wuffs_jpeg__decoder__top_left_quants_has_zero( ++ const wuffs_jpeg__decoder* self, ++ uint32_t a_q); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_jpeg__decoder__num_animation_loops( +- const wuffs_jpeg__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func jpeg.decoder.num_decoded_frame_configs ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__load_mcu_blocks_for_single_component_smooth( ++ wuffs_jpeg__decoder* self, ++ uint32_t a_mx, ++ uint32_t a_my, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_csel); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_jpeg__decoder__num_decoded_frame_configs( +- const wuffs_jpeg__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- if (self->private_impl.f_call_sequence > 32u) { +- return 1u; +- } +- return 0u; +-} +- +-// -------- func jpeg.decoder.num_decoded_frames ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_jpeg__decoder__num_decoded_frames( +- const wuffs_jpeg__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- if (self->private_impl.f_call_sequence > 64u) { +- return 1u; +- } +- return 0u; +-} +- +-// -------- func jpeg.decoder.restart_frame ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu__choosy_default( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_jpeg__decoder__restart_frame( ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu_progressive_ac_high_bits( + wuffs_jpeg__decoder* self, +- uint64_t a_index, +- uint64_t a_io_position) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- +- uint32_t v_i = 0; +- uint32_t v_j = 0; ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my); + +- if (self->private_impl.f_call_sequence < 32u) { +- return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- } +- if (a_index != 0u) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- self->private_impl.f_call_sequence = 40u; +- self->private_impl.f_bitstream_is_closed = false; +- self->private_impl.f_frame_config_io_position = a_io_position; +- self->private_impl.f_scan_count = 0u; +- self->private_impl.f_restart_interval = self->private_impl.f_saved_restart_interval; +- v_i = 0u; +- while (v_i < 4u) { +- self->private_impl.f_seen_dqt[v_i] = self->private_impl.f_saved_seen_dqt[v_i]; +- v_j = 0u; +- while (v_j < 64u) { +- self->private_impl.f_quant_tables[v_i][v_j] = self->private_impl.f_saved_quant_tables[v_i][v_j]; +- v_j += 1u; +- } +- v_i += 1u; +- } +- v_i = 0u; +- while (v_i < 4u) { +- v_j = 0u; +- while (v_j < 10u) { +- self->private_impl.f_block_smoothing_lowest_scan_al[v_i][v_j] = 16u; +- v_j += 1u; +- } +- v_i += 1u; +- } +- v_i = 0u; +- while (v_i < 8u) { +- self->private_impl.f_seen_dht[v_i] = false; +- v_i += 1u; +- } +- return wuffs_base__make_status(NULL); +-} ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu_progressive_ac_low_bit( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my); + +-// -------- func jpeg.decoder.set_report_metadata ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu_progressive_dc_high_bits( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my); + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_jpeg__decoder__set_report_metadata( ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu_progressive_dc_low_bit( + wuffs_jpeg__decoder* self, +- uint32_t a_fourcc, +- bool a_report) { +- return wuffs_base__make_empty_struct(); +-} ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my); + +-// -------- func jpeg.decoder.tell_me_more ++// ---------------- VTables + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_jpeg__decoder__tell_me_more( ++const wuffs_base__image_decoder__func_ptrs ++wuffs_jpeg__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_jpeg__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_jpeg__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_jpeg__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_jpeg__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_jpeg__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_jpeg__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_jpeg__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_jpeg__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_jpeg__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_jpeg__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_jpeg__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_jpeg__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_jpeg__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_jpeg__decoder__initialize( + wuffs_jpeg__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); + } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); + } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 4)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } + } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); + +- status = wuffs_base__make_status(wuffs_base__error__no_more_information); +- goto exit; ++ self->private_impl.choosy_decode_idct = &wuffs_jpeg__decoder__decode_idct__choosy_default; ++ self->private_impl.choosy_load_mcu_blocks_for_single_component = &wuffs_jpeg__decoder__load_mcu_blocks_for_single_component__choosy_default; ++ self->private_impl.choosy_decode_mcu = &wuffs_jpeg__decoder__decode_mcu__choosy_default; + +- goto ok; +- ok: +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_jpeg__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); + } + +-// -------- func jpeg.decoder.history_retain_length +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_jpeg__decoder__history_retain_length( +- const wuffs_jpeg__decoder* self) { +- if (!self) { +- return 0; ++wuffs_jpeg__decoder* ++wuffs_jpeg__decoder__alloc(void) { ++ wuffs_jpeg__decoder* x = ++ (wuffs_jpeg__decoder*)(calloc(1, sizeof(wuffs_jpeg__decoder))); ++ if (!x) { ++ return NULL; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ if (wuffs_jpeg__decoder__initialize( ++ x, sizeof(wuffs_jpeg__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; + } ++ return x; ++} + +- return 0u; ++size_t ++sizeof__wuffs_jpeg__decoder(void) { ++ return sizeof(wuffs_jpeg__decoder); + } + +-// -------- func jpeg.decoder.workbuf_len ++// ---------------- Function Implementations ++ ++// -------- func jpeg.decoder.decode_idct + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_jpeg__decoder__workbuf_len( +- const wuffs_jpeg__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- +- return wuffs_base__utility__make_range_ii_u64(self->private_impl.f_components_workbuf_offsets[8u], self->private_impl.f_components_workbuf_offsets[8u]); +-} +- +-// -------- func jpeg.decoder.top_left_quants_has_zero +- +-WUFFS_BASE__GENERATED_C_CODE +-static bool +-wuffs_jpeg__decoder__top_left_quants_has_zero( +- const wuffs_jpeg__decoder* self, ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__decode_idct( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__slice_u8 a_dst_buffer, ++ uint64_t a_dst_stride, + uint32_t a_q) { +- return ((self->private_impl.f_quant_tables[a_q][0u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][1u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][2u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][3u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][8u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][9u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][10u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][16u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][17u] == 0u) || +- (self->private_impl.f_quant_tables[a_q][24u] == 0u)); ++ return (*self->private_impl.choosy_decode_idct)(self, a_dst_buffer, a_dst_stride, a_q); + } + +-// -------- func jpeg.decoder.load_mcu_blocks_for_single_component_smooth +- + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_jpeg__decoder__load_mcu_blocks_for_single_component_smooth( ++wuffs_jpeg__decoder__decode_idct__choosy_default( + wuffs_jpeg__decoder* self, +- uint32_t a_mx, +- uint32_t a_my, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_csel) { +- uint64_t v_stride16 = 0; +- uint64_t v_offset = 0; +- uint32_t v_dx = 0; +- uint32_t v_dy = 0; +- uint32_t v_mx = 0; +- uint32_t v_my = 0; +- uint8_t v_q = 0; +- uint32_t v_q_00 = 0; +- uint32_t v_q_xy = 0; +- uint8_t v_al = 0; +- uint32_t v_scratch = 0; +- uint32_t v_limit = 0; ++ wuffs_base__slice_u8 a_dst_buffer, ++ uint64_t a_dst_stride, ++ uint32_t a_q) { ++ uint32_t v_bq0 = 0; ++ uint32_t v_bq2 = 0; ++ uint32_t v_bq4 = 0; ++ uint32_t v_bq6 = 0; ++ uint32_t v_ca = 0; ++ uint32_t v_cb2 = 0; ++ uint32_t v_cb6 = 0; ++ uint32_t v_ccp = 0; ++ uint32_t v_ccm = 0; ++ uint32_t v_cd0 = 0; ++ uint32_t v_cd1 = 0; ++ uint32_t v_cd2 = 0; ++ uint32_t v_cd3 = 0; ++ uint32_t v_bq1 = 0; ++ uint32_t v_bq3 = 0; ++ uint32_t v_bq5 = 0; ++ uint32_t v_bq7 = 0; ++ uint32_t v_ci51 = 0; ++ uint32_t v_ci53 = 0; ++ uint32_t v_ci71 = 0; ++ uint32_t v_ci73 = 0; ++ uint32_t v_cj = 0; ++ uint32_t v_ck1 = 0; ++ uint32_t v_ck3 = 0; ++ uint32_t v_ck5 = 0; ++ uint32_t v_ck7 = 0; ++ uint32_t v_cl51 = 0; ++ uint32_t v_cl73 = 0; ++ uint32_t v_in0 = 0; ++ uint32_t v_in2 = 0; ++ uint32_t v_in4 = 0; ++ uint32_t v_in6 = 0; ++ uint32_t v_ra = 0; ++ uint32_t v_rb2 = 0; ++ uint32_t v_rb6 = 0; ++ uint32_t v_rcp = 0; ++ uint32_t v_rcm = 0; ++ uint32_t v_rd0 = 0; ++ uint32_t v_rd1 = 0; ++ uint32_t v_rd2 = 0; ++ uint32_t v_rd3 = 0; ++ uint32_t v_in1 = 0; ++ uint32_t v_in3 = 0; ++ uint32_t v_in5 = 0; ++ uint32_t v_in7 = 0; ++ uint32_t v_ri51 = 0; ++ uint32_t v_ri53 = 0; ++ uint32_t v_ri71 = 0; ++ uint32_t v_ri73 = 0; ++ uint32_t v_rj = 0; ++ uint32_t v_rk1 = 0; ++ uint32_t v_rk3 = 0; ++ uint32_t v_rk5 = 0; ++ uint32_t v_rk7 = 0; ++ uint32_t v_rl51 = 0; ++ uint32_t v_rl73 = 0; ++ uint32_t v_intermediate[64] = {0}; + +- v_stride16 = ((uint64_t)((self->private_impl.f_components_workbuf_widths[a_csel] * 16u))); +- v_offset = (self->private_impl.f_components_workbuf_offsets[(a_csel | 4u)] + (((uint64_t)(a_mx)) * 128u) + (((uint64_t)(a_my)) * v_stride16)); +- if (v_offset <= ((uint64_t)(a_workbuf.len))) { +- wuffs_base__bulk_load_host_endian(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); ++ if (8u > a_dst_stride) { ++ return wuffs_base__make_empty_struct(); + } +- v_dy = 0u; +- while (v_dy < 5u) { +- v_my = wuffs_base__u32__min(self->private_impl.f_block_smoothing_my_max_incl, wuffs_base__u32__sat_sub((a_my + v_dy), 2u)); +- v_dx = 0u; +- while (v_dx < 5u) { +- v_mx = wuffs_base__u32__min(self->private_impl.f_block_smoothing_mx_max_incl, wuffs_base__u32__sat_sub((a_mx + v_dx), 2u)); +- v_offset = (self->private_impl.f_components_workbuf_offsets[(a_csel | 4u)] + (((uint64_t)(v_mx)) * 128u) + (((uint64_t)(v_my)) * v_stride16)); +- if (v_offset <= ((uint64_t)(a_workbuf.len))) { +- wuffs_base__bulk_load_host_endian(&self->private_impl.f_block_smoothing_dc_values[v_dy][v_dx], 1u * (size_t)2u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); +- } +- v_dx += 1u; +- } +- v_dy += 1u; ++ if (0u == (self->private_data.f_mcu_blocks[0u][8u] | ++ self->private_data.f_mcu_blocks[0u][16u] | ++ self->private_data.f_mcu_blocks[0u][24u] | ++ self->private_data.f_mcu_blocks[0u][32u] | ++ self->private_data.f_mcu_blocks[0u][40u] | ++ self->private_data.f_mcu_blocks[0u][48u] | ++ self->private_data.f_mcu_blocks[0u][56u])) { ++ v_intermediate[0u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][0u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][0u])))) << 2u)); ++ v_intermediate[8u] = v_intermediate[0u]; ++ v_intermediate[16u] = v_intermediate[0u]; ++ v_intermediate[24u] = v_intermediate[0u]; ++ v_intermediate[32u] = v_intermediate[0u]; ++ v_intermediate[40u] = v_intermediate[0u]; ++ v_intermediate[48u] = v_intermediate[0u]; ++ v_intermediate[56u] = v_intermediate[0u]; ++ } else { ++ v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][16u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][16u])))); ++ v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][48u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][48u])))); ++ v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); ++ v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); ++ v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); ++ v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][0u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][0u])))); ++ v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][32u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][32u])))); ++ v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); ++ v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); ++ v_cd0 = ((uint32_t)(v_ccp + v_cb2)); ++ v_cd1 = ((uint32_t)(v_ccm + v_cb6)); ++ v_cd2 = ((uint32_t)(v_ccm - v_cb6)); ++ v_cd3 = ((uint32_t)(v_ccp - v_cb2)); ++ v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][8u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][8u])))); ++ v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][24u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][24u])))); ++ v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][40u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][40u])))); ++ v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][56u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][56u])))); ++ v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); ++ v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); ++ v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); ++ v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); ++ v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); ++ v_ck1 = ((uint32_t)(v_bq1 * 12299u)); ++ v_ck3 = ((uint32_t)(v_bq3 * 25172u)); ++ v_ck5 = ((uint32_t)(v_bq5 * 16819u)); ++ v_ck7 = ((uint32_t)(v_bq7 * 2446u)); ++ v_ci51 *= 4294964100u; ++ v_ci53 *= 4294946301u; ++ v_ci71 *= 4294959923u; ++ v_ci73 *= 4294951227u; ++ v_cl51 = ((uint32_t)(v_ci51 + v_cj)); ++ v_cl73 = ((uint32_t)(v_ci73 + v_cj)); ++ v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); ++ v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); ++ v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); ++ v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); ++ v_intermediate[0u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); ++ v_intermediate[56u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); ++ v_intermediate[8u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); ++ v_intermediate[48u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); ++ v_intermediate[16u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); ++ v_intermediate[40u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); ++ v_intermediate[24u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); ++ v_intermediate[32u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); + } +- v_q = self->private_impl.f_components_tq[a_csel]; +- v_q_00 = ((uint32_t)(self->private_impl.f_quant_tables[v_q][0u])); +- if (v_q_00 <= 0u) { +- return wuffs_base__make_empty_struct(); ++ if (0u == (self->private_data.f_mcu_blocks[0u][9u] | ++ self->private_data.f_mcu_blocks[0u][17u] | ++ self->private_data.f_mcu_blocks[0u][25u] | ++ self->private_data.f_mcu_blocks[0u][33u] | ++ self->private_data.f_mcu_blocks[0u][41u] | ++ self->private_data.f_mcu_blocks[0u][49u] | ++ self->private_data.f_mcu_blocks[0u][57u])) { ++ v_intermediate[1u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][1u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][1u])))) << 2u)); ++ v_intermediate[9u] = v_intermediate[1u]; ++ v_intermediate[17u] = v_intermediate[1u]; ++ v_intermediate[25u] = v_intermediate[1u]; ++ v_intermediate[33u] = v_intermediate[1u]; ++ v_intermediate[41u] = v_intermediate[1u]; ++ v_intermediate[49u] = v_intermediate[1u]; ++ v_intermediate[57u] = v_intermediate[1u]; ++ } else { ++ v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][17u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][17u])))); ++ v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][49u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][49u])))); ++ v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); ++ v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); ++ v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); ++ v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][1u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][1u])))); ++ v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][33u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][33u])))); ++ v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); ++ v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); ++ v_cd0 = ((uint32_t)(v_ccp + v_cb2)); ++ v_cd1 = ((uint32_t)(v_ccm + v_cb6)); ++ v_cd2 = ((uint32_t)(v_ccm - v_cb6)); ++ v_cd3 = ((uint32_t)(v_ccp - v_cb2)); ++ v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][9u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][9u])))); ++ v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][25u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][25u])))); ++ v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][41u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][41u])))); ++ v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][57u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][57u])))); ++ v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); ++ v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); ++ v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); ++ v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); ++ v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); ++ v_ck1 = ((uint32_t)(v_bq1 * 12299u)); ++ v_ck3 = ((uint32_t)(v_bq3 * 25172u)); ++ v_ck5 = ((uint32_t)(v_bq5 * 16819u)); ++ v_ck7 = ((uint32_t)(v_bq7 * 2446u)); ++ v_ci51 *= 4294964100u; ++ v_ci53 *= 4294946301u; ++ v_ci71 *= 4294959923u; ++ v_ci73 *= 4294951227u; ++ v_cl51 = ((uint32_t)(v_ci51 + v_cj)); ++ v_cl73 = ((uint32_t)(v_ci73 + v_cj)); ++ v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); ++ v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); ++ v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); ++ v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); ++ v_intermediate[1u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); ++ v_intermediate[57u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); ++ v_intermediate[9u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); ++ v_intermediate[49u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); ++ v_intermediate[17u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); ++ v_intermediate[41u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); ++ v_intermediate[25u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); ++ v_intermediate[33u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); + } +- if (0u != (16u & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][1u] & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][2u] & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][3u] & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][4u] & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][5u] & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][6u] & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][7u] & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][8u] & +- self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][9u])) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(4294967288u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(6u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(42u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(6u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(4294967288u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(42u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(152u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(42u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(4294967288u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(6u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(42u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(6u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(4294967288u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + 128u)) / 256u))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + 128u)) / 256u))); +- } +- self->private_data.f_mcu_blocks[0u][0u] = ((uint16_t)(v_scratch)); +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][1u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][1u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(4294967283u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(38u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(4294967258u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(4294967283u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][1u] = ((uint16_t)(v_scratch)); +- } +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][2u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][2u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(4294967291u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(4294967282u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(4294967291u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][2u] = ((uint16_t)(v_scratch)); +- } +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][3u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][3u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][3u] = ((uint16_t)(v_scratch)); +- } +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][8u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][8u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(38u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(4294967283u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(4294967258u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(4294967283u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][8u] = ((uint16_t)(v_scratch)); +- } +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][9u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][9u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(9u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(4294967287u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(4294967287u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(9u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][9u] = ((uint16_t)(v_scratch)); +- } +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][10u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][10u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][10u] = ((uint16_t)(v_scratch)); +- } +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][16u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][16u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(4294967291u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(4294967282u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(4294967291u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][16u] = ((uint16_t)(v_scratch)); +- } +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][17u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][17u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][17u] = ((uint16_t)(v_scratch)); +- } +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][24u])); +- if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][24u] == 0u)) { +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } else { +- v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); +- } +- self->private_data.f_mcu_blocks[0u][24u] = ((uint16_t)(v_scratch)); +- } ++ if (0u == (self->private_data.f_mcu_blocks[0u][10u] | ++ self->private_data.f_mcu_blocks[0u][18u] | ++ self->private_data.f_mcu_blocks[0u][26u] | ++ self->private_data.f_mcu_blocks[0u][34u] | ++ self->private_data.f_mcu_blocks[0u][42u] | ++ self->private_data.f_mcu_blocks[0u][50u] | ++ self->private_data.f_mcu_blocks[0u][58u])) { ++ v_intermediate[2u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][2u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][2u])))) << 2u)); ++ v_intermediate[10u] = v_intermediate[2u]; ++ v_intermediate[18u] = v_intermediate[2u]; ++ v_intermediate[26u] = v_intermediate[2u]; ++ v_intermediate[34u] = v_intermediate[2u]; ++ v_intermediate[42u] = v_intermediate[2u]; ++ v_intermediate[50u] = v_intermediate[2u]; ++ v_intermediate[58u] = v_intermediate[2u]; + } else { +- v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][1u]; +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][1u])); +- if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][1u] == 0u)) { +- v_limit = ((((uint32_t)(1u)) << v_al) - 1u); +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(4294967289u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(50u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(4294967246u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } else { +- v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } +- self->private_data.f_mcu_blocks[0u][1u] = ((uint16_t)(v_scratch)); +- } +- v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][5u]; +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][2u])); +- if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][2u] == 0u)) { +- v_limit = ((((uint32_t)(1u)) << v_al) - 1u); +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(4294967272u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } else { +- v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } +- self->private_data.f_mcu_blocks[0u][2u] = ((uint16_t)(v_scratch)); +- } +- v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][2u]; +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][8u])); +- if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][8u] == 0u)) { +- v_limit = ((((uint32_t)(1u)) << v_al) - 1u); +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(4294967289u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(50u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(4294967246u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } else { +- v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } +- self->private_data.f_mcu_blocks[0u][8u] = ((uint16_t)(v_scratch)); +- } +- v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][4u]; +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][9u])); +- if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][9u] == 0u)) { +- v_limit = ((((uint32_t)(1u)) << v_al) - 1u); +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(10u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(4294967286u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(4294967286u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(10u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } else { +- v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } +- self->private_data.f_mcu_blocks[0u][9u] = ((uint16_t)(v_scratch)); +- } +- v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][3u]; +- v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][16u])); +- if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][16u] == 0u)) { +- v_limit = ((((uint32_t)(1u)) << v_al) - 1u); +- v_scratch = 0u; +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); +- v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); +- v_scratch += ((uint32_t)(4294967272u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); +- v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); +- v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); +- v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); +- v_scratch *= v_q_00; +- if (v_scratch < 2147483648u) { +- v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } else { +- v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); +- } +- self->private_data.f_mcu_blocks[0u][16u] = ((uint16_t)(v_scratch)); +- } ++ v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][18u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][18u])))); ++ v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][50u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][50u])))); ++ v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); ++ v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); ++ v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); ++ v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][2u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][2u])))); ++ v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][34u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][34u])))); ++ v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); ++ v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); ++ v_cd0 = ((uint32_t)(v_ccp + v_cb2)); ++ v_cd1 = ((uint32_t)(v_ccm + v_cb6)); ++ v_cd2 = ((uint32_t)(v_ccm - v_cb6)); ++ v_cd3 = ((uint32_t)(v_ccp - v_cb2)); ++ v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][10u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][10u])))); ++ v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][26u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][26u])))); ++ v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][42u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][42u])))); ++ v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][58u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][58u])))); ++ v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); ++ v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); ++ v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); ++ v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); ++ v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); ++ v_ck1 = ((uint32_t)(v_bq1 * 12299u)); ++ v_ck3 = ((uint32_t)(v_bq3 * 25172u)); ++ v_ck5 = ((uint32_t)(v_bq5 * 16819u)); ++ v_ck7 = ((uint32_t)(v_bq7 * 2446u)); ++ v_ci51 *= 4294964100u; ++ v_ci53 *= 4294946301u; ++ v_ci71 *= 4294959923u; ++ v_ci73 *= 4294951227u; ++ v_cl51 = ((uint32_t)(v_ci51 + v_cj)); ++ v_cl73 = ((uint32_t)(v_ci73 + v_cj)); ++ v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); ++ v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); ++ v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); ++ v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); ++ v_intermediate[2u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); ++ v_intermediate[58u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); ++ v_intermediate[10u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); ++ v_intermediate[50u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); ++ v_intermediate[18u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); ++ v_intermediate[42u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); ++ v_intermediate[26u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); ++ v_intermediate[34u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); + } +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func jpeg.decoder.decode_mcu +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my) { +- return (*self->private_impl.choosy_decode_mcu)(self, a_workbuf, a_mx, a_my); +-} +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu__choosy_default( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my) { +- uint32_t v_ret = 0; +- uint64_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint8_t v_csel = 0; +- wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_r = &u_r; +- const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint32_t v_pos = 0; +- uint8_t v_dc_h = 0; +- uint32_t v_dc_symbol = 0; +- uint32_t v_dc_ht_fast = 0; +- uint32_t v_dc_bl = 0; +- uint32_t v_dc_code = 0; +- uint32_t v_dc_blm1 = 0; +- uint32_t v_dc_ht_slow = 0; +- uint16_t v_dc_value = 0; +- uint16_t v_dc_extend = 0; +- const uint16_t* v_ac_huff_table_fast = NULL; +- uint8_t v_ac_h = 0; +- uint32_t v_ac_symbol = 0; +- uint32_t v_ac_ht_fast = 0; +- uint32_t v_ac_bl = 0; +- uint32_t v_ac_code = 0; +- uint32_t v_ac_blm1 = 0; +- uint32_t v_ac_ht_slow = 0; +- uint16_t v_ac_value = 0; +- uint16_t v_ac_extend = 0; +- uint32_t v_ac_rrrr = 0; +- uint32_t v_ac_ssss = 0; +- uint32_t v_z = 0; +- uint32_t v_mcb = 0; +- uint64_t v_stride = 0; +- uint64_t v_offset = 0; +- +- v_bits = self->private_impl.f_bitstream_bits; +- v_n_bits = self->private_impl.f_bitstream_n_bits; +- if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { +- return 2u; ++ if (0u == (self->private_data.f_mcu_blocks[0u][11u] | ++ self->private_data.f_mcu_blocks[0u][19u] | ++ self->private_data.f_mcu_blocks[0u][27u] | ++ self->private_data.f_mcu_blocks[0u][35u] | ++ self->private_data.f_mcu_blocks[0u][43u] | ++ self->private_data.f_mcu_blocks[0u][51u] | ++ self->private_data.f_mcu_blocks[0u][59u])) { ++ v_intermediate[3u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][3u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][3u])))) << 2u)); ++ v_intermediate[11u] = v_intermediate[3u]; ++ v_intermediate[19u] = v_intermediate[3u]; ++ v_intermediate[27u] = v_intermediate[3u]; ++ v_intermediate[35u] = v_intermediate[3u]; ++ v_intermediate[43u] = v_intermediate[3u]; ++ v_intermediate[51u] = v_intermediate[3u]; ++ v_intermediate[59u] = v_intermediate[3u]; ++ } else { ++ v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][19u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][19u])))); ++ v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][51u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][51u])))); ++ v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); ++ v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); ++ v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); ++ v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][3u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][3u])))); ++ v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][35u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][35u])))); ++ v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); ++ v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); ++ v_cd0 = ((uint32_t)(v_ccp + v_cb2)); ++ v_cd1 = ((uint32_t)(v_ccm + v_cb6)); ++ v_cd2 = ((uint32_t)(v_ccm - v_cb6)); ++ v_cd3 = ((uint32_t)(v_ccp - v_cb2)); ++ v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][11u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][11u])))); ++ v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][27u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][27u])))); ++ v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][43u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][43u])))); ++ v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][59u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][59u])))); ++ v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); ++ v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); ++ v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); ++ v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); ++ v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); ++ v_ck1 = ((uint32_t)(v_bq1 * 12299u)); ++ v_ck3 = ((uint32_t)(v_bq3 * 25172u)); ++ v_ck5 = ((uint32_t)(v_bq5 * 16819u)); ++ v_ck7 = ((uint32_t)(v_bq7 * 2446u)); ++ v_ci51 *= 4294964100u; ++ v_ci53 *= 4294946301u; ++ v_ci71 *= 4294959923u; ++ v_ci73 *= 4294951227u; ++ v_cl51 = ((uint32_t)(v_ci51 + v_cj)); ++ v_cl73 = ((uint32_t)(v_ci73 + v_cj)); ++ v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); ++ v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); ++ v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); ++ v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); ++ v_intermediate[3u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); ++ v_intermediate[59u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); ++ v_intermediate[11u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); ++ v_intermediate[51u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); ++ v_intermediate[19u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); ++ v_intermediate[43u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); ++ v_intermediate[27u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); ++ v_intermediate[35u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); + } +- { +- wuffs_base__io_buffer* o_0_v_r = v_r; +- const uint8_t *o_0_iop_v_r = iop_v_r; +- const uint8_t *o_0_io0_v_r = io0_v_r; +- const uint8_t *o_0_io1_v_r = io1_v_r; +- const uint8_t *o_0_io2_v_r = io2_v_r; +- v_r = wuffs_base__io_reader__set( +- &u_r, +- &iop_v_r, +- &io0_v_r, +- &io1_v_r, +- &io2_v_r, +- wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, +- self->private_impl.f_bitstream_ri, +- self->private_impl.f_bitstream_wi), +- ((uint64_t)(self->private_impl.f_bitstream_ri))); +- do { +- while (self->private_impl.f_mcu_current_block < self->private_impl.f_mcu_num_blocks) { +- while (self->private_impl.f_mcu_zig_index <= 0u) { +- wuffs_base__bulk_memset(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, 0u); +- if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { +- v_ret = 1u; +- goto label__goto_done__break; +- } +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- v_dc_h = self->private_impl.f_mcu_blocks_dc_hselector[self->private_impl.f_mcu_current_block]; +- v_dc_ht_fast = ((uint32_t)(self->private_impl.f_huff_tables_fast[v_dc_h][(v_bits >> 56u)])); +- v_dc_bl = (v_dc_ht_fast >> 8u); +- if (v_n_bits >= v_dc_bl) { +- v_dc_symbol = (15u & v_dc_ht_fast); +- v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; +- v_bits <<= (v_dc_bl & 63u); +- v_n_bits -= v_dc_bl; +- } else { +- v_dc_code = ((uint32_t)((v_bits >> 55u))); +- v_dc_blm1 = 8u; +- v_bits <<= 9u; +- v_n_bits -= 9u; +- while (true) { +- v_dc_ht_slow = self->private_impl.f_huff_tables_slow[v_dc_h][v_dc_blm1]; +- if (v_dc_code < (v_dc_ht_slow >> 8u)) { +- v_dc_symbol = (15u & ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_dc_h][(255u & ((uint32_t)(v_dc_code + v_dc_ht_slow)))]))); +- v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; +- break; +- } +- v_dc_code = (((uint32_t)(v_dc_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); +- v_bits <<= 1u; +- v_n_bits -= 1u; +- v_dc_blm1 = ((v_dc_blm1 + 1u) & 15u); +- if (v_dc_blm1 == 0u) { +- v_dc_symbol = 0u; +- v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; +- break; +- } +- } +- } +- v_dc_value = ((uint16_t)(((v_bits >> 32u) >> (32u - v_dc_symbol)))); +- v_dc_value += (v_dc_extend & (((uint16_t)(wuffs_base__utility__sign_extend_rshift_u64(v_bits, 63u))) ^ 65535u)); +- v_bits <<= v_dc_symbol; +- v_n_bits -= v_dc_symbol; +- v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[self->private_impl.f_mcu_current_block]]; +- self->private_impl.f_mcu_previous_dc_values[v_csel] += v_dc_value; +- self->private_data.f_mcu_blocks[0u][0u] = self->private_impl.f_mcu_previous_dc_values[v_csel]; +- self->private_impl.f_mcu_zig_index = 1u; +- break; +- } +- if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { +- v_ret = 1u; +- goto label__goto_done__break; +- } +- if (v_n_bits < 16u) { +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- } +- v_z = 1u; +- self->private_impl.f_mcu_zig_index = 0u; +- v_ac_h = self->private_impl.f_mcu_blocks_ac_hselector[self->private_impl.f_mcu_current_block]; +- v_ac_huff_table_fast = &self->private_impl.f_huff_tables_fast[v_ac_h][0u]; +- while (v_z < 64u) { +- v_ac_ht_fast = ((uint32_t)(v_ac_huff_table_fast[(v_bits >> 56u)])); +- if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { +- v_ret = 2u; +- goto label__goto_done__break; +- } +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- v_ac_bl = (v_ac_ht_fast >> 8u); +- if (v_n_bits >= v_ac_bl) { +- v_ac_symbol = (255u & v_ac_ht_fast); +- v_bits <<= (v_ac_bl & 63u); +- v_n_bits -= v_ac_bl; +- } else { +- v_ac_code = ((uint32_t)((v_bits >> 55u))); +- v_ac_blm1 = 8u; +- v_bits <<= 9u; +- v_n_bits -= 9u; +- while (true) { +- v_ac_ht_slow = self->private_impl.f_huff_tables_slow[v_ac_h][v_ac_blm1]; +- if (v_ac_code < (v_ac_ht_slow >> 8u)) { +- v_ac_symbol = ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_ac_h][(255u & ((uint32_t)(v_ac_code + v_ac_ht_slow)))])); +- break; +- } +- v_ac_code = (((uint32_t)(v_ac_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); +- v_bits <<= 1u; +- v_n_bits -= 1u; +- v_ac_blm1 = ((v_ac_blm1 + 1u) & 15u); +- if (v_ac_blm1 == 0u) { +- v_ac_symbol = 0u; +- break; +- } +- } +- } +- v_ac_rrrr = (v_ac_symbol >> 4u); +- v_z += (v_ac_rrrr + 1u); +- v_ac_ssss = (v_ac_symbol & 15u); +- v_ac_extend = WUFFS_JPEG__EXTEND[v_ac_ssss]; +- if (v_ac_ssss > 0u) { +- v_ac_value = ((uint16_t)((v_bits >> (64u - v_ac_ssss)))); +- v_ac_value += (v_ac_extend & (((uint16_t)(wuffs_base__utility__sign_extend_rshift_u64(v_bits, 63u))) ^ 65535u)); +- v_bits <<= v_ac_ssss; +- v_n_bits -= v_ac_ssss; +- self->private_data.f_mcu_blocks[0u][WUFFS_JPEG__UNZIG[v_z]] = v_ac_value; +- } else if (v_ac_rrrr < 15u) { +- break; +- } +- } +- v_mcb = self->private_impl.f_mcu_current_block; +- self->private_impl.f_mcu_current_block += 1u; +- if (self->private_impl.f_test_only_interrupt_decode_mcu) { +- goto label__goto_done__break; +- } +- v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[v_mcb]]; +- v_stride = ((uint64_t)(self->private_impl.f_components_workbuf_widths[v_csel])); +- v_offset = (self->private_impl.f_mcu_blocks_offset[v_mcb] + (((uint64_t)(self->private_impl.f_mcu_blocks_mx_mul[v_mcb])) * ((uint64_t)(a_mx))) + (((uint64_t)(self->private_impl.f_mcu_blocks_my_mul[v_mcb])) * ((uint64_t)(a_my)))); +- if (v_offset <= ((uint64_t)(a_workbuf.len))) { +- wuffs_jpeg__decoder__decode_idct(self, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset), v_stride, ((uint32_t)(self->private_impl.f_components_tq[v_csel]))); +- } +- } +- self->private_impl.f_mcu_current_block = 0u; +- } while (0); +- label__goto_done__break:; +- v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); +- if (v_pos > self->private_impl.f_bitstream_wi) { +- v_ret = 2u; +- } else { +- self->private_impl.f_bitstream_ri = v_pos; +- } +- v_r = o_0_v_r; +- iop_v_r = o_0_iop_v_r; +- io0_v_r = o_0_io0_v_r; +- io1_v_r = o_0_io1_v_r; +- io2_v_r = o_0_io2_v_r; ++ if (0u == (self->private_data.f_mcu_blocks[0u][12u] | ++ self->private_data.f_mcu_blocks[0u][20u] | ++ self->private_data.f_mcu_blocks[0u][28u] | ++ self->private_data.f_mcu_blocks[0u][36u] | ++ self->private_data.f_mcu_blocks[0u][44u] | ++ self->private_data.f_mcu_blocks[0u][52u] | ++ self->private_data.f_mcu_blocks[0u][60u])) { ++ v_intermediate[4u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][4u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][4u])))) << 2u)); ++ v_intermediate[12u] = v_intermediate[4u]; ++ v_intermediate[20u] = v_intermediate[4u]; ++ v_intermediate[28u] = v_intermediate[4u]; ++ v_intermediate[36u] = v_intermediate[4u]; ++ v_intermediate[44u] = v_intermediate[4u]; ++ v_intermediate[52u] = v_intermediate[4u]; ++ v_intermediate[60u] = v_intermediate[4u]; ++ } else { ++ v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][20u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][20u])))); ++ v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][52u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][52u])))); ++ v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); ++ v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); ++ v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); ++ v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][4u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][4u])))); ++ v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][36u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][36u])))); ++ v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); ++ v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); ++ v_cd0 = ((uint32_t)(v_ccp + v_cb2)); ++ v_cd1 = ((uint32_t)(v_ccm + v_cb6)); ++ v_cd2 = ((uint32_t)(v_ccm - v_cb6)); ++ v_cd3 = ((uint32_t)(v_ccp - v_cb2)); ++ v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][12u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][12u])))); ++ v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][28u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][28u])))); ++ v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][44u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][44u])))); ++ v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][60u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][60u])))); ++ v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); ++ v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); ++ v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); ++ v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); ++ v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); ++ v_ck1 = ((uint32_t)(v_bq1 * 12299u)); ++ v_ck3 = ((uint32_t)(v_bq3 * 25172u)); ++ v_ck5 = ((uint32_t)(v_bq5 * 16819u)); ++ v_ck7 = ((uint32_t)(v_bq7 * 2446u)); ++ v_ci51 *= 4294964100u; ++ v_ci53 *= 4294946301u; ++ v_ci71 *= 4294959923u; ++ v_ci73 *= 4294951227u; ++ v_cl51 = ((uint32_t)(v_ci51 + v_cj)); ++ v_cl73 = ((uint32_t)(v_ci73 + v_cj)); ++ v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); ++ v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); ++ v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); ++ v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); ++ v_intermediate[4u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); ++ v_intermediate[60u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); ++ v_intermediate[12u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); ++ v_intermediate[52u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); ++ v_intermediate[20u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); ++ v_intermediate[44u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); ++ v_intermediate[28u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); ++ v_intermediate[36u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); + } +- self->private_impl.f_bitstream_bits = v_bits; +- self->private_impl.f_bitstream_n_bits = v_n_bits; +- return v_ret; +-} +- +-// -------- func jpeg.decoder.decode_mcu_progressive_ac_high_bits +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu_progressive_ac_high_bits( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my) { +- uint32_t v_ret = 0; +- uint64_t v_bits = 0; +- uint32_t v_n_bits = 0; +- wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_r = &u_r; +- const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint32_t v_pos = 0; +- const uint16_t* v_ac_huff_table_fast = NULL; +- uint8_t v_ac_h = 0; +- uint32_t v_ac_symbol = 0; +- uint32_t v_ac_ht_fast = 0; +- uint32_t v_ac_bl = 0; +- uint32_t v_ac_code = 0; +- uint32_t v_ac_blm1 = 0; +- uint32_t v_ac_ht_slow = 0; +- uint16_t v_ac_value = 0; +- uint16_t v_ac_extend = 0; +- uint32_t v_ac_rrrr = 0; +- uint32_t v_ac_ssss = 0; +- uint32_t v_z = 0; +- +- if (self->private_impl.f_eob_run > 0u) { +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_impl.f_eob_run -= 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- return 0u; ++ if (0u == (self->private_data.f_mcu_blocks[0u][13u] | ++ self->private_data.f_mcu_blocks[0u][21u] | ++ self->private_data.f_mcu_blocks[0u][29u] | ++ self->private_data.f_mcu_blocks[0u][37u] | ++ self->private_data.f_mcu_blocks[0u][45u] | ++ self->private_data.f_mcu_blocks[0u][53u] | ++ self->private_data.f_mcu_blocks[0u][61u])) { ++ v_intermediate[5u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][5u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][5u])))) << 2u)); ++ v_intermediate[13u] = v_intermediate[5u]; ++ v_intermediate[21u] = v_intermediate[5u]; ++ v_intermediate[29u] = v_intermediate[5u]; ++ v_intermediate[37u] = v_intermediate[5u]; ++ v_intermediate[45u] = v_intermediate[5u]; ++ v_intermediate[53u] = v_intermediate[5u]; ++ v_intermediate[61u] = v_intermediate[5u]; ++ } else { ++ v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][21u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][21u])))); ++ v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][53u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][53u])))); ++ v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); ++ v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); ++ v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); ++ v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][5u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][5u])))); ++ v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][37u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][37u])))); ++ v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); ++ v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); ++ v_cd0 = ((uint32_t)(v_ccp + v_cb2)); ++ v_cd1 = ((uint32_t)(v_ccm + v_cb6)); ++ v_cd2 = ((uint32_t)(v_ccm - v_cb6)); ++ v_cd3 = ((uint32_t)(v_ccp - v_cb2)); ++ v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][13u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][13u])))); ++ v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][29u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][29u])))); ++ v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][45u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][45u])))); ++ v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][61u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][61u])))); ++ v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); ++ v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); ++ v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); ++ v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); ++ v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); ++ v_ck1 = ((uint32_t)(v_bq1 * 12299u)); ++ v_ck3 = ((uint32_t)(v_bq3 * 25172u)); ++ v_ck5 = ((uint32_t)(v_bq5 * 16819u)); ++ v_ck7 = ((uint32_t)(v_bq7 * 2446u)); ++ v_ci51 *= 4294964100u; ++ v_ci53 *= 4294946301u; ++ v_ci71 *= 4294959923u; ++ v_ci73 *= 4294951227u; ++ v_cl51 = ((uint32_t)(v_ci51 + v_cj)); ++ v_cl73 = ((uint32_t)(v_ci73 + v_cj)); ++ v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); ++ v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); ++ v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); ++ v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); ++ v_intermediate[5u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); ++ v_intermediate[61u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); ++ v_intermediate[13u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); ++ v_intermediate[53u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); ++ v_intermediate[21u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); ++ v_intermediate[45u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); ++ v_intermediate[29u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); ++ v_intermediate[37u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); + } +- v_bits = self->private_impl.f_bitstream_bits; +- v_n_bits = self->private_impl.f_bitstream_n_bits; +- if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { +- return 2u; ++ if (0u == (self->private_data.f_mcu_blocks[0u][14u] | ++ self->private_data.f_mcu_blocks[0u][22u] | ++ self->private_data.f_mcu_blocks[0u][30u] | ++ self->private_data.f_mcu_blocks[0u][38u] | ++ self->private_data.f_mcu_blocks[0u][46u] | ++ self->private_data.f_mcu_blocks[0u][54u] | ++ self->private_data.f_mcu_blocks[0u][62u])) { ++ v_intermediate[6u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][6u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][6u])))) << 2u)); ++ v_intermediate[14u] = v_intermediate[6u]; ++ v_intermediate[22u] = v_intermediate[6u]; ++ v_intermediate[30u] = v_intermediate[6u]; ++ v_intermediate[38u] = v_intermediate[6u]; ++ v_intermediate[46u] = v_intermediate[6u]; ++ v_intermediate[54u] = v_intermediate[6u]; ++ v_intermediate[62u] = v_intermediate[6u]; ++ } else { ++ v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][22u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][22u])))); ++ v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][54u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][54u])))); ++ v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); ++ v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); ++ v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); ++ v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][6u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][6u])))); ++ v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][38u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][38u])))); ++ v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); ++ v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); ++ v_cd0 = ((uint32_t)(v_ccp + v_cb2)); ++ v_cd1 = ((uint32_t)(v_ccm + v_cb6)); ++ v_cd2 = ((uint32_t)(v_ccm - v_cb6)); ++ v_cd3 = ((uint32_t)(v_ccp - v_cb2)); ++ v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][14u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][14u])))); ++ v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][30u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][30u])))); ++ v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][46u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][46u])))); ++ v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][62u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][62u])))); ++ v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); ++ v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); ++ v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); ++ v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); ++ v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); ++ v_ck1 = ((uint32_t)(v_bq1 * 12299u)); ++ v_ck3 = ((uint32_t)(v_bq3 * 25172u)); ++ v_ck5 = ((uint32_t)(v_bq5 * 16819u)); ++ v_ck7 = ((uint32_t)(v_bq7 * 2446u)); ++ v_ci51 *= 4294964100u; ++ v_ci53 *= 4294946301u; ++ v_ci71 *= 4294959923u; ++ v_ci73 *= 4294951227u; ++ v_cl51 = ((uint32_t)(v_ci51 + v_cj)); ++ v_cl73 = ((uint32_t)(v_ci73 + v_cj)); ++ v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); ++ v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); ++ v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); ++ v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); ++ v_intermediate[6u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); ++ v_intermediate[62u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); ++ v_intermediate[14u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); ++ v_intermediate[54u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); ++ v_intermediate[22u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); ++ v_intermediate[46u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); ++ v_intermediate[30u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); ++ v_intermediate[38u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); + } +- { +- wuffs_base__io_buffer* o_0_v_r = v_r; +- const uint8_t *o_0_iop_v_r = iop_v_r; +- const uint8_t *o_0_io0_v_r = io0_v_r; +- const uint8_t *o_0_io1_v_r = io1_v_r; +- const uint8_t *o_0_io2_v_r = io2_v_r; +- v_r = wuffs_base__io_reader__set( +- &u_r, +- &iop_v_r, +- &io0_v_r, +- &io1_v_r, +- &io2_v_r, +- wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, +- self->private_impl.f_bitstream_ri, +- self->private_impl.f_bitstream_wi), +- ((uint64_t)(self->private_impl.f_bitstream_ri))); +- do { +- do { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { +- v_ret = 1u; +- goto label__goto_done__break; +- } +- if (v_n_bits < 16u) { +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- } +- v_z = self->private_impl.f_mcu_zig_index; +- self->private_impl.f_mcu_zig_index = 0u; +- v_ac_h = self->private_impl.f_mcu_blocks_ac_hselector[0u]; +- v_ac_huff_table_fast = &self->private_impl.f_huff_tables_fast[v_ac_h][0u]; +- while (v_z <= ((uint32_t)(self->private_impl.f_scan_se))) { +- v_ac_ht_fast = ((uint32_t)(v_ac_huff_table_fast[(v_bits >> 56u)])); +- if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { +- v_ret = 2u; +- goto label__goto_done__break; +- } +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- v_ac_bl = (v_ac_ht_fast >> 8u); +- if (v_n_bits >= v_ac_bl) { +- v_ac_symbol = (255u & v_ac_ht_fast); +- v_bits <<= (v_ac_bl & 63u); +- v_n_bits -= v_ac_bl; +- } else { +- v_ac_code = ((uint32_t)((v_bits >> 55u))); +- v_ac_blm1 = 8u; +- v_bits <<= 9u; +- v_n_bits -= 9u; +- while (true) { +- v_ac_ht_slow = self->private_impl.f_huff_tables_slow[v_ac_h][v_ac_blm1]; +- if (v_ac_code < (v_ac_ht_slow >> 8u)) { +- v_ac_symbol = ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_ac_h][(255u & ((uint32_t)(v_ac_code + v_ac_ht_slow)))])); +- break; +- } +- v_ac_code = (((uint32_t)(v_ac_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); +- v_bits <<= 1u; +- v_n_bits -= 1u; +- v_ac_blm1 = ((v_ac_blm1 + 1u) & 15u); +- if (v_ac_blm1 == 0u) { +- v_ac_symbol = 0u; +- break; +- } +- } +- } +- v_ac_rrrr = (v_ac_symbol >> 4u); +- v_z += (v_ac_rrrr + 1u); +- v_ac_ssss = (v_ac_symbol & 15u); +- v_ac_extend = WUFFS_JPEG__EXTEND[v_ac_ssss]; +- if (v_ac_ssss > 0u) { +- v_ac_value = ((uint16_t)((v_bits >> (64u - v_ac_ssss)))); +- v_ac_value += (v_ac_extend & (((uint16_t)(wuffs_base__utility__sign_extend_rshift_u64(v_bits, 63u))) ^ 65535u)); +- v_bits <<= v_ac_ssss; +- v_n_bits -= v_ac_ssss; +- self->private_data.f_mcu_blocks[0u][WUFFS_JPEG__UNZIG[v_z]] = ((uint16_t)(((uint16_t)(v_ac_value << self->private_impl.f_scan_al)))); +- } else if (v_ac_rrrr < 15u) { +- self->private_impl.f_eob_run = ((uint16_t)(((((uint16_t)(1u)) << v_ac_rrrr) - 1u))); +- if (v_ac_rrrr > 0u) { +- self->private_impl.f_eob_run += ((uint16_t)((v_bits >> (64u - v_ac_rrrr)))); +- v_bits <<= v_ac_rrrr; +- v_n_bits -= v_ac_rrrr; +- } +- break; +- } +- } +- } while (0); +- } while (0); +- label__goto_done__break:; +- v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); +- if (v_pos > self->private_impl.f_bitstream_wi) { +- v_ret = 2u; +- } else { +- self->private_impl.f_bitstream_ri = v_pos; +- } +- v_r = o_0_v_r; +- iop_v_r = o_0_iop_v_r; +- io0_v_r = o_0_io0_v_r; +- io1_v_r = o_0_io1_v_r; +- io2_v_r = o_0_io2_v_r; ++ if (0u == (self->private_data.f_mcu_blocks[0u][15u] | ++ self->private_data.f_mcu_blocks[0u][23u] | ++ self->private_data.f_mcu_blocks[0u][31u] | ++ self->private_data.f_mcu_blocks[0u][39u] | ++ self->private_data.f_mcu_blocks[0u][47u] | ++ self->private_data.f_mcu_blocks[0u][55u] | ++ self->private_data.f_mcu_blocks[0u][63u])) { ++ v_intermediate[7u] = ((uint32_t)(((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][7u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][7u])))) << 2u)); ++ v_intermediate[15u] = v_intermediate[7u]; ++ v_intermediate[23u] = v_intermediate[7u]; ++ v_intermediate[31u] = v_intermediate[7u]; ++ v_intermediate[39u] = v_intermediate[7u]; ++ v_intermediate[47u] = v_intermediate[7u]; ++ v_intermediate[55u] = v_intermediate[7u]; ++ v_intermediate[63u] = v_intermediate[7u]; ++ } else { ++ v_bq2 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][23u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][23u])))); ++ v_bq6 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][55u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][55u])))); ++ v_ca = ((uint32_t)(((uint32_t)(v_bq2 + v_bq6)) * 4433u)); ++ v_cb2 = ((uint32_t)(v_ca + ((uint32_t)(v_bq2 * 6270u)))); ++ v_cb6 = ((uint32_t)(v_ca - ((uint32_t)(v_bq6 * 15137u)))); ++ v_bq0 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][7u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][7u])))); ++ v_bq4 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][39u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][39u])))); ++ v_ccp = ((uint32_t)(((uint32_t)(v_bq0 + v_bq4)) << 13u)); ++ v_ccm = ((uint32_t)(((uint32_t)(v_bq0 - v_bq4)) << 13u)); ++ v_cd0 = ((uint32_t)(v_ccp + v_cb2)); ++ v_cd1 = ((uint32_t)(v_ccm + v_cb6)); ++ v_cd2 = ((uint32_t)(v_ccm - v_cb6)); ++ v_cd3 = ((uint32_t)(v_ccp - v_cb2)); ++ v_bq1 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][15u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][15u])))); ++ v_bq3 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][31u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][31u])))); ++ v_bq5 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][47u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][47u])))); ++ v_bq7 = ((uint32_t)(wuffs_base__utility__sign_extend_convert_u16_u32(self->private_data.f_mcu_blocks[0u][63u]) * ((uint32_t)(self->private_impl.f_quant_tables[a_q][63u])))); ++ v_ci51 = ((uint32_t)(v_bq5 + v_bq1)); ++ v_ci53 = ((uint32_t)(v_bq5 + v_bq3)); ++ v_ci71 = ((uint32_t)(v_bq7 + v_bq1)); ++ v_ci73 = ((uint32_t)(v_bq7 + v_bq3)); ++ v_cj = ((uint32_t)(((uint32_t)(v_ci73 + v_ci51)) * 9633u)); ++ v_ck1 = ((uint32_t)(v_bq1 * 12299u)); ++ v_ck3 = ((uint32_t)(v_bq3 * 25172u)); ++ v_ck5 = ((uint32_t)(v_bq5 * 16819u)); ++ v_ck7 = ((uint32_t)(v_bq7 * 2446u)); ++ v_ci51 *= 4294964100u; ++ v_ci53 *= 4294946301u; ++ v_ci71 *= 4294959923u; ++ v_ci73 *= 4294951227u; ++ v_cl51 = ((uint32_t)(v_ci51 + v_cj)); ++ v_cl73 = ((uint32_t)(v_ci73 + v_cj)); ++ v_ck1 += ((uint32_t)(v_ci71 + v_cl51)); ++ v_ck3 += ((uint32_t)(v_ci53 + v_cl73)); ++ v_ck5 += ((uint32_t)(v_ci53 + v_cl51)); ++ v_ck7 += ((uint32_t)(v_ci71 + v_cl73)); ++ v_intermediate[7u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 + v_ck1)) + 1024u)), 11u); ++ v_intermediate[63u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd0 - v_ck1)) + 1024u)), 11u); ++ v_intermediate[15u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 + v_ck3)) + 1024u)), 11u); ++ v_intermediate[55u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd1 - v_ck3)) + 1024u)), 11u); ++ v_intermediate[23u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 + v_ck5)) + 1024u)), 11u); ++ v_intermediate[47u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd2 - v_ck5)) + 1024u)), 11u); ++ v_intermediate[31u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 + v_ck7)) + 1024u)), 11u); ++ v_intermediate[39u] = wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(((uint32_t)(v_cd3 - v_ck7)) + 1024u)), 11u); + } +- self->private_impl.f_bitstream_bits = v_bits; +- self->private_impl.f_bitstream_n_bits = v_n_bits; +- return v_ret; +-} +- +-// -------- func jpeg.decoder.decode_mcu_progressive_ac_low_bit +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu_progressive_ac_low_bit( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my) { +- uint32_t v_ret = 0; +- uint64_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint16_t v_one_lshift_scan_al = 0; +- wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_r = &u_r; +- const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint32_t v_pos = 0; +- const uint16_t* v_ac_huff_table_fast = NULL; +- uint8_t v_ac_h = 0; +- uint32_t v_ac_symbol = 0; +- uint32_t v_ac_ht_fast = 0; +- uint32_t v_ac_bl = 0; +- uint32_t v_ac_code = 0; +- uint32_t v_ac_blm1 = 0; +- uint32_t v_ac_ht_slow = 0; +- uint16_t v_ac_value = 0; +- uint32_t v_ac_rrrr = 0; +- uint32_t v_ac_ssss = 0; +- uint8_t v_unzig = 0; +- bool v_bit = false; +- +- v_bits = self->private_impl.f_bitstream_bits; +- v_n_bits = self->private_impl.f_bitstream_n_bits; +- v_one_lshift_scan_al = (((uint16_t)(1u)) << self->private_impl.f_scan_al); +- if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { +- return 2u; +- } +- { +- wuffs_base__io_buffer* o_0_v_r = v_r; +- const uint8_t *o_0_iop_v_r = iop_v_r; +- const uint8_t *o_0_io0_v_r = io0_v_r; +- const uint8_t *o_0_io1_v_r = io1_v_r; +- const uint8_t *o_0_io2_v_r = io2_v_r; +- v_r = wuffs_base__io_reader__set( +- &u_r, +- &iop_v_r, +- &io0_v_r, +- &io1_v_r, +- &io2_v_r, +- wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, +- self->private_impl.f_bitstream_ri, +- self->private_impl.f_bitstream_wi), +- ((uint64_t)(self->private_impl.f_bitstream_ri))); +- do { +- do { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { +- v_ret = 1u; +- goto label__goto_done__break; +- } +- while (true) { +- if (self->private_impl.f_eob_run > 0u) { +- break; +- } +- v_ac_h = self->private_impl.f_mcu_blocks_ac_hselector[0u]; +- v_ac_huff_table_fast = &self->private_impl.f_huff_tables_fast[v_ac_h][0u]; +- while (true) { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { +- v_ret = 2u; +- goto label__goto_done__break; +- } +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- v_ac_ht_fast = ((uint32_t)(v_ac_huff_table_fast[(v_bits >> 56u)])); +- v_ac_bl = (v_ac_ht_fast >> 8u); +- if (v_n_bits >= v_ac_bl) { +- v_ac_symbol = (255u & v_ac_ht_fast); +- v_bits <<= (v_ac_bl & 63u); +- v_n_bits -= v_ac_bl; +- } else { +- v_ac_code = ((uint32_t)((v_bits >> 55u))); +- v_ac_blm1 = 8u; +- v_bits <<= 9u; +- v_n_bits -= 9u; +- while (true) { +- v_ac_ht_slow = self->private_impl.f_huff_tables_slow[v_ac_h][v_ac_blm1]; +- if (v_ac_code < (v_ac_ht_slow >> 8u)) { +- v_ac_symbol = ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_ac_h][(255u & ((uint32_t)(v_ac_code + v_ac_ht_slow)))])); +- break; +- } +- v_ac_code = (((uint32_t)(v_ac_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); +- v_bits <<= 1u; +- v_n_bits -= 1u; +- v_ac_blm1 = ((v_ac_blm1 + 1u) & 15u); +- if (v_ac_blm1 == 0u) { +- v_ac_symbol = 0u; +- break; +- } +- } +- } +- v_ac_rrrr = (v_ac_symbol >> 4u); +- v_ac_ssss = (v_ac_symbol & 15u); +- v_ac_value = 0u; +- if (v_ac_ssss > 0u) { +- v_ac_value = (((uint16_t)(1u)) << self->private_impl.f_scan_al); +- if ((v_bits >> 63u) == 0u) { +- v_ac_value = ((uint16_t)(((uint16_t)(65535u)) << self->private_impl.f_scan_al)); +- } +- v_bits <<= 1u; +- v_n_bits -= 1u; +- } else if (v_ac_rrrr < 15u) { +- self->private_impl.f_eob_run = (((uint16_t)(1u)) << v_ac_rrrr); +- if (v_ac_rrrr > 0u) { +- self->private_impl.f_eob_run += ((uint16_t)((v_bits >> (64u - v_ac_rrrr)))); +- v_bits <<= v_ac_rrrr; +- v_n_bits -= v_ac_rrrr; +- } +- goto label__goto_do_eob__break; +- } +- while (true) { +- v_unzig = WUFFS_JPEG__UNZIG[(1u + self->private_impl.f_mcu_zig_index)]; +- if (self->private_data.f_mcu_blocks[0u][v_unzig] != 0u) { +- if (v_n_bits == 0u) { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { +- v_ret = 2u; +- goto label__goto_done__break; +- } +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- } +- v_bit = ((v_bits >> 63u) > 0u); +- v_bits <<= 1u; +- v_n_bits -= 1u; +- if (v_bit) { +- if (self->private_data.f_mcu_blocks[0u][v_unzig] < 32768u) { +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_data.f_mcu_blocks[0u][v_unzig] += v_one_lshift_scan_al; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_data.f_mcu_blocks[0u][v_unzig] -= v_one_lshift_scan_al; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } +- } +- } else if (v_ac_rrrr <= 0u) { +- break; +- } else { +- v_ac_rrrr -= 1u; +- } +- if (self->private_impl.f_mcu_zig_index >= ((uint32_t)(self->private_impl.f_scan_se))) { +- break; +- } +- self->private_impl.f_mcu_zig_index += 1u; +- } +- if (v_ac_value != 0u) { +- self->private_data.f_mcu_blocks[0u][WUFFS_JPEG__UNZIG[(1u + self->private_impl.f_mcu_zig_index)]] = v_ac_value; +- } +- if (self->private_impl.f_mcu_zig_index >= ((uint32_t)(self->private_impl.f_scan_se))) { +- break; +- } +- self->private_impl.f_mcu_zig_index += 1u; +- } +- goto label__block__break; +- } +- label__goto_do_eob__break:; +- if (self->private_impl.f_eob_run <= 0u) { +- v_ret = 2u; +- goto label__goto_done__break; +- } +- while (true) { +- v_unzig = WUFFS_JPEG__UNZIG[(1u + self->private_impl.f_mcu_zig_index)]; +- if (self->private_data.f_mcu_blocks[0u][v_unzig] != 0u) { +- if (v_n_bits == 0u) { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { +- v_ret = 2u; +- goto label__goto_done__break; +- } +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- } +- v_bit = ((v_bits >> 63u) > 0u); +- v_bits <<= 1u; +- v_n_bits -= 1u; +- if (v_bit) { +- if (self->private_data.f_mcu_blocks[0u][v_unzig] < 32768u) { +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_data.f_mcu_blocks[0u][v_unzig] += v_one_lshift_scan_al; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_data.f_mcu_blocks[0u][v_unzig] -= v_one_lshift_scan_al; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } +- } +- } +- if (self->private_impl.f_mcu_zig_index >= ((uint32_t)(self->private_impl.f_scan_se))) { +- break; +- } +- self->private_impl.f_mcu_zig_index += 1u; +- } +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_impl.f_eob_run -= 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } while (0); +- label__block__break:; +- } while (0); +- label__goto_done__break:; +- v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); +- if (v_pos > self->private_impl.f_bitstream_wi) { +- v_ret = 2u; +- } else { +- self->private_impl.f_bitstream_ri = v_pos; ++ if (0u == (v_intermediate[1u] | ++ v_intermediate[2u] | ++ v_intermediate[3u] | ++ v_intermediate[4u] | ++ v_intermediate[5u] | ++ v_intermediate[6u] | ++ v_intermediate[7u])) { ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); + } +- v_r = o_0_v_r; +- iop_v_r = o_0_iop_v_r; +- io0_v_r = o_0_io0_v_r; +- io1_v_r = o_0_io1_v_r; +- io2_v_r = o_0_io2_v_r; +- } +- self->private_impl.f_bitstream_bits = v_bits; +- self->private_impl.f_bitstream_n_bits = v_n_bits; +- return v_ret; +-} +- +-// -------- func jpeg.decoder.decode_mcu_progressive_dc_high_bits +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu_progressive_dc_high_bits( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my) { +- uint32_t v_ret = 0; +- uint64_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint8_t v_csel = 0; +- wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_r = &u_r; +- const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint32_t v_pos = 0; +- uint8_t v_dc_h = 0; +- uint32_t v_dc_symbol = 0; +- uint32_t v_dc_ht_fast = 0; +- uint32_t v_dc_bl = 0; +- uint32_t v_dc_code = 0; +- uint32_t v_dc_blm1 = 0; +- uint32_t v_dc_ht_slow = 0; +- uint16_t v_dc_value = 0; +- uint16_t v_dc_extend = 0; +- +- v_bits = self->private_impl.f_bitstream_bits; +- v_n_bits = self->private_impl.f_bitstream_n_bits; +- if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { +- return 2u; +- } +- { +- wuffs_base__io_buffer* o_0_v_r = v_r; +- const uint8_t *o_0_iop_v_r = iop_v_r; +- const uint8_t *o_0_io0_v_r = io0_v_r; +- const uint8_t *o_0_io1_v_r = io1_v_r; +- const uint8_t *o_0_io2_v_r = io2_v_r; +- v_r = wuffs_base__io_reader__set( +- &u_r, +- &iop_v_r, +- &io0_v_r, +- &io1_v_r, +- &io2_v_r, +- wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, +- self->private_impl.f_bitstream_ri, +- self->private_impl.f_bitstream_wi), +- ((uint64_t)(self->private_impl.f_bitstream_ri))); +- do { +- while (self->private_impl.f_mcu_current_block < self->private_impl.f_mcu_num_blocks) { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { +- v_ret = 1u; +- goto label__goto_done__break; +- } +- do { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { +- v_ret = 2u; +- goto label__goto_done__break; +- } +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- v_dc_h = self->private_impl.f_mcu_blocks_dc_hselector[self->private_impl.f_mcu_current_block]; +- v_dc_ht_fast = ((uint32_t)(self->private_impl.f_huff_tables_fast[v_dc_h][(v_bits >> 56u)])); +- v_dc_bl = (v_dc_ht_fast >> 8u); +- if (v_n_bits >= v_dc_bl) { +- v_dc_symbol = (15u & v_dc_ht_fast); +- v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; +- v_bits <<= (v_dc_bl & 63u); +- v_n_bits -= v_dc_bl; +- } else { +- v_dc_code = ((uint32_t)((v_bits >> 55u))); +- v_dc_blm1 = 8u; +- v_bits <<= 9u; +- v_n_bits -= 9u; +- while (true) { +- v_dc_ht_slow = self->private_impl.f_huff_tables_slow[v_dc_h][v_dc_blm1]; +- if (v_dc_code < (v_dc_ht_slow >> 8u)) { +- v_dc_symbol = (15u & ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_dc_h][(255u & ((uint32_t)(v_dc_code + v_dc_ht_slow)))]))); +- v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; +- break; +- } +- v_dc_code = (((uint32_t)(v_dc_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); +- v_bits <<= 1u; +- v_n_bits -= 1u; +- v_dc_blm1 = ((v_dc_blm1 + 1u) & 15u); +- if (v_dc_blm1 == 0u) { +- v_dc_symbol = 0u; +- v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; +- break; +- } +- } +- } +- v_dc_value = ((uint16_t)(((v_bits >> 32u) >> (32u - v_dc_symbol)))); +- v_dc_value += (v_dc_extend & (((uint16_t)(wuffs_base__utility__sign_extend_rshift_u64(v_bits, 63u))) ^ 65535u)); +- v_bits <<= v_dc_symbol; +- v_n_bits -= v_dc_symbol; +- v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[self->private_impl.f_mcu_current_block]]; +- self->private_impl.f_mcu_previous_dc_values[v_csel] += v_dc_value; +- self->private_data.f_mcu_blocks[self->private_impl.f_mcu_current_block][0u] = ((uint16_t)(self->private_impl.f_mcu_previous_dc_values[v_csel] << self->private_impl.f_scan_al)); +- } while (0); +- self->private_impl.f_mcu_current_block += 1u; +- } +- self->private_impl.f_mcu_current_block = 0u; +- } while (0); +- label__goto_done__break:; +- v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); +- if (v_pos > self->private_impl.f_bitstream_wi) { +- v_ret = 2u; +- } else { +- self->private_impl.f_bitstream_ri = v_pos; ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[0u] + 16u)) >> 5u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ } else { ++ v_in2 = v_intermediate[2u]; ++ v_in6 = v_intermediate[6u]; ++ v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); ++ v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); ++ v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); ++ v_in0 = v_intermediate[0u]; ++ v_in4 = v_intermediate[4u]; ++ v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); ++ v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); ++ v_rd0 = ((uint32_t)(v_rcp + v_rb2)); ++ v_rd1 = ((uint32_t)(v_rcm + v_rb6)); ++ v_rd2 = ((uint32_t)(v_rcm - v_rb6)); ++ v_rd3 = ((uint32_t)(v_rcp - v_rb2)); ++ v_in1 = v_intermediate[1u]; ++ v_in3 = v_intermediate[3u]; ++ v_in5 = v_intermediate[5u]; ++ v_in7 = v_intermediate[7u]; ++ v_ri51 = ((uint32_t)(v_in5 + v_in1)); ++ v_ri53 = ((uint32_t)(v_in5 + v_in3)); ++ v_ri71 = ((uint32_t)(v_in7 + v_in1)); ++ v_ri73 = ((uint32_t)(v_in7 + v_in3)); ++ v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); ++ v_rk1 = ((uint32_t)(v_in1 * 12299u)); ++ v_rk3 = ((uint32_t)(v_in3 * 25172u)); ++ v_rk5 = ((uint32_t)(v_in5 * 16819u)); ++ v_rk7 = ((uint32_t)(v_in7 * 2446u)); ++ v_ri51 *= 4294964100u; ++ v_ri53 *= 4294946301u; ++ v_ri71 *= 4294959923u; ++ v_ri73 *= 4294951227u; ++ v_rl51 = ((uint32_t)(v_ri51 + v_rj)); ++ v_rl73 = ((uint32_t)(v_ri73 + v_rj)); ++ v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); ++ v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); ++ v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); ++ v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); + } +- v_r = o_0_v_r; +- iop_v_r = o_0_iop_v_r; +- io0_v_r = o_0_io0_v_r; +- io1_v_r = o_0_io1_v_r; +- io2_v_r = o_0_io2_v_r; +- } +- self->private_impl.f_bitstream_bits = v_bits; +- self->private_impl.f_bitstream_n_bits = v_n_bits; +- return v_ret; +-} +- +-// -------- func jpeg.decoder.decode_mcu_progressive_dc_low_bit +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_jpeg__decoder__decode_mcu_progressive_dc_low_bit( +- wuffs_jpeg__decoder* self, +- wuffs_base__slice_u8 a_workbuf, +- uint32_t a_mx, +- uint32_t a_my) { +- uint32_t v_ret = 0; +- uint64_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint16_t v_one_lshift_scan_al = 0; +- wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_r = &u_r; +- const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint32_t v_pos = 0; +- +- v_bits = self->private_impl.f_bitstream_bits; +- v_n_bits = self->private_impl.f_bitstream_n_bits; +- v_one_lshift_scan_al = (((uint16_t)(1u)) << self->private_impl.f_scan_al); +- if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { +- return 2u; ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); + } +- { +- wuffs_base__io_buffer* o_0_v_r = v_r; +- const uint8_t *o_0_iop_v_r = iop_v_r; +- const uint8_t *o_0_io0_v_r = io0_v_r; +- const uint8_t *o_0_io1_v_r = io1_v_r; +- const uint8_t *o_0_io2_v_r = io2_v_r; +- v_r = wuffs_base__io_reader__set( +- &u_r, +- &iop_v_r, +- &io0_v_r, +- &io1_v_r, +- &io2_v_r, +- wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, +- self->private_impl.f_bitstream_ri, +- self->private_impl.f_bitstream_wi), +- ((uint64_t)(self->private_impl.f_bitstream_ri))); +- do { +- while (self->private_impl.f_mcu_current_block < self->private_impl.f_mcu_num_blocks) { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { +- v_ret = 1u; +- goto label__goto_done__break; +- } +- do { +- if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { +- v_ret = 2u; +- goto label__goto_done__break; +- } +- v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); +- iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); +- v_n_bits |= 56u; +- if ((v_bits >> 63u) != 0u) { +- self->private_data.f_mcu_blocks[self->private_impl.f_mcu_current_block][0u] |= v_one_lshift_scan_al; +- } +- v_bits <<= 1u; +- v_n_bits -= 1u; +- } while (0); +- self->private_impl.f_mcu_current_block += 1u; +- } +- self->private_impl.f_mcu_current_block = 0u; +- } while (0); +- label__goto_done__break:; +- v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); +- if (v_pos > self->private_impl.f_bitstream_wi) { +- v_ret = 2u; +- } else { +- self->private_impl.f_bitstream_ri = v_pos; ++ if (0u == (v_intermediate[9u] | ++ v_intermediate[10u] | ++ v_intermediate[11u] | ++ v_intermediate[12u] | ++ v_intermediate[13u] | ++ v_intermediate[14u] | ++ v_intermediate[15u])) { ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); + } +- v_r = o_0_v_r; +- iop_v_r = o_0_iop_v_r; +- io0_v_r = o_0_io0_v_r; +- io1_v_r = o_0_io1_v_r; +- io2_v_r = o_0_io2_v_r; +- } +- self->private_impl.f_bitstream_bits = v_bits; +- self->private_impl.f_bitstream_n_bits = v_n_bits; +- return v_ret; +-} +- +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JPEG) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON) +- +-// ---------------- Status Codes Implementations +- +-const char wuffs_json__error__bad_c0_control_code[] = "#json: bad C0 control code"; +-const char wuffs_json__error__bad_utf_8[] = "#json: bad UTF-8"; +-const char wuffs_json__error__bad_backslash_escape[] = "#json: bad backslash-escape"; +-const char wuffs_json__error__bad_input[] = "#json: bad input"; +-const char wuffs_json__error__bad_new_line_in_a_string[] = "#json: bad new-line in a string"; +-const char wuffs_json__error__bad_quirk_combination[] = "#json: bad quirk combination"; +-const char wuffs_json__error__unsupported_number_length[] = "#json: unsupported number length"; +-const char wuffs_json__error__unsupported_recursion_depth[] = "#json: unsupported recursion depth"; +-const char wuffs_json__error__internal_error_inconsistent_i_o[] = "#json: internal error: inconsistent I/O"; +- +-// ---------------- Private Consts +- +-#define WUFFS_JSON__DECODER_NUMBER_LENGTH_MAX_INCL 99 +- +-static const uint8_t +-WUFFS_JSON__LUT_BACKSLASHES[256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 3, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 162, 0, 0, 0, 0, 5, +- 0, 0, 0, 0, 0, 0, 0, 175, +- 7, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 4, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 220, 0, 0, 0, +- 0, 1, 136, 0, 0, 2, 140, 0, +- 0, 0, 0, 0, 0, 0, 138, 0, +- 0, 0, 141, 0, 137, 0, 6, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +-}; +- +-static const uint8_t +-WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 1, 3, 4, 5, 6, 7, 10, +-}; +- +-static const uint8_t +-WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_CHARS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 7, 27, 10, 63, 39, 11, 0, +-}; +- +-static const uint8_t +-WUFFS_JSON__LUT_CHARS[256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 128, 129, 130, 131, 132, 133, 134, 135, +- 136, 137, 138, 139, 140, 141, 142, 143, +- 144, 145, 146, 147, 148, 149, 150, 151, +- 152, 153, 154, 155, 156, 157, 158, 159, +- 0, 0, 1, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 2, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 16, 16, 16, 16, 16, 16, 16, 16, +- 16, 16, 16, 16, 16, 16, 16, 16, +- 16, 16, 16, 16, 16, 16, 16, 16, +- 16, 16, 16, 16, 16, 16, 16, 16, +- 16, 16, 16, 16, 16, 16, 16, 16, +- 16, 16, 16, 16, 16, 16, 16, 16, +- 16, 16, 16, 16, 16, 16, 16, 16, +- 16, 16, 16, 16, 16, 16, 16, 16, +- 32, 32, 3, 3, 3, 3, 3, 3, +- 3, 3, 3, 3, 3, 3, 3, 3, +- 3, 3, 3, 3, 3, 3, 3, 3, +- 3, 3, 3, 3, 3, 3, 3, 3, +- 4, 4, 4, 4, 4, 4, 4, 4, +- 4, 4, 4, 4, 4, 4, 4, 4, +- 5, 5, 5, 5, 5, 32, 32, 32, +- 32, 32, 32, 32, 32, 32, 32, 32, +-}; +- +-#define WUFFS_JSON__CLASS_WHITESPACE 0 +- +-#define WUFFS_JSON__CLASS_STRING 1 +- +-#define WUFFS_JSON__CLASS_COMMA 2 +- +-#define WUFFS_JSON__CLASS_COLON 3 +- +-#define WUFFS_JSON__CLASS_NUMBER 4 +- +-#define WUFFS_JSON__CLASS_OPEN_CURLY_BRACE 5 +- +-#define WUFFS_JSON__CLASS_CLOSE_CURLY_BRACE 6 +- +-#define WUFFS_JSON__CLASS_OPEN_SQUARE_BRACKET 7 +- +-#define WUFFS_JSON__CLASS_CLOSE_SQUARE_BRACKET 8 +- +-#define WUFFS_JSON__CLASS_FALSE 9 +- +-#define WUFFS_JSON__CLASS_TRUE 10 +- +-#define WUFFS_JSON__CLASS_NULL_NAN_INF 11 +- +-#define WUFFS_JSON__CLASS_COMMENT 12 +- +-#define WUFFS_JSON__EXPECT_VALUE 7858 +- +-#define WUFFS_JSON__EXPECT_NON_STRING_VALUE 7856 +- +-#define WUFFS_JSON__EXPECT_STRING 4098 +- +-#define WUFFS_JSON__EXPECT_COMMA 4100 +- +-#define WUFFS_JSON__EXPECT_COLON 4104 +- +-#define WUFFS_JSON__EXPECT_NUMBER 4112 +- +-#define WUFFS_JSON__EXPECT_CLOSE_CURLY_BRACE 4160 +- +-#define WUFFS_JSON__EXPECT_CLOSE_SQUARE_BRACKET 4352 +- +-static const uint8_t +-WUFFS_JSON__LUT_CLASSES[256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 0, 0, 15, 15, 0, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 0, 15, 1, 15, 15, 15, 15, 15, +- 15, 15, 15, 11, 2, 4, 15, 12, +- 4, 4, 4, 4, 4, 4, 4, 4, +- 4, 4, 3, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 11, 15, 15, 15, 15, 11, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 7, 15, 8, 15, 15, +- 15, 15, 15, 15, 15, 15, 9, 15, +- 15, 11, 15, 15, 15, 15, 11, 15, +- 15, 15, 15, 15, 10, 15, 15, 15, +- 15, 15, 15, 5, 15, 6, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +- 15, 15, 15, 15, 15, 15, 15, 15, +-}; +- +-static const uint8_t +-WUFFS_JSON__LUT_DECIMAL_DIGITS[256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 128, 129, 130, 131, 132, 133, 134, 135, +- 136, 137, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +-}; +- +-static const uint8_t +-WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 128, 129, 130, 131, 132, 133, 134, 135, +- 136, 137, 0, 0, 0, 0, 0, 0, +- 0, 138, 139, 140, 141, 142, 143, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 138, 139, 140, 141, 142, 143, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +-}; +- +-#define WUFFS_JSON__QUIRKS_BASE 1225364480 +- +-#define WUFFS_JSON__QUIRKS_COUNT 21 +- +-// ---------------- Private Initializer Prototypes +- +-// ---------------- Private Function Prototypes +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_json__decoder__decode_number( +- wuffs_json__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_json__decoder__decode_digits( +- wuffs_json__decoder* self, +- wuffs_base__io_buffer* a_src, +- uint32_t a_n); +- +-WUFFS_BASE__GENERATED_C_CODE +-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__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_json__decoder__decode_comment( +- wuffs_json__decoder* self, +- wuffs_base__token_buffer* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_json__decoder__decode_inf_nan( +- wuffs_json__decoder* self, +- wuffs_base__token_buffer* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_json__decoder__decode_trailer( +- wuffs_json__decoder* self, +- wuffs_base__token_buffer* a_dst, +- wuffs_base__io_buffer* a_src); +- +-// ---------------- VTables +- +-const wuffs_base__token_decoder__func_ptrs +-wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__token_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__slice_u8))(&wuffs_json__decoder__decode_tokens), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_json__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_json__decoder__history_retain_length), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_json__decoder__set_quirk), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_json__decoder__workbuf_len), +-}; +- +-// ---------------- Initializer Implementations +- +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_json__decoder__initialize( +- wuffs_json__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[8u] + 16u)) >> 5u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ } else { ++ v_in2 = v_intermediate[10u]; ++ v_in6 = v_intermediate[14u]; ++ v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); ++ v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); ++ v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); ++ v_in0 = v_intermediate[8u]; ++ v_in4 = v_intermediate[12u]; ++ v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); ++ v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); ++ v_rd0 = ((uint32_t)(v_rcp + v_rb2)); ++ v_rd1 = ((uint32_t)(v_rcm + v_rb6)); ++ v_rd2 = ((uint32_t)(v_rcm - v_rb6)); ++ v_rd3 = ((uint32_t)(v_rcp - v_rb2)); ++ v_in1 = v_intermediate[9u]; ++ v_in3 = v_intermediate[11u]; ++ v_in5 = v_intermediate[13u]; ++ v_in7 = v_intermediate[15u]; ++ v_ri51 = ((uint32_t)(v_in5 + v_in1)); ++ v_ri53 = ((uint32_t)(v_in5 + v_in3)); ++ v_ri71 = ((uint32_t)(v_in7 + v_in1)); ++ v_ri73 = ((uint32_t)(v_in7 + v_in3)); ++ v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); ++ v_rk1 = ((uint32_t)(v_in1 * 12299u)); ++ v_rk3 = ((uint32_t)(v_in3 * 25172u)); ++ v_rk5 = ((uint32_t)(v_in5 * 16819u)); ++ v_rk7 = ((uint32_t)(v_in7 * 2446u)); ++ v_ri51 *= 4294964100u; ++ v_ri53 *= 4294946301u; ++ v_ri71 *= 4294959923u; ++ v_ri73 *= 4294951227u; ++ v_rl51 = ((uint32_t)(v_ri51 + v_rj)); ++ v_rl73 = ((uint32_t)(v_ri73 + v_rj)); ++ v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); ++ v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); ++ v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); ++ v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); + } +- +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ if (0u == (v_intermediate[17u] | ++ v_intermediate[18u] | ++ v_intermediate[19u] | ++ v_intermediate[20u] | ++ v_intermediate[21u] | ++ v_intermediate[22u] | ++ v_intermediate[23u])) { ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); + } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[16u] + 16u)) >> 5u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); + } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ v_in2 = v_intermediate[18u]; ++ v_in6 = v_intermediate[22u]; ++ v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); ++ v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); ++ v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); ++ v_in0 = v_intermediate[16u]; ++ v_in4 = v_intermediate[20u]; ++ v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); ++ v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); ++ v_rd0 = ((uint32_t)(v_rcp + v_rb2)); ++ v_rd1 = ((uint32_t)(v_rcm + v_rb6)); ++ v_rd2 = ((uint32_t)(v_rcm - v_rb6)); ++ v_rd3 = ((uint32_t)(v_rcp - v_rb2)); ++ v_in1 = v_intermediate[17u]; ++ v_in3 = v_intermediate[19u]; ++ v_in5 = v_intermediate[21u]; ++ v_in7 = v_intermediate[23u]; ++ v_ri51 = ((uint32_t)(v_in5 + v_in1)); ++ v_ri53 = ((uint32_t)(v_in5 + v_in3)); ++ v_ri71 = ((uint32_t)(v_in7 + v_in1)); ++ v_ri73 = ((uint32_t)(v_in7 + v_in3)); ++ v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); ++ v_rk1 = ((uint32_t)(v_in1 * 12299u)); ++ v_rk3 = ((uint32_t)(v_in3 * 25172u)); ++ v_rk5 = ((uint32_t)(v_in5 * 16819u)); ++ v_rk7 = ((uint32_t)(v_in7 * 2446u)); ++ v_ri51 *= 4294964100u; ++ v_ri53 *= 4294946301u; ++ v_ri71 *= 4294959923u; ++ v_ri73 *= 4294951227u; ++ v_rl51 = ((uint32_t)(v_ri51 + v_rj)); ++ v_rl73 = ((uint32_t)(v_ri73 + v_rj)); ++ v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); ++ v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); ++ v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); ++ v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); + } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); + } +- +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name = +- wuffs_base__token_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers = +- (const void*)(&wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder); +- return wuffs_base__make_status(NULL); +-} +- +-wuffs_json__decoder* +-wuffs_json__decoder__alloc(void) { +- wuffs_json__decoder* x = +- (wuffs_json__decoder*)(calloc(sizeof(wuffs_json__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_json__decoder__initialize( +- x, sizeof(wuffs_json__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; +- } +- return x; +-} +- +-size_t +-sizeof__wuffs_json__decoder(void) { +- return sizeof(wuffs_json__decoder); +-} +- +-// ---------------- Function Implementations +- +-// -------- func json.decoder.get_quirk +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_json__decoder__get_quirk( +- const wuffs_json__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- uint32_t v_key = 0; +- +- if (a_key >= 1225364480u) { +- v_key = (a_key - 1225364480u); +- if (v_key < 21u) { +- if (self->private_impl.f_quirks[v_key]) { +- return 1u; +- } ++ if (0u == (v_intermediate[25u] | ++ v_intermediate[26u] | ++ v_intermediate[27u] | ++ v_intermediate[28u] | ++ v_intermediate[29u] | ++ v_intermediate[30u] | ++ v_intermediate[31u])) { ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); + } +- } +- return 0u; +-} +- +-// -------- func json.decoder.set_quirk +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_json__decoder__set_quirk( +- wuffs_json__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- +- if (a_key >= 1225364480u) { +- a_key -= 1225364480u; +- if (a_key < 21u) { +- self->private_impl.f_quirks[a_key] = (a_value > 0u); +- return wuffs_base__make_status(NULL); ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[24u] + 16u)) >> 5u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ } else { ++ v_in2 = v_intermediate[26u]; ++ v_in6 = v_intermediate[30u]; ++ v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); ++ v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); ++ v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); ++ v_in0 = v_intermediate[24u]; ++ v_in4 = v_intermediate[28u]; ++ v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); ++ v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); ++ v_rd0 = ((uint32_t)(v_rcp + v_rb2)); ++ v_rd1 = ((uint32_t)(v_rcm + v_rb6)); ++ v_rd2 = ((uint32_t)(v_rcm - v_rb6)); ++ v_rd3 = ((uint32_t)(v_rcp - v_rb2)); ++ v_in1 = v_intermediate[25u]; ++ v_in3 = v_intermediate[27u]; ++ v_in5 = v_intermediate[29u]; ++ v_in7 = v_intermediate[31u]; ++ v_ri51 = ((uint32_t)(v_in5 + v_in1)); ++ v_ri53 = ((uint32_t)(v_in5 + v_in3)); ++ v_ri71 = ((uint32_t)(v_in7 + v_in1)); ++ v_ri73 = ((uint32_t)(v_in7 + v_in3)); ++ v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); ++ v_rk1 = ((uint32_t)(v_in1 * 12299u)); ++ v_rk3 = ((uint32_t)(v_in3 * 25172u)); ++ v_rk5 = ((uint32_t)(v_in5 * 16819u)); ++ v_rk7 = ((uint32_t)(v_in7 * 2446u)); ++ v_ri51 *= 4294964100u; ++ v_ri53 *= 4294946301u; ++ v_ri71 *= 4294959923u; ++ v_ri73 *= 4294951227u; ++ v_rl51 = ((uint32_t)(v_ri51 + v_rj)); ++ v_rl73 = ((uint32_t)(v_ri73 + v_rj)); ++ v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); ++ v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); ++ v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); ++ v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); + } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); + } +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); +-} +- +-// -------- func json.decoder.history_retain_length +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_json__decoder__history_retain_length( +- const wuffs_json__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ if (0u == (v_intermediate[33u] | ++ v_intermediate[34u] | ++ v_intermediate[35u] | ++ v_intermediate[36u] | ++ v_intermediate[37u] | ++ v_intermediate[38u] | ++ v_intermediate[39u])) { ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[32u] + 16u)) >> 5u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ } else { ++ v_in2 = v_intermediate[34u]; ++ v_in6 = v_intermediate[38u]; ++ v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); ++ v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); ++ v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); ++ v_in0 = v_intermediate[32u]; ++ v_in4 = v_intermediate[36u]; ++ v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); ++ v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); ++ v_rd0 = ((uint32_t)(v_rcp + v_rb2)); ++ v_rd1 = ((uint32_t)(v_rcm + v_rb6)); ++ v_rd2 = ((uint32_t)(v_rcm - v_rb6)); ++ v_rd3 = ((uint32_t)(v_rcp - v_rb2)); ++ v_in1 = v_intermediate[33u]; ++ v_in3 = v_intermediate[35u]; ++ v_in5 = v_intermediate[37u]; ++ v_in7 = v_intermediate[39u]; ++ v_ri51 = ((uint32_t)(v_in5 + v_in1)); ++ v_ri53 = ((uint32_t)(v_in5 + v_in3)); ++ v_ri71 = ((uint32_t)(v_in7 + v_in1)); ++ v_ri73 = ((uint32_t)(v_in7 + v_in3)); ++ v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); ++ v_rk1 = ((uint32_t)(v_in1 * 12299u)); ++ v_rk3 = ((uint32_t)(v_in3 * 25172u)); ++ v_rk5 = ((uint32_t)(v_in5 * 16819u)); ++ v_rk7 = ((uint32_t)(v_in7 * 2446u)); ++ v_ri51 *= 4294964100u; ++ v_ri53 *= 4294946301u; ++ v_ri71 *= 4294959923u; ++ v_ri73 *= 4294951227u; ++ v_rl51 = ((uint32_t)(v_ri51 + v_rj)); ++ v_rl73 = ((uint32_t)(v_ri73 + v_rj)); ++ v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); ++ v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); ++ v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); ++ v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); + } +- +- return 0u; +-} +- +-// -------- func json.decoder.workbuf_len +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_json__decoder__workbuf_len( +- const wuffs_json__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ if (0u == (v_intermediate[41u] | ++ v_intermediate[42u] | ++ v_intermediate[43u] | ++ v_intermediate[44u] | ++ v_intermediate[45u] | ++ v_intermediate[46u] | ++ v_intermediate[47u])) { ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[40u] + 16u)) >> 5u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ } else { ++ v_in2 = v_intermediate[42u]; ++ v_in6 = v_intermediate[46u]; ++ v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); ++ v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); ++ v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); ++ v_in0 = v_intermediate[40u]; ++ v_in4 = v_intermediate[44u]; ++ v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); ++ v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); ++ v_rd0 = ((uint32_t)(v_rcp + v_rb2)); ++ v_rd1 = ((uint32_t)(v_rcm + v_rb6)); ++ v_rd2 = ((uint32_t)(v_rcm - v_rb6)); ++ v_rd3 = ((uint32_t)(v_rcp - v_rb2)); ++ v_in1 = v_intermediate[41u]; ++ v_in3 = v_intermediate[43u]; ++ v_in5 = v_intermediate[45u]; ++ v_in7 = v_intermediate[47u]; ++ v_ri51 = ((uint32_t)(v_in5 + v_in1)); ++ v_ri53 = ((uint32_t)(v_in5 + v_in3)); ++ v_ri71 = ((uint32_t)(v_in7 + v_in1)); ++ v_ri73 = ((uint32_t)(v_in7 + v_in3)); ++ v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); ++ v_rk1 = ((uint32_t)(v_in1 * 12299u)); ++ v_rk3 = ((uint32_t)(v_in3 * 25172u)); ++ v_rk5 = ((uint32_t)(v_in5 * 16819u)); ++ v_rk7 = ((uint32_t)(v_in7 * 2446u)); ++ v_ri51 *= 4294964100u; ++ v_ri53 *= 4294946301u; ++ v_ri71 *= 4294959923u; ++ v_ri73 *= 4294951227u; ++ v_rl51 = ((uint32_t)(v_ri51 + v_rj)); ++ v_rl73 = ((uint32_t)(v_ri73 + v_rj)); ++ v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); ++ v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); ++ v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); ++ v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ if (0u == (v_intermediate[49u] | ++ v_intermediate[50u] | ++ v_intermediate[51u] | ++ v_intermediate[52u] | ++ v_intermediate[53u] | ++ v_intermediate[54u] | ++ v_intermediate[55u])) { ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[48u] + 16u)) >> 5u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ } else { ++ v_in2 = v_intermediate[50u]; ++ v_in6 = v_intermediate[54u]; ++ v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); ++ v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); ++ v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); ++ v_in0 = v_intermediate[48u]; ++ v_in4 = v_intermediate[52u]; ++ v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); ++ v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); ++ v_rd0 = ((uint32_t)(v_rcp + v_rb2)); ++ v_rd1 = ((uint32_t)(v_rcm + v_rb6)); ++ v_rd2 = ((uint32_t)(v_rcm - v_rb6)); ++ v_rd3 = ((uint32_t)(v_rcp - v_rb2)); ++ v_in1 = v_intermediate[49u]; ++ v_in3 = v_intermediate[51u]; ++ v_in5 = v_intermediate[53u]; ++ v_in7 = v_intermediate[55u]; ++ v_ri51 = ((uint32_t)(v_in5 + v_in1)); ++ v_ri53 = ((uint32_t)(v_in5 + v_in3)); ++ v_ri71 = ((uint32_t)(v_in7 + v_in1)); ++ v_ri73 = ((uint32_t)(v_in7 + v_in3)); ++ v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); ++ v_rk1 = ((uint32_t)(v_in1 * 12299u)); ++ v_rk3 = ((uint32_t)(v_in3 * 25172u)); ++ v_rk5 = ((uint32_t)(v_in5 * 16819u)); ++ v_rk7 = ((uint32_t)(v_in7 * 2446u)); ++ v_ri51 *= 4294964100u; ++ v_ri53 *= 4294946301u; ++ v_ri71 *= 4294959923u; ++ v_ri73 *= 4294951227u; ++ v_rl51 = ((uint32_t)(v_ri51 + v_rj)); ++ v_rl73 = ((uint32_t)(v_ri73 + v_rj)); ++ v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); ++ v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); ++ v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); ++ v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); + } +- +- return wuffs_base__utility__empty_range_ii_u64(); ++ if (0u == (v_intermediate[57u] | ++ v_intermediate[58u] | ++ v_intermediate[59u] | ++ v_intermediate[60u] | ++ v_intermediate[61u] | ++ v_intermediate[62u] | ++ v_intermediate[63u])) { ++ if (8u > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(v_intermediate[56u] + 16u)) >> 5u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[2u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[3u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[4u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[5u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[6u] = a_dst_buffer.ptr[0u]; ++ a_dst_buffer.ptr[7u] = a_dst_buffer.ptr[0u]; ++ } else { ++ v_in2 = v_intermediate[58u]; ++ v_in6 = v_intermediate[62u]; ++ v_ra = ((uint32_t)(((uint32_t)(v_in2 + v_in6)) * 4433u)); ++ v_rb2 = ((uint32_t)(v_ra + ((uint32_t)(v_in2 * 6270u)))); ++ v_rb6 = ((uint32_t)(v_ra - ((uint32_t)(v_in6 * 15137u)))); ++ v_in0 = v_intermediate[56u]; ++ v_in4 = v_intermediate[60u]; ++ v_rcp = ((uint32_t)(((uint32_t)(v_in0 + v_in4)) << 13u)); ++ v_rcm = ((uint32_t)(((uint32_t)(v_in0 - v_in4)) << 13u)); ++ v_rd0 = ((uint32_t)(v_rcp + v_rb2)); ++ v_rd1 = ((uint32_t)(v_rcm + v_rb6)); ++ v_rd2 = ((uint32_t)(v_rcm - v_rb6)); ++ v_rd3 = ((uint32_t)(v_rcp - v_rb2)); ++ v_in1 = v_intermediate[57u]; ++ v_in3 = v_intermediate[59u]; ++ v_in5 = v_intermediate[61u]; ++ v_in7 = v_intermediate[63u]; ++ v_ri51 = ((uint32_t)(v_in5 + v_in1)); ++ v_ri53 = ((uint32_t)(v_in5 + v_in3)); ++ v_ri71 = ((uint32_t)(v_in7 + v_in1)); ++ v_ri73 = ((uint32_t)(v_in7 + v_in3)); ++ v_rj = ((uint32_t)(((uint32_t)(v_ri73 + v_ri51)) * 9633u)); ++ v_rk1 = ((uint32_t)(v_in1 * 12299u)); ++ v_rk3 = ((uint32_t)(v_in3 * 25172u)); ++ v_rk5 = ((uint32_t)(v_in5 * 16819u)); ++ v_rk7 = ((uint32_t)(v_in7 * 2446u)); ++ v_ri51 *= 4294964100u; ++ v_ri53 *= 4294946301u; ++ v_ri71 *= 4294959923u; ++ v_ri73 *= 4294951227u; ++ v_rl51 = ((uint32_t)(v_ri51 + v_rj)); ++ v_rl73 = ((uint32_t)(v_ri73 + v_rj)); ++ v_rk1 += ((uint32_t)(v_ri71 + v_rl51)); ++ v_rk3 += ((uint32_t)(v_ri53 + v_rl73)); ++ v_rk5 += ((uint32_t)(v_ri53 + v_rl51)); ++ v_rk7 += ((uint32_t)(v_ri71 + v_rl73)); ++ if (8u > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ a_dst_buffer.ptr[0u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 + v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[7u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd0 - v_rk1)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[1u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 + v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[6u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd1 - v_rk3)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[2u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 + v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[5u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd2 - v_rk5)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[3u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 + v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ a_dst_buffer.ptr[4u] = WUFFS_JPEG__BIAS_AND_CLAMP[((((uint32_t)(((uint32_t)(v_rd3 - v_rk7)) + 131072u)) >> 18u) & 1023u)]; ++ } ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func json.decoder.decode_tokens ++// ‼ WUFFS MULTI-FILE SECTION +x86_avx2 ++// -------- func jpeg.decoder.decode_idct_x86_avx2 + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2") + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_json__decoder__decode_tokens( +- wuffs_json__decoder* self, +- wuffs_base__token_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_vminor = 0; +- uint32_t v_number_length = 0; +- uint32_t v_number_status = 0; +- uint32_t v_string_length = 0; +- uint32_t v_whitespace_length = 0; +- uint32_t v_depth = 0; +- uint32_t v_stack_byte = 0; +- uint32_t v_stack_bit = 0; +- uint32_t v_match = 0; +- uint32_t v_c4 = 0; +- uint8_t v_c = 0; +- uint8_t v_backslash = 0; +- uint8_t v_char = 0; +- uint8_t v_class = 0; +- uint32_t v_multi_byte_utf8 = 0; +- uint8_t v_backslash_x_ok = 0; +- uint8_t v_backslash_x_value = 0; +- uint32_t v_backslash_x_string = 0; +- uint8_t v_uni4_ok = 0; +- uint64_t v_uni4_string = 0; +- uint32_t v_uni4_value = 0; +- uint32_t v_uni4_high_surrogate = 0; +- uint8_t v_uni8_ok = 0; +- uint64_t v_uni8_string = 0; +- uint32_t v_uni8_value = 0; +- uint32_t v_expect = 0; +- uint32_t v_expect_after_value = 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 && a_dst->data.ptr) { +- 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; +- } +- } +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__decode_idct_x86_avx2( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__slice_u8 a_dst_buffer, ++ uint64_t a_dst_stride, ++ uint32_t a_q) { ++ __m256i v_k_0000 = {0}; ++ __m256i v_k_8080 = {0}; ++ __m256i v_k_0000_0002 = {0}; ++ __m256i v_k_0001_FFFF = {0}; ++ __m256i v_k_0400_0000 = {0}; ++ __m256i v_k_29CF_1151_D630_1151 = {0}; ++ __m256i v_k_E333_133E_ADFD_1051 = {0}; ++ __m256i v_k_E6DC_25A1_1925_25A1 = {0}; ++ __m256i v_k_ECC1_E333_EFB0_ADFD = {0}; ++ __m128i v_az_coeffs = {0}; ++ __m256i v_az_ah00 = {0}; ++ __m256i v_az_ad00 = {0}; ++ __m256i v_az_eh00 = {0}; ++ __m256i v_az_adeh = {0}; ++ __m256i v_rows01 = {0}; ++ __m256i v_rows23 = {0}; ++ __m256i v_rows45 = {0}; ++ __m256i v_rows67 = {0}; ++ __m256i v_quants01 = {0}; ++ __m256i v_quants23 = {0}; ++ __m256i v_quants45 = {0}; ++ __m256i v_quants67 = {0}; ++ __m256i v_rows04 = {0}; ++ __m256i v_rows31 = {0}; ++ __m256i v_rows26 = {0}; ++ __m256i v_rows75 = {0}; ++ __m256i v_fp_rows62 = {0}; ++ __m256i v_fp_bq2662ad = {0}; ++ __m256i v_fp_bq2662eh = {0}; ++ __m256i v_fp_cb26ad = {0}; ++ __m256i v_fp_cb26eh = {0}; ++ __m256i v_fp_rows40pos = {0}; ++ __m256i v_fp_rows04neg = {0}; ++ __m256i v_fp_rows0pm4 = {0}; ++ __m256i v_fp_ccpmad = {0}; ++ __m256i v_fp_ccpmeh = {0}; ++ __m256i v_fp_cd01ad = {0}; ++ __m256i v_fp_cd01eh = {0}; ++ __m256i v_fp_cd32ad = {0}; ++ __m256i v_fp_cd32eh = {0}; ++ __m256i v_fp_sums7351 = {0}; ++ __m256i v_fp_sums5173 = {0}; ++ __m256i v_fp_ci73515173ad = {0}; ++ __m256i v_fp_ci73515173eh = {0}; ++ __m256i v_fp_cl7351ad = {0}; ++ __m256i v_fp_cl7351eh = {0}; ++ __m256i v_fp_rows13 = {0}; ++ __m256i v_fp_bq7153ad = {0}; ++ __m256i v_fp_bq7153eh = {0}; ++ __m256i v_fp_ck75ad = {0}; ++ __m256i v_fp_ck75eh = {0}; ++ __m256i v_fp_cl5173ad = {0}; ++ __m256i v_fp_cl5173eh = {0}; ++ __m256i v_fp_ck13ad = {0}; ++ __m256i v_fp_ck13eh = {0}; ++ __m256i v_intermediate01ad = {0}; ++ __m256i v_intermediate01eh = {0}; ++ __m256i v_intermediate01 = {0}; ++ __m256i v_intermediate32ad = {0}; ++ __m256i v_intermediate32eh = {0}; ++ __m256i v_intermediate32 = {0}; ++ __m256i v_intermediate45ad = {0}; ++ __m256i v_intermediate45eh = {0}; ++ __m256i v_intermediate45 = {0}; ++ __m256i v_intermediate76ad = {0}; ++ __m256i v_intermediate76eh = {0}; ++ __m256i v_intermediate76 = {0}; ++ __m256i v_ita0a1e0e1 = {0}; ++ __m256i v_ita2a3e2e3 = {0}; ++ __m256i v_ita4a5e4e5 = {0}; ++ __m256i v_ita6a7e6e7 = {0}; ++ __m256i v_ita0c0e0g0 = {0}; ++ __m256i v_ita1c1e1g1 = {0}; ++ __m256i v_ita4c4e4g4 = {0}; ++ __m256i v_ita5c5e5g5 = {0}; ++ __m256i v_ita0b0e0f0 = {0}; ++ __m256i v_ita4b4e4f4 = {0}; ++ __m256i v_itc0d0g0h0 = {0}; ++ __m256i v_itc4d4g4h4 = {0}; ++ __m256i v_intermediateae = {0}; ++ __m256i v_intermediatebf = {0}; ++ __m256i v_intermediatecg = {0}; ++ __m256i v_intermediatedh = {0}; ++ __m256i v_intermediatedb = {0}; ++ __m256i v_intermediatehf = {0}; ++ __m256i v_sp_cols62 = {0}; ++ __m256i v_sp_bq2662ad = {0}; ++ __m256i v_sp_bq2662eh = {0}; ++ __m256i v_sp_rb26ad = {0}; ++ __m256i v_sp_rb26eh = {0}; ++ __m256i v_sp_cols40pos = {0}; ++ __m256i v_sp_cols04neg = {0}; ++ __m256i v_sp_cols0pm4 = {0}; ++ __m256i v_sp_rcpmad = {0}; ++ __m256i v_sp_rcpmeh = {0}; ++ __m256i v_sp_rd01ad = {0}; ++ __m256i v_sp_rd01eh = {0}; ++ __m256i v_sp_rd32ad = {0}; ++ __m256i v_sp_rd32eh = {0}; ++ __m256i v_sp_sums7351 = {0}; ++ __m256i v_sp_sums5173 = {0}; ++ __m256i v_sp_ri73515173ad = {0}; ++ __m256i v_sp_ri73515173eh = {0}; ++ __m256i v_sp_rl7351ad = {0}; ++ __m256i v_sp_rl7351eh = {0}; ++ __m256i v_sp_cols13 = {0}; ++ __m256i v_sp_bq7153ad = {0}; ++ __m256i v_sp_bq7153eh = {0}; ++ __m256i v_sp_rk75ad = {0}; ++ __m256i v_sp_rk75eh = {0}; ++ __m256i v_sp_rl5173ad = {0}; ++ __m256i v_sp_rl5173eh = {0}; ++ __m256i v_sp_rk13ad = {0}; ++ __m256i v_sp_rk13eh = {0}; ++ __m256i v_final01ad = {0}; ++ __m256i v_final01eh = {0}; ++ __m256i v_final01 = {0}; ++ __m256i v_final32ad = {0}; ++ __m256i v_final32eh = {0}; ++ __m256i v_final32 = {0}; ++ __m256i v_final45ad = {0}; ++ __m256i v_final45eh = {0}; ++ __m256i v_final45 = {0}; ++ __m256i v_final76ad = {0}; ++ __m256i v_final76eh = {0}; ++ __m256i v_final76 = {0}; ++ __m256i v_fta0a1e0e1 = {0}; ++ __m256i v_fta2a3e2e3 = {0}; ++ __m256i v_fta4a5e4e5 = {0}; ++ __m256i v_fta6a7e6e7 = {0}; ++ __m256i v_fta0c0e0g0 = {0}; ++ __m256i v_fta1c1e1g1 = {0}; ++ __m256i v_fta4c4e4g4 = {0}; ++ __m256i v_fta5c5e5g5 = {0}; ++ __m256i v_fta0b0e0f0 = {0}; ++ __m256i v_ftc0d0g0h0 = {0}; ++ __m256i v_fta4b4e4f4 = {0}; ++ __m256i v_ftc4d4g4h4 = {0}; ++ __m256i v_finalae = {0}; ++ __m256i v_finalbf = {0}; ++ __m256i v_finalcg = {0}; ++ __m256i v_finaldh = {0}; ++ __m256i v_final0145 = {0}; ++ __m256i v_final2367 = {0}; ++ uint64_t v_final0 = 0; ++ uint64_t v_final1 = 0; ++ uint64_t v_final2 = 0; ++ uint64_t v_final3 = 0; ++ uint64_t v_final4 = 0; ++ uint64_t v_final5 = 0; ++ uint64_t v_final6 = 0; ++ uint64_t v_final7 = 0; ++ wuffs_base__slice_u8 v_remaining = {0}; + +- uint32_t coro_susp_point = self->private_impl.p_decode_tokens[0]; +- if (coro_susp_point) { +- v_depth = self->private_data.s_decode_tokens[0].v_depth; +- v_expect = self->private_data.s_decode_tokens[0].v_expect; +- v_expect_after_value = self->private_data.s_decode_tokens[0].v_expect_after_value; ++ if (8u > a_dst_stride) { ++ return wuffs_base__make_empty_struct(); + } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- if (self->private_impl.f_end_of_data) { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- if (self->private_impl.f_quirks[18u]) { +- if (self->private_impl.f_quirks[11u] || self->private_impl.f_quirks[12u] || self->private_impl.f_quirks[17u]) { +- status = wuffs_base__make_status(wuffs_json__error__bad_quirk_combination); +- goto exit; ++ v_k_0000 = _mm256_set_epi16((int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u), (int16_t)(0u)); ++ v_k_8080 = _mm256_set_epi16((int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u), (int16_t)(32896u)); ++ v_k_0000_0002 = _mm256_set_epi16((int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u), (int16_t)(2u), (int16_t)(0u)); ++ v_k_0001_FFFF = _mm256_set_epi16((int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(65535u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u), (int16_t)(1u)); ++ v_k_0400_0000 = _mm256_set_epi16((int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u), (int16_t)(0u), (int16_t)(1024u)); ++ v_k_29CF_1151_D630_1151 = _mm256_set_epi16((int16_t)(4433u), (int16_t)(54832u), (int16_t)(4433u), (int16_t)(54832u), (int16_t)(4433u), (int16_t)(54832u), (int16_t)(4433u), (int16_t)(54832u), (int16_t)(4433u), (int16_t)(10703u), (int16_t)(4433u), (int16_t)(10703u), (int16_t)(4433u), (int16_t)(10703u), (int16_t)(4433u), (int16_t)(10703u)); ++ v_k_E333_133E_ADFD_1051 = _mm256_set_epi16((int16_t)(4177u), (int16_t)(44541u), (int16_t)(4177u), (int16_t)(44541u), (int16_t)(4177u), (int16_t)(44541u), (int16_t)(4177u), (int16_t)(44541u), (int16_t)(4926u), (int16_t)(58163u), (int16_t)(4926u), (int16_t)(58163u), (int16_t)(4926u), (int16_t)(58163u), (int16_t)(4926u), (int16_t)(58163u)); ++ v_k_E6DC_25A1_1925_25A1 = _mm256_set_epi16((int16_t)(9633u), (int16_t)(6437u), (int16_t)(9633u), (int16_t)(6437u), (int16_t)(9633u), (int16_t)(6437u), (int16_t)(9633u), (int16_t)(6437u), (int16_t)(9633u), (int16_t)(59100u), (int16_t)(9633u), (int16_t)(59100u), (int16_t)(9633u), (int16_t)(59100u), (int16_t)(9633u), (int16_t)(59100u)); ++ v_k_ECC1_E333_EFB0_ADFD = _mm256_set_epi16((int16_t)(44541u), (int16_t)(61360u), (int16_t)(44541u), (int16_t)(61360u), (int16_t)(44541u), (int16_t)(61360u), (int16_t)(44541u), (int16_t)(61360u), (int16_t)(58163u), (int16_t)(60609u), (int16_t)(58163u), (int16_t)(60609u), (int16_t)(58163u), (int16_t)(60609u), (int16_t)(58163u), (int16_t)(60609u)); ++ do { ++ if (0u == (wuffs_base__peek_u64le__no_bounds_check((const uint8_t*)(const void*)(self->private_data.f_mcu_blocks[0u] + 8u)) | wuffs_base__peek_u64le__no_bounds_check((const uint8_t*)(const void*)(self->private_data.f_mcu_blocks[0u] + 16u)))) { ++ v_az_coeffs = _mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_or_si128(_mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 8u)), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 16u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 24u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 32u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 40u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 48u))), _mm_lddqu_si128((const __m128i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 56u))); ++ if (0u == ((uint64_t)(_mm_cvtsi128_si64(_mm_packs_epi16(v_az_coeffs, v_az_coeffs))))) { ++ v_rows01 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 0u)); ++ v_quants01 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 0u)); ++ v_rows01 = _mm256_mullo_epi16(v_rows01, v_quants01); ++ v_az_ah00 = _mm256_slli_epi16(v_rows01, (int32_t)(2u)); ++ v_az_ad00 = _mm256_unpacklo_epi16(v_az_ah00, v_az_ah00); ++ v_az_eh00 = _mm256_unpackhi_epi16(v_az_ah00, v_az_ah00); ++ v_az_adeh = _mm256_inserti128_si256(v_az_ad00, _mm256_castsi256_si128(v_az_eh00), (int32_t)(1u)); ++ v_intermediateae = _mm256_shuffle_epi32(v_az_adeh, (int32_t)(0u)); ++ v_intermediatebf = _mm256_shuffle_epi32(v_az_adeh, (int32_t)(85u)); ++ v_intermediatecg = _mm256_shuffle_epi32(v_az_adeh, (int32_t)(170u)); ++ v_intermediatedh = _mm256_shuffle_epi32(v_az_adeh, (int32_t)(255u)); ++ break; + } + } +- if (self->private_impl.f_quirks[15u] || self->private_impl.f_quirks[16u]) { +- 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_rows01 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 0u)); ++ v_rows23 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 16u)); ++ v_rows45 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 32u)); ++ v_rows67 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_data.f_mcu_blocks[0u] + 48u)); ++ v_quants01 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 0u)); ++ v_quants23 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 16u)); ++ v_quants45 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 32u)); ++ v_quants67 = _mm256_lddqu_si256((const __m256i*)(const void*)(self->private_impl.f_quant_tables[a_q] + 48u)); ++ v_rows01 = _mm256_mullo_epi16(v_rows01, v_quants01); ++ v_rows23 = _mm256_mullo_epi16(v_rows23, v_quants23); ++ v_rows45 = _mm256_mullo_epi16(v_rows45, v_quants45); ++ v_rows67 = _mm256_mullo_epi16(v_rows67, v_quants67); ++ v_rows04 = _mm256_permute2x128_si256(v_rows01, v_rows45, (int32_t)(32u)); ++ v_rows31 = _mm256_permute2x128_si256(v_rows23, v_rows01, (int32_t)(49u)); ++ v_rows26 = _mm256_permute2x128_si256(v_rows23, v_rows67, (int32_t)(32u)); ++ v_rows75 = _mm256_permute2x128_si256(v_rows67, v_rows45, (int32_t)(49u)); ++ v_fp_rows62 = _mm256_permute2x128_si256(v_rows26, v_rows26, (int32_t)(1u)); ++ v_fp_bq2662ad = _mm256_unpacklo_epi16(v_rows26, v_fp_rows62); ++ v_fp_bq2662eh = _mm256_unpackhi_epi16(v_rows26, v_fp_rows62); ++ v_fp_cb26ad = _mm256_madd_epi16(v_fp_bq2662ad, v_k_29CF_1151_D630_1151); ++ v_fp_cb26eh = _mm256_madd_epi16(v_fp_bq2662eh, v_k_29CF_1151_D630_1151); ++ v_fp_rows40pos = _mm256_permute2x128_si256(v_rows04, v_rows04, (int32_t)(1u)); ++ v_fp_rows04neg = _mm256_sign_epi16(v_rows04, v_k_0001_FFFF); ++ v_fp_rows0pm4 = _mm256_add_epi16(v_fp_rows40pos, v_fp_rows04neg); ++ v_fp_ccpmad = _mm256_srai_epi32(_mm256_unpacklo_epi16(v_k_0000, v_fp_rows0pm4), (int32_t)(3u)); ++ v_fp_ccpmeh = _mm256_srai_epi32(_mm256_unpackhi_epi16(v_k_0000, v_fp_rows0pm4), (int32_t)(3u)); ++ v_fp_cd01ad = _mm256_add_epi32(v_fp_ccpmad, v_fp_cb26ad); ++ v_fp_cd01eh = _mm256_add_epi32(v_fp_ccpmeh, v_fp_cb26eh); ++ v_fp_cd32ad = _mm256_sub_epi32(v_fp_ccpmad, v_fp_cb26ad); ++ v_fp_cd32eh = _mm256_sub_epi32(v_fp_ccpmeh, v_fp_cb26eh); ++ v_fp_sums7351 = _mm256_add_epi16(v_rows75, v_rows31); ++ v_fp_sums5173 = _mm256_permute2x128_si256(v_fp_sums7351, v_fp_sums7351, (int32_t)(1u)); ++ v_fp_ci73515173ad = _mm256_unpacklo_epi16(v_fp_sums7351, v_fp_sums5173); ++ v_fp_ci73515173eh = _mm256_unpackhi_epi16(v_fp_sums7351, v_fp_sums5173); ++ v_fp_cl7351ad = _mm256_madd_epi16(v_fp_ci73515173ad, v_k_E6DC_25A1_1925_25A1); ++ v_fp_cl7351eh = _mm256_madd_epi16(v_fp_ci73515173eh, v_k_E6DC_25A1_1925_25A1); ++ v_fp_rows13 = _mm256_permute2x128_si256(v_rows31, v_rows31, (int32_t)(1u)); ++ v_fp_bq7153ad = _mm256_unpacklo_epi16(v_rows75, v_fp_rows13); ++ v_fp_bq7153eh = _mm256_unpackhi_epi16(v_rows75, v_fp_rows13); ++ v_fp_ck75ad = _mm256_add_epi32(_mm256_madd_epi16(v_fp_bq7153ad, v_k_ECC1_E333_EFB0_ADFD), v_fp_cl7351ad); ++ v_fp_ck75eh = _mm256_add_epi32(_mm256_madd_epi16(v_fp_bq7153eh, v_k_ECC1_E333_EFB0_ADFD), v_fp_cl7351eh); ++ v_fp_cl5173ad = _mm256_permute2x128_si256(v_fp_cl7351ad, v_fp_cl7351ad, (int32_t)(1u)); ++ v_fp_cl5173eh = _mm256_permute2x128_si256(v_fp_cl7351eh, v_fp_cl7351eh, (int32_t)(1u)); ++ v_fp_ck13ad = _mm256_add_epi32(v_fp_cl5173ad, _mm256_madd_epi16(v_fp_bq7153ad, v_k_E333_133E_ADFD_1051)); ++ v_fp_ck13eh = _mm256_add_epi32(v_fp_cl5173eh, _mm256_madd_epi16(v_fp_bq7153eh, v_k_E333_133E_ADFD_1051)); ++ v_intermediate01ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_fp_cd01ad, v_fp_ck13ad), v_k_0400_0000), (int32_t)(11u)); ++ v_intermediate01eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_fp_cd01eh, v_fp_ck13eh), v_k_0400_0000), (int32_t)(11u)); ++ v_intermediate01 = _mm256_packs_epi32(v_intermediate01ad, v_intermediate01eh); ++ v_intermediate32ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_fp_cd32ad, v_fp_ck75ad), v_k_0400_0000), (int32_t)(11u)); ++ v_intermediate32eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_fp_cd32eh, v_fp_ck75eh), v_k_0400_0000), (int32_t)(11u)); ++ v_intermediate32 = _mm256_packs_epi32(v_intermediate32ad, v_intermediate32eh); ++ v_intermediate45ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_fp_cd32ad, v_fp_ck75ad), v_k_0400_0000), (int32_t)(11u)); ++ v_intermediate45eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_fp_cd32eh, v_fp_ck75eh), v_k_0400_0000), (int32_t)(11u)); ++ v_intermediate45 = _mm256_packs_epi32(v_intermediate45ad, v_intermediate45eh); ++ v_intermediate76ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_fp_cd01ad, v_fp_ck13ad), v_k_0400_0000), (int32_t)(11u)); ++ v_intermediate76eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_fp_cd01eh, v_fp_ck13eh), v_k_0400_0000), (int32_t)(11u)); ++ v_intermediate76 = _mm256_packs_epi32(v_intermediate76ad, v_intermediate76eh); ++ v_ita0a1e0e1 = _mm256_permute4x64_epi64(v_intermediate01, (int32_t)(216u)); ++ v_ita2a3e2e3 = _mm256_permute4x64_epi64(v_intermediate32, (int32_t)(114u)); ++ v_ita4a5e4e5 = _mm256_permute4x64_epi64(v_intermediate45, (int32_t)(216u)); ++ v_ita6a7e6e7 = _mm256_permute4x64_epi64(v_intermediate76, (int32_t)(114u)); ++ v_ita0c0e0g0 = _mm256_unpacklo_epi16(v_ita0a1e0e1, v_ita2a3e2e3); ++ v_ita1c1e1g1 = _mm256_unpackhi_epi16(v_ita0a1e0e1, v_ita2a3e2e3); ++ v_ita4c4e4g4 = _mm256_unpacklo_epi16(v_ita4a5e4e5, v_ita6a7e6e7); ++ v_ita5c5e5g5 = _mm256_unpackhi_epi16(v_ita4a5e4e5, v_ita6a7e6e7); ++ v_ita0b0e0f0 = _mm256_unpacklo_epi16(v_ita0c0e0g0, v_ita1c1e1g1); ++ v_itc0d0g0h0 = _mm256_unpackhi_epi16(v_ita0c0e0g0, v_ita1c1e1g1); ++ v_ita4b4e4f4 = _mm256_unpacklo_epi16(v_ita4c4e4g4, v_ita5c5e5g5); ++ v_itc4d4g4h4 = _mm256_unpackhi_epi16(v_ita4c4e4g4, v_ita5c5e5g5); ++ v_intermediateae = _mm256_unpacklo_epi64(v_ita0b0e0f0, v_ita4b4e4f4); ++ v_intermediatebf = _mm256_unpackhi_epi64(v_ita0b0e0f0, v_ita4b4e4f4); ++ v_intermediatecg = _mm256_unpacklo_epi64(v_itc0d0g0h0, v_itc4d4g4h4); ++ v_intermediatedh = _mm256_unpackhi_epi64(v_itc0d0g0h0, v_itc4d4g4h4); ++ } while (0); ++ v_intermediatedb = _mm256_permute2x128_si256(v_intermediatedh, v_intermediatebf, (int32_t)(32u)); ++ v_intermediatehf = _mm256_permute2x128_si256(v_intermediatedh, v_intermediatebf, (int32_t)(49u)); ++ v_sp_cols62 = _mm256_permute2x128_si256(v_intermediatecg, v_intermediatecg, (int32_t)(1u)); ++ v_sp_bq2662ad = _mm256_unpacklo_epi16(v_intermediatecg, v_sp_cols62); ++ v_sp_bq2662eh = _mm256_unpackhi_epi16(v_intermediatecg, v_sp_cols62); ++ v_sp_rb26ad = _mm256_madd_epi16(v_sp_bq2662ad, v_k_29CF_1151_D630_1151); ++ v_sp_rb26eh = _mm256_madd_epi16(v_sp_bq2662eh, v_k_29CF_1151_D630_1151); ++ v_sp_cols40pos = _mm256_permute2x128_si256(v_intermediateae, v_intermediateae, (int32_t)(1u)); ++ v_sp_cols04neg = _mm256_sign_epi16(v_intermediateae, v_k_0001_FFFF); ++ v_sp_cols0pm4 = _mm256_add_epi16(v_sp_cols40pos, v_sp_cols04neg); ++ v_sp_rcpmad = _mm256_srai_epi32(_mm256_unpacklo_epi16(v_k_0000, v_sp_cols0pm4), (int32_t)(3u)); ++ v_sp_rcpmeh = _mm256_srai_epi32(_mm256_unpackhi_epi16(v_k_0000, v_sp_cols0pm4), (int32_t)(3u)); ++ v_sp_rd01ad = _mm256_add_epi32(v_sp_rcpmad, v_sp_rb26ad); ++ v_sp_rd01eh = _mm256_add_epi32(v_sp_rcpmeh, v_sp_rb26eh); ++ v_sp_rd32ad = _mm256_sub_epi32(v_sp_rcpmad, v_sp_rb26ad); ++ v_sp_rd32eh = _mm256_sub_epi32(v_sp_rcpmeh, v_sp_rb26eh); ++ v_sp_sums7351 = _mm256_add_epi16(v_intermediatehf, v_intermediatedb); ++ v_sp_sums5173 = _mm256_permute2x128_si256(v_sp_sums7351, v_sp_sums7351, (int32_t)(1u)); ++ v_sp_ri73515173ad = _mm256_unpacklo_epi16(v_sp_sums7351, v_sp_sums5173); ++ v_sp_ri73515173eh = _mm256_unpackhi_epi16(v_sp_sums7351, v_sp_sums5173); ++ v_sp_rl7351ad = _mm256_madd_epi16(v_sp_ri73515173ad, v_k_E6DC_25A1_1925_25A1); ++ v_sp_rl7351eh = _mm256_madd_epi16(v_sp_ri73515173eh, v_k_E6DC_25A1_1925_25A1); ++ v_sp_cols13 = _mm256_permute2x128_si256(v_intermediatedb, v_intermediatedb, (int32_t)(1u)); ++ v_sp_bq7153ad = _mm256_unpacklo_epi16(v_intermediatehf, v_sp_cols13); ++ v_sp_bq7153eh = _mm256_unpackhi_epi16(v_intermediatehf, v_sp_cols13); ++ v_sp_rk75ad = _mm256_add_epi32(_mm256_madd_epi16(v_sp_bq7153ad, v_k_ECC1_E333_EFB0_ADFD), v_sp_rl7351ad); ++ v_sp_rk75eh = _mm256_add_epi32(_mm256_madd_epi16(v_sp_bq7153eh, v_k_ECC1_E333_EFB0_ADFD), v_sp_rl7351eh); ++ v_sp_rl5173ad = _mm256_permute2x128_si256(v_sp_rl7351ad, v_sp_rl7351ad, (int32_t)(1u)); ++ v_sp_rl5173eh = _mm256_permute2x128_si256(v_sp_rl7351eh, v_sp_rl7351eh, (int32_t)(1u)); ++ v_sp_rk13ad = _mm256_add_epi32(v_sp_rl5173ad, _mm256_madd_epi16(v_sp_bq7153ad, v_k_E333_133E_ADFD_1051)); ++ v_sp_rk13eh = _mm256_add_epi32(v_sp_rl5173eh, _mm256_madd_epi16(v_sp_bq7153eh, v_k_E333_133E_ADFD_1051)); ++ v_final01ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_sp_rd01ad, v_sp_rk13ad), v_k_0000_0002), (int32_t)(18u)); ++ v_final01eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_sp_rd01eh, v_sp_rk13eh), v_k_0000_0002), (int32_t)(18u)); ++ v_final01 = _mm256_packs_epi32(v_final01ad, v_final01eh); ++ v_final32ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_sp_rd32ad, v_sp_rk75ad), v_k_0000_0002), (int32_t)(18u)); ++ v_final32eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_add_epi32(v_sp_rd32eh, v_sp_rk75eh), v_k_0000_0002), (int32_t)(18u)); ++ v_final32 = _mm256_packs_epi32(v_final32ad, v_final32eh); ++ v_final45ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_sp_rd32ad, v_sp_rk75ad), v_k_0000_0002), (int32_t)(18u)); ++ v_final45eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_sp_rd32eh, v_sp_rk75eh), v_k_0000_0002), (int32_t)(18u)); ++ v_final45 = _mm256_packs_epi32(v_final45ad, v_final45eh); ++ v_final76ad = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_sp_rd01ad, v_sp_rk13ad), v_k_0000_0002), (int32_t)(18u)); ++ v_final76eh = _mm256_srai_epi32(_mm256_add_epi32(_mm256_sub_epi32(v_sp_rd01eh, v_sp_rk13eh), v_k_0000_0002), (int32_t)(18u)); ++ v_final76 = _mm256_packs_epi32(v_final76ad, v_final76eh); ++ v_fta0a1e0e1 = _mm256_permute4x64_epi64(v_final01, (int32_t)(216u)); ++ v_fta2a3e2e3 = _mm256_permute4x64_epi64(v_final32, (int32_t)(114u)); ++ v_fta4a5e4e5 = _mm256_permute4x64_epi64(v_final45, (int32_t)(216u)); ++ v_fta6a7e6e7 = _mm256_permute4x64_epi64(v_final76, (int32_t)(114u)); ++ v_fta0c0e0g0 = _mm256_unpacklo_epi16(v_fta0a1e0e1, v_fta2a3e2e3); ++ v_fta1c1e1g1 = _mm256_unpackhi_epi16(v_fta0a1e0e1, v_fta2a3e2e3); ++ v_fta4c4e4g4 = _mm256_unpacklo_epi16(v_fta4a5e4e5, v_fta6a7e6e7); ++ v_fta5c5e5g5 = _mm256_unpackhi_epi16(v_fta4a5e4e5, v_fta6a7e6e7); ++ v_fta0b0e0f0 = _mm256_unpacklo_epi16(v_fta0c0e0g0, v_fta1c1e1g1); ++ v_ftc0d0g0h0 = _mm256_unpackhi_epi16(v_fta0c0e0g0, v_fta1c1e1g1); ++ v_fta4b4e4f4 = _mm256_unpacklo_epi16(v_fta4c4e4g4, v_fta5c5e5g5); ++ v_ftc4d4g4h4 = _mm256_unpackhi_epi16(v_fta4c4e4g4, v_fta5c5e5g5); ++ v_finalae = _mm256_unpacklo_epi64(v_fta0b0e0f0, v_fta4b4e4f4); ++ v_finalbf = _mm256_unpackhi_epi64(v_fta0b0e0f0, v_fta4b4e4f4); ++ v_finalcg = _mm256_unpacklo_epi64(v_ftc0d0g0h0, v_ftc4d4g4h4); ++ v_finaldh = _mm256_unpackhi_epi64(v_ftc0d0g0h0, v_ftc4d4g4h4); ++ v_final0145 = _mm256_add_epi8(_mm256_packs_epi16(v_finalae, v_finalbf), v_k_8080); ++ v_final2367 = _mm256_add_epi8(_mm256_packs_epi16(v_finalcg, v_finaldh), v_k_8080); ++ v_final0 = ((uint64_t)(_mm256_extract_epi64(v_final0145, (int32_t)(0u)))); ++ v_final1 = ((uint64_t)(_mm256_extract_epi64(v_final0145, (int32_t)(1u)))); ++ v_final2 = ((uint64_t)(_mm256_extract_epi64(v_final2367, (int32_t)(0u)))); ++ v_final3 = ((uint64_t)(_mm256_extract_epi64(v_final2367, (int32_t)(1u)))); ++ v_final4 = ((uint64_t)(_mm256_extract_epi64(v_final0145, (int32_t)(2u)))); ++ v_final5 = ((uint64_t)(_mm256_extract_epi64(v_final0145, (int32_t)(3u)))); ++ v_final6 = ((uint64_t)(_mm256_extract_epi64(v_final2367, (int32_t)(2u)))); ++ v_final7 = ((uint64_t)(_mm256_extract_epi64(v_final2367, (int32_t)(3u)))); ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final0); ++ a_dst_buffer = v_remaining; ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final1); ++ a_dst_buffer = v_remaining; ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final2); ++ a_dst_buffer = v_remaining; ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final3); ++ a_dst_buffer = v_remaining; ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final4); ++ a_dst_buffer = v_remaining; ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final5); ++ a_dst_buffer = v_remaining; ++ if (a_dst_stride > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_dst_buffer, a_dst_stride); ++ wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final6); ++ a_dst_buffer = v_remaining; ++ if (8u > ((uint64_t)(a_dst_buffer.len))) { ++ return wuffs_base__make_empty_struct(); ++ } ++ wuffs_base__poke_u64le__no_bounds_check(a_dst_buffer.ptr, v_final7); ++ return wuffs_base__make_empty_struct(); ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++// ‼ WUFFS MULTI-FILE SECTION -x86_avx2 ++ ++// -------- func jpeg.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_jpeg__decoder__get_quirk( ++ const wuffs_jpeg__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (a_key == 2u) { ++ if (self->private_impl.f_use_lower_quality) { ++ return 18446744073709551615u; ++ } ++ } else if (a_key == 1220532224u) { ++ if (self->private_impl.f_reject_progressive_jpegs) { ++ return 1u; ++ } ++ } ++ return 0u; ++} ++ ++// -------- func jpeg.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_jpeg__decoder__set_quirk( ++ wuffs_jpeg__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (a_key == 2u) { ++ self->private_impl.f_use_lower_quality = (a_value >= 9223372036854775808u); ++ return wuffs_base__make_status(NULL); ++ } else if (a_key == 1220532224u) { ++ self->private_impl.f_reject_progressive_jpegs = (a_value != 0u); ++ return wuffs_base__make_status(NULL); ++ } ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func jpeg.decoder.decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_jpeg__decoder__decode_image_config( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_jpeg__decoder__do_decode_image_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func jpeg.decoder.do_decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__do_decode_image_config( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint8_t v_marker = 0; ++ uint32_t v_pixfmt = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_image_config; ++ if (coro_susp_point) { ++ v_marker = self->private_data.s_do_decode_image_config.v_marker; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (v_c8 != 255u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (v_c8 != 216u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_header); ++ goto exit; + } +- v_expect = 7858u; +- label__outer__continue:; + while (true) { + while (true) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- goto label__outer__continue; +- } +- v_whitespace_length = 0u; +- v_c = 0u; +- v_class = 0u; +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (v_whitespace_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_whitespace_length = 0u; +- } +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- goto label__outer__continue; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- v_class = WUFFS_JSON__LUT_CLASSES[v_c]; +- if (v_class != 0u) { +- break; +- } +- iop_a_src += 1u; +- if (v_whitespace_length >= 65534u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(65535u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_whitespace_length = 0u; +- goto label__outer__continue; ++ goto suspend; + } +- v_whitespace_length += 1u; ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; + } +- if (v_whitespace_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_whitespace_length = 0u; +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- goto label__outer__continue; ++ if (v_c8 == 255u) { ++ break; ++ } ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; + } +- if (0u == (v_expect & (((uint32_t)(1u)) << v_class))) { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; ++ if (v_c8 != 255u) { ++ v_marker = v_c8; ++ break; + } +- if (v_class == 1u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 1u; +- label__string_loop_outer__continue:; +- while (true) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); +- continue; +- } +- v_string_length = 0u; ++ } ++ if (v_marker == 0u) { ++ continue; ++ } else if ((208u <= v_marker) && (v_marker <= 217u)) { ++ if (v_marker <= 215u) { ++ continue; ++ } ++ } else { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint32_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_4 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); + while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (v_string_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- } +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); +- goto label__string_loop_outer__continue; ++ goto suspend; + } +- while (((uint64_t)(io2_a_src - iop_a_src)) > 4u) { +- v_c4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- if (0u != (WUFFS_JSON__LUT_CHARS[(255u & (v_c4 >> 0u))] | +- WUFFS_JSON__LUT_CHARS[(255u & (v_c4 >> 8u))] | +- WUFFS_JSON__LUT_CHARS[(255u & (v_c4 >> 16u))] | +- WUFFS_JSON__LUT_CHARS[(255u & (v_c4 >> 24u))])) { +- break; +- } +- iop_a_src += 4u; +- if (v_string_length > 65527u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)((v_string_length + 4u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- goto label__string_loop_outer__continue; +- } +- v_string_length += 4u; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); ++ if (num_bits_4 == 8) { ++ t_4 = ((uint32_t)(*scratch >> 48)); ++ break; + } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- v_char = WUFFS_JSON__LUT_CHARS[v_c]; +- if (v_char == 0u) { +- iop_a_src += 1u; +- if (v_string_length >= 65531u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(65532u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- goto label__string_loop_outer__continue; +- } +- v_string_length += 1u; +- continue; +- } else if (v_char == 1u) { +- if (v_string_length != 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- } +- goto label__string_loop_outer__break; +- } else if (v_char == 2u) { +- if (v_string_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- goto label__string_loop_outer__continue; +- } +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); +- goto label__string_loop_outer__continue; +- } +- v_c = ((uint8_t)((wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8u))); +- v_backslash = WUFFS_JSON__LUT_BACKSLASHES[v_c]; +- if ((v_backslash & 128u) != 0u) { +- iop_a_src += 2u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((6291456u | ((uint32_t)((v_backslash & 127u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } else if (v_backslash != 0u) { +- if (self->private_impl.f_quirks[WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[(v_backslash & 7u)]]) { +- iop_a_src += 2u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((6291456u | ((uint32_t)(WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_CHARS[(v_backslash & 7u)]))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } +- } else if (v_c == 117u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 6u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); +- goto label__string_loop_outer__continue; +- } +- v_uni4_string = (((uint64_t)(wuffs_base__peek_u48le__no_bounds_check(iop_a_src))) >> 16u); +- v_uni4_value = 0u; +- v_uni4_ok = 128u; +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 0u))]; +- v_uni4_ok &= v_c; +- v_uni4_value |= (((uint32_t)((v_c & 15u))) << 12u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 8u))]; +- v_uni4_ok &= v_c; +- v_uni4_value |= (((uint32_t)((v_c & 15u))) << 8u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 16u))]; +- v_uni4_ok &= v_c; +- v_uni4_value |= (((uint32_t)((v_c & 15u))) << 4u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 24u))]; +- v_uni4_ok &= v_c; +- v_uni4_value |= (((uint32_t)((v_c & 15u))) << 0u); +- if (v_uni4_ok == 0u) { +- } else if ((v_uni4_value < 55296u) || (57343u < v_uni4_value)) { +- iop_a_src += 6u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((6291456u | v_uni4_value))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(6u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } else if (v_uni4_value >= 56320u) { +- } else { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 12u) { +- if (a_src && a_src->meta.closed) { +- if (self->private_impl.f_quirks[20u]) { +- iop_a_src += 6u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(6u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } +- status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); +- goto label__string_loop_outer__continue; +- } +- v_uni4_string = (wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 4u) >> 16u); +- if (((255u & (v_uni4_string >> 0u)) != 92u) || ((255u & (v_uni4_string >> 8u)) != 117u)) { +- v_uni4_high_surrogate = 0u; +- v_uni4_value = 0u; +- v_uni4_ok = 0u; +- } else { +- v_uni4_high_surrogate = (65536u + ((v_uni4_value - 55296u) << 10u)); +- v_uni4_value = 0u; +- v_uni4_ok = 128u; +- v_uni4_string >>= 16u; +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 0u))]; +- v_uni4_ok &= v_c; +- v_uni4_value |= (((uint32_t)((v_c & 15u))) << 12u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 8u))]; +- v_uni4_ok &= v_c; +- v_uni4_value |= (((uint32_t)((v_c & 15u))) << 8u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 16u))]; +- v_uni4_ok &= v_c; +- v_uni4_value |= (((uint32_t)((v_c & 15u))) << 4u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 24u))]; +- v_uni4_ok &= v_c; +- v_uni4_value |= (((uint32_t)((v_c & 15u))) << 0u); +- } +- if ((v_uni4_ok != 0u) && (56320u <= v_uni4_value) && (v_uni4_value <= 57343u)) { +- v_uni4_value -= 56320u; +- iop_a_src += 12u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((6291456u | v_uni4_high_surrogate | v_uni4_value))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(12u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } +- } +- if (self->private_impl.f_quirks[20u]) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 6u) { +- status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- iop_a_src += 6u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(6u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } +- } else if ((v_c == 85u) && self->private_impl.f_quirks[2u]) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 10u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); +- goto label__string_loop_outer__continue; +- } +- v_uni8_string = wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 2u); +- v_uni8_value = 0u; +- v_uni8_ok = 128u; +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 0u))]; +- v_uni8_ok &= v_c; +- v_uni8_value |= (((uint32_t)((v_c & 15u))) << 28u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 8u))]; +- v_uni8_ok &= v_c; +- v_uni8_value |= (((uint32_t)((v_c & 15u))) << 24u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 16u))]; +- v_uni8_ok &= v_c; +- v_uni8_value |= (((uint32_t)((v_c & 15u))) << 20u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 24u))]; +- v_uni8_ok &= v_c; +- v_uni8_value |= (((uint32_t)((v_c & 15u))) << 16u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 32u))]; +- v_uni8_ok &= v_c; +- v_uni8_value |= (((uint32_t)((v_c & 15u))) << 12u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 40u))]; +- v_uni8_ok &= v_c; +- v_uni8_value |= (((uint32_t)((v_c & 15u))) << 8u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 48u))]; +- v_uni8_ok &= v_c; +- v_uni8_value |= (((uint32_t)((v_c & 15u))) << 4u); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 56u))]; +- v_uni8_ok &= v_c; +- v_uni8_value |= (((uint32_t)((v_c & 15u))) << 0u); +- if (v_uni8_ok == 0u) { +- } else if ((v_uni8_value < 55296u) || ((57343u < v_uni8_value) && (v_uni8_value <= 1114111u))) { +- iop_a_src += 10u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((6291456u | (v_uni8_value & 2097151u)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(10u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } else if (self->private_impl.f_quirks[20u]) { +- iop_a_src += 10u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(10u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } +- } else if ((v_c == 120u) && self->private_impl.f_quirks[9u]) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); +- goto label__string_loop_outer__continue; +- } +- v_backslash_x_string = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- v_backslash_x_ok = 128u; +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_backslash_x_string >> 16u))]; +- v_backslash_x_ok &= v_c; +- v_backslash_x_value = ((uint8_t)(((v_c & 15u) << 4u))); +- v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_backslash_x_string >> 24u))]; +- v_backslash_x_ok &= v_c; +- v_backslash_x_value = ((uint8_t)((v_backslash_x_value | (v_c & 15u)))); +- if ((v_backslash_x_ok == 0u) || ((v_backslash_x_string & 65535u) != 30812u)) { +- status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); +- goto exit; +- } +- iop_a_src += 4u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((6291456u | ((uint32_t)(v_backslash_x_value))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__string_loop_outer__continue; +- } +- status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); +- goto exit; +- } else if (v_char == 3u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { +- if (v_string_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- goto label__string_loop_outer__continue; +- } +- } +- if (a_src && a_src->meta.closed) { +- if (self->private_impl.f_quirks[20u]) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 1u; +- goto label__string_loop_outer__continue; +- } +- status = wuffs_base__make_status(wuffs_json__error__bad_utf_8); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); +- goto label__string_loop_outer__continue; +- } +- v_multi_byte_utf8 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- if ((v_multi_byte_utf8 & 49152u) == 32768u) { +- v_multi_byte_utf8 = ((1984u & ((uint32_t)(v_multi_byte_utf8 << 6u))) | (63u & (v_multi_byte_utf8 >> 8u))); +- iop_a_src += 2u; +- if (v_string_length >= 65528u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)((v_string_length + 2u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- goto label__string_loop_outer__continue; +- } +- v_string_length += 2u; +- continue; +- } +- } else if (v_char == 4u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 3u) { +- if (v_string_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- goto label__string_loop_outer__continue; +- } +- } +- if (a_src && a_src->meta.closed) { +- if (self->private_impl.f_quirks[20u]) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 1u; +- goto label__string_loop_outer__continue; +- } +- status = wuffs_base__make_status(wuffs_json__error__bad_utf_8); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12); +- goto label__string_loop_outer__continue; +- } +- v_multi_byte_utf8 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); +- if ((v_multi_byte_utf8 & 12632064u) == 8421376u) { +- v_multi_byte_utf8 = ((61440u & ((uint32_t)(v_multi_byte_utf8 << 12u))) | (4032u & (v_multi_byte_utf8 >> 2u)) | (63u & (v_multi_byte_utf8 >> 16u))); +- if ((2047u < v_multi_byte_utf8) && ((v_multi_byte_utf8 < 55296u) || (57343u < v_multi_byte_utf8))) { +- iop_a_src += 3u; +- if (v_string_length >= 65528u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)((v_string_length + 3u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- goto label__string_loop_outer__continue; +- } +- v_string_length += 3u; +- continue; +- } +- } +- } else if (v_char == 5u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { +- if (v_string_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- goto label__string_loop_outer__continue; +- } +- } +- if (a_src && a_src->meta.closed) { +- if (self->private_impl.f_quirks[20u]) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 1u; +- goto label__string_loop_outer__continue; +- } +- status = wuffs_base__make_status(wuffs_json__error__bad_utf_8); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(13); +- goto label__string_loop_outer__continue; +- } +- v_multi_byte_utf8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- if ((v_multi_byte_utf8 & 3233857536u) == 2155905024u) { +- v_multi_byte_utf8 = ((1835008u & ((uint32_t)(v_multi_byte_utf8 << 18u))) | +- (258048u & ((uint32_t)(v_multi_byte_utf8 << 4u))) | +- (4032u & (v_multi_byte_utf8 >> 10u)) | +- (63u & (v_multi_byte_utf8 >> 24u))); +- if ((65535u < v_multi_byte_utf8) && (v_multi_byte_utf8 <= 1114111u)) { +- iop_a_src += 4u; +- if (v_string_length >= 65528u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)((v_string_length + 4u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- goto label__string_loop_outer__continue; +- } +- v_string_length += 4u; +- continue; +- } +- } +- } +- if (v_string_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_string_length = 0u; +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- goto label__string_loop_outer__continue; +- } +- } +- if ((v_char & 128u) != 0u) { +- if (self->private_impl.f_quirks[0u]) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((6291456u | ((uint32_t)((v_char & 127u)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 1u; +- goto label__string_loop_outer__continue; +- } +- if (v_char == 138u) { +- status = wuffs_base__make_status(wuffs_json__error__bad_new_line_in_a_string); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_json__error__bad_c0_control_code); +- goto exit; +- } +- if (self->private_impl.f_quirks[20u]) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 1u; +- goto label__string_loop_outer__continue; +- } +- status = wuffs_base__make_status(wuffs_json__error__bad_utf_8); +- goto exit; ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)); + } + } +- label__string_loop_outer__break:; +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14); +- continue; +- } +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15); +- continue; +- } +- iop_a_src += 1u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- break; ++ self->private_impl.f_payload_length = t_4; ++ } ++ if (self->private_impl.f_payload_length < 2u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length -= 2u; ++ } ++ if (v_marker < 192u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); ++ goto exit; ++ } else if (v_marker < 208u) { ++ if (v_marker <= 194u) { ++ if ((v_marker == 194u) && self->private_impl.f_reject_progressive_jpegs) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__rejected_progressive_jpeg); ++ goto exit; ++ } else if (self->private_impl.f_sof_marker != 0u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ goto exit; + } +- if (0u == (v_expect & (((uint32_t)(1u)) << 4u))) { +- v_expect = 4104u; +- goto label__outer__continue; ++ self->private_impl.f_sof_marker = v_marker; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ status = wuffs_jpeg__decoder__decode_sof(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; + } + break; +- } else if (v_class == 2u) { +- iop_a_src += 1u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (0u == (v_expect & (((uint32_t)(1u)) << 8u))) { +- if (self->private_impl.f_quirks[13u]) { +- v_expect = 4162u; +- } else { +- v_expect = 4098u; +- } +- } else { +- if (self->private_impl.f_quirks[13u]) { +- v_expect = 8114u; +- } else { +- v_expect = 7858u; +- } ++ } else if (v_marker == 195u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_lossless_coding); ++ goto exit; ++ } else if (v_marker == 196u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } else if ((197u <= v_marker) && (v_marker <= 199u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_hierarchical_coding); ++ goto exit; ++ } else if (v_marker == 200u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_arithmetic_coding); ++ goto exit; ++ } ++ } else if (v_marker < 224u) { ++ if (v_marker < 218u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_marker); ++ goto exit; ++ } else if (v_marker == 218u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } else if (v_marker == 219u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- goto label__outer__continue; +- } else if (v_class == 3u) { +- iop_a_src += 1u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_expect = 7858u; +- goto label__outer__continue; +- } else if (v_class == 4u) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ status = wuffs_jpeg__decoder__decode_dqt(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ continue; ++ } else if (v_marker == 221u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ status = wuffs_jpeg__decoder__decode_dri(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ continue; ++ } else { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); ++ goto exit; ++ } ++ } else if (v_marker < 240u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ status = wuffs_jpeg__decoder__decode_appn(self, a_src, v_marker); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ continue; ++ } else { ++ if (v_marker == 254u) { ++ } else { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); ++ goto exit; ++ } ++ } ++ self->private_data.s_do_decode_image_config.scratch = self->private_impl.f_payload_length; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ if (self->private_data.s_do_decode_image_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_image_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_image_config.scratch; ++ self->private_impl.f_payload_length = 0u; ++ } ++ self->private_impl.choosy_decode_idct = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V3) ++ wuffs_base__cpu_arch__have_x86_avx2() ? &wuffs_jpeg__decoder__decode_idct_x86_avx2 : ++#endif ++ self->private_impl.choosy_decode_idct); ++ self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ if (a_dst != NULL) { ++ v_pixfmt = 536870920u; ++ if (self->private_impl.f_num_components > 1u) { ++ v_pixfmt = 2415954056u; ++ } ++ wuffs_base__image_config__set( ++ a_dst, ++ v_pixfmt, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ self->private_impl.f_frame_config_io_position, ++ true); ++ } ++ self->private_impl.f_call_sequence = 32u; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_do_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_image_config.v_marker = v_marker; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.decode_dqt ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_dqt( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint8_t v_q = 0; ++ uint32_t v_i = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_dqt; ++ if (coro_susp_point) { ++ v_q = self->private_data.s_decode_dqt.v_q; ++ v_i = self->private_data.s_decode_dqt.v_i; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (self->private_impl.f_payload_length > 0u) { ++ self->private_impl.f_payload_length -= 1u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (((uint8_t)(v_c8 & 15u)) > 3u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dqt_marker); ++ goto exit; ++ } ++ v_q = ((uint8_t)(v_c8 & 15u)); ++ if (((uint8_t)(v_c8 >> 4u)) == 1u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_precision); ++ goto exit; ++ } else if ((((uint8_t)(v_c8 >> 4u)) > 1u) || (self->private_impl.f_payload_length < 64u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dqt_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length -= 64u; ++ v_i = 0u; ++ while (v_i < 64u) { ++ v_i += 1u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint16_t t_1 = *iop_a_src++; ++ self->private_impl.f_quant_tables[v_q][WUFFS_JPEG__UNZIG[v_i]] = t_1; ++ } ++ } ++ self->private_impl.f_seen_dqt[v_q] = true; ++ if (self->private_impl.f_sof_marker == 0u) { ++ v_i = 0u; ++ while (v_i < 64u) { ++ self->private_impl.f_saved_quant_tables[v_q][v_i] = self->private_impl.f_quant_tables[v_q][v_i]; ++ v_i += 1u; ++ } ++ self->private_impl.f_saved_seen_dqt[v_q] = true; ++ } ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_dqt = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_dqt = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_dqt.v_q = v_q; ++ self->private_data.s_decode_dqt.v_i = v_i; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.decode_dri ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_dri( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_dri; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_payload_length != 2u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dri_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length = 0u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint16_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_0 = wuffs_base__peek_u16be__no_bounds_check(iop_a_src); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_dri.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_dri.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 8) { ++ t_0 = ((uint16_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ } ++ self->private_impl.f_restart_interval = t_0; ++ } ++ if (self->private_impl.f_sof_marker == 0u) { ++ self->private_impl.f_saved_restart_interval = self->private_impl.f_restart_interval; ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_dri = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_dri = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.decode_appn ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_appn( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint8_t a_marker) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_c32 = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_appn; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ do { ++ if (a_marker == 224u) { ++ if (self->private_impl.f_payload_length >= 5u) { ++ self->private_impl.f_payload_length -= 5u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_appn.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_appn.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ v_c32 = t_0; ++ } ++ if (v_c32 != 1179207242u) { ++ self->private_impl.f_payload_length = (65535u & (self->private_impl.f_payload_length + 1u)); ++ break; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ self->private_impl.f_is_jfif = (v_c8 == 0u); ++ } ++ } else if (a_marker == 238u) { ++ if (self->private_impl.f_payload_length >= 12u) { ++ self->private_impl.f_payload_length -= 12u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_appn.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_appn.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ if (num_bits_2 == 24) { ++ t_2 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)) << 56; ++ } ++ } ++ v_c32 = t_2; ++ } ++ if (v_c32 != 1651467329u) { ++ self->private_impl.f_payload_length = (65535u & (self->private_impl.f_payload_length + 8u)); ++ break; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_3 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_appn.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_appn.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; ++ if (num_bits_3 == 24) { ++ t_3 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ } ++ } ++ v_c32 = t_3; ++ } ++ if ((255u & v_c32) != 101u) { ++ self->private_impl.f_payload_length = (65535u & (self->private_impl.f_payload_length + 4u)); ++ break; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ uint32_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_appn.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_appn.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; ++ if (num_bits_4 == 24) { ++ t_4 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)) << 56; ++ } ++ } ++ v_c32 = t_4; ++ } ++ if ((v_c32 >> 24u) == 0u) { ++ self->private_impl.f_is_adobe = 1u; ++ } else { ++ self->private_impl.f_is_adobe = 2u; ++ } ++ } ++ } ++ } while (0); ++ self->private_data.s_decode_appn.scratch = self->private_impl.f_payload_length; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ if (self->private_data.s_decode_appn.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_decode_appn.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_decode_appn.scratch; ++ self->private_impl.f_payload_length = 0u; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_appn = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_appn = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.decode_sof ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_sof( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint8_t v_comp_h = 0; ++ uint8_t v_comp_v = 0; ++ uint32_t v_i = 0; ++ uint32_t v_j = 0; ++ bool v_has_h24 = false; ++ bool v_has_h3 = false; ++ bool v_has_v24 = false; ++ bool v_has_v3 = false; ++ uint32_t v_upper_bound = 0; ++ uint64_t v_wh0 = 0; ++ uint64_t v_wh1 = 0; ++ uint64_t v_wh2 = 0; ++ uint64_t v_wh3 = 0; ++ uint64_t v_progressive = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_sof; ++ if (coro_susp_point) { ++ v_i = self->private_data.s_decode_sof.v_i; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_payload_length < 6u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length -= 6u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (v_c8 == 8u) { ++ } else if (v_c8 == 12u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_precision_12_bits); ++ goto exit; ++ } else if (v_c8 == 16u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_precision_16_bits); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_precision); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_1 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_sof.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_sof.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); ++ if (num_bits_1 == 8) { ++ t_1 = ((uint32_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)); ++ } ++ } ++ self->private_impl.f_height = t_1; ++ } ++ if (self->private_impl.f_height == 0u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_implicit_height); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_2 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_sof.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_sof.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); ++ if (num_bits_2 == 8) { ++ t_2 = ((uint32_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)); ++ } ++ } ++ self->private_impl.f_width = t_2; ++ } ++ if (self->private_impl.f_width == 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ if ((v_c8 == 0u) || (v_c8 > 4u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ goto exit; ++ } else if (v_c8 == 2u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_color_model); ++ goto exit; ++ } ++ self->private_impl.f_num_components = ((uint32_t)(v_c8)); ++ if (self->private_impl.f_payload_length != (3u * self->private_impl.f_num_components)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length = 0u; ++ v_i = 0u; ++ while (v_i < self->private_impl.f_num_components) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ self->private_impl.f_components_c[v_i] = t_4; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; ++ } ++ v_comp_h = ((uint8_t)(v_c8 >> 4u)); ++ v_comp_v = ((uint8_t)(v_c8 & 15u)); ++ if ((v_comp_h == 0u) || ++ (v_comp_h > 4u) || ++ (v_comp_v == 0u) || ++ (v_comp_v > 4u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ goto exit; ++ } ++ self->private_impl.f_components_h[v_i] = v_comp_h; ++ if (self->private_impl.f_max_incl_components_h < self->private_impl.f_components_h[v_i]) { ++ self->private_impl.f_max_incl_components_h = self->private_impl.f_components_h[v_i]; ++ } ++ self->private_impl.f_components_v[v_i] = v_comp_v; ++ if (self->private_impl.f_max_incl_components_v < self->private_impl.f_components_v[v_i]) { ++ self->private_impl.f_max_incl_components_v = self->private_impl.f_components_v[v_i]; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; ++ } ++ if (v_c8 >= 4u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ goto exit; ++ } ++ self->private_impl.f_components_tq[v_i] = v_c8; ++ v_j = 0u; ++ while (v_j < v_i) { ++ if (self->private_impl.f_components_c[v_j] == self->private_impl.f_components_c[v_i]) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ goto exit; ++ } ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ if (self->private_impl.f_num_components == 1u) { ++ self->private_impl.f_max_incl_components_h = 1u; ++ self->private_impl.f_max_incl_components_v = 1u; ++ self->private_impl.f_components_h[0u] = 1u; ++ self->private_impl.f_components_v[0u] = 1u; ++ } else { ++ v_has_h24 = false; ++ v_has_h3 = false; ++ v_has_v24 = false; ++ v_has_v3 = false; ++ v_i = 0u; ++ while (v_i < self->private_impl.f_num_components) { ++ v_has_h24 = (v_has_h24 || (self->private_impl.f_components_h[v_i] == 2u) || (self->private_impl.f_components_h[v_i] == 4u)); ++ v_has_h3 = (v_has_h3 || (self->private_impl.f_components_h[v_i] == 3u)); ++ v_has_v24 = (v_has_v24 || (self->private_impl.f_components_v[v_i] == 2u) || (self->private_impl.f_components_v[v_i] == 4u)); ++ v_has_v3 = (v_has_v3 || (self->private_impl.f_components_v[v_i] == 3u)); ++ v_i += 1u; ++ } ++ if ((v_has_h24 && v_has_h3) || (v_has_v24 && v_has_v3)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_fractional_sampling); ++ goto exit; ++ } ++ if (self->private_impl.f_num_components == 4u) { ++ self->private_impl.f_is_rgb_or_cmyk = (self->private_impl.f_is_adobe < 2u); ++ } else { ++ if (self->private_impl.f_is_jfif) { ++ self->private_impl.f_is_rgb_or_cmyk = false; ++ } else if (self->private_impl.f_is_adobe > 0u) { ++ self->private_impl.f_is_rgb_or_cmyk = (self->private_impl.f_is_adobe == 1u); ++ } else { ++ self->private_impl.f_is_rgb_or_cmyk = ((self->private_impl.f_components_c[0u] == 82u) && (self->private_impl.f_components_c[1u] == 71u) && (self->private_impl.f_components_c[2u] == 66u)); ++ } ++ } ++ } ++ self->private_impl.f_width_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_width, 1u, self->private_impl.f_max_incl_components_h); ++ self->private_impl.f_height_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_height, 1u, self->private_impl.f_max_incl_components_v); ++ v_upper_bound = 65544u; ++ self->private_impl.f_components_workbuf_widths[0u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_width_in_mcus * ((uint32_t)(self->private_impl.f_components_h[0u])))); ++ self->private_impl.f_components_workbuf_widths[1u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_width_in_mcus * ((uint32_t)(self->private_impl.f_components_h[1u])))); ++ self->private_impl.f_components_workbuf_widths[2u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_width_in_mcus * ((uint32_t)(self->private_impl.f_components_h[2u])))); ++ self->private_impl.f_components_workbuf_widths[3u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_width_in_mcus * ((uint32_t)(self->private_impl.f_components_h[3u])))); ++ self->private_impl.f_components_workbuf_heights[0u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_height_in_mcus * ((uint32_t)(self->private_impl.f_components_v[0u])))); ++ self->private_impl.f_components_workbuf_heights[1u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_height_in_mcus * ((uint32_t)(self->private_impl.f_components_v[1u])))); ++ self->private_impl.f_components_workbuf_heights[2u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_height_in_mcus * ((uint32_t)(self->private_impl.f_components_v[2u])))); ++ self->private_impl.f_components_workbuf_heights[3u] = wuffs_base__u32__min(v_upper_bound, (8u * self->private_impl.f_height_in_mcus * ((uint32_t)(self->private_impl.f_components_v[3u])))); ++ v_wh0 = (((uint64_t)(self->private_impl.f_components_workbuf_widths[0u])) * ((uint64_t)(self->private_impl.f_components_workbuf_heights[0u]))); ++ v_wh1 = (((uint64_t)(self->private_impl.f_components_workbuf_widths[1u])) * ((uint64_t)(self->private_impl.f_components_workbuf_heights[1u]))); ++ v_wh2 = (((uint64_t)(self->private_impl.f_components_workbuf_widths[2u])) * ((uint64_t)(self->private_impl.f_components_workbuf_heights[2u]))); ++ v_wh3 = (((uint64_t)(self->private_impl.f_components_workbuf_widths[3u])) * ((uint64_t)(self->private_impl.f_components_workbuf_heights[3u]))); ++ v_progressive = 0u; ++ if (self->private_impl.f_sof_marker >= 194u) { ++ v_progressive = 2u; ++ v_i = 0u; ++ while (v_i < 4u) { ++ v_j = 0u; ++ while (v_j < 10u) { ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_i][v_j] = 16u; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ } ++ self->private_impl.f_components_workbuf_offsets[0u] = 0u; ++ self->private_impl.f_components_workbuf_offsets[1u] = (self->private_impl.f_components_workbuf_offsets[0u] + v_wh0); ++ self->private_impl.f_components_workbuf_offsets[2u] = (self->private_impl.f_components_workbuf_offsets[1u] + v_wh1); ++ self->private_impl.f_components_workbuf_offsets[3u] = (self->private_impl.f_components_workbuf_offsets[2u] + v_wh2); ++ self->private_impl.f_components_workbuf_offsets[4u] = (self->private_impl.f_components_workbuf_offsets[3u] + v_wh3); ++ self->private_impl.f_components_workbuf_offsets[5u] = (self->private_impl.f_components_workbuf_offsets[4u] + (v_wh0 * v_progressive)); ++ self->private_impl.f_components_workbuf_offsets[6u] = (self->private_impl.f_components_workbuf_offsets[5u] + (v_wh1 * v_progressive)); ++ self->private_impl.f_components_workbuf_offsets[7u] = (self->private_impl.f_components_workbuf_offsets[6u] + (v_wh2 * v_progressive)); ++ self->private_impl.f_components_workbuf_offsets[8u] = (self->private_impl.f_components_workbuf_offsets[7u] + (v_wh3 * v_progressive)); ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_sof = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_sof = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_sof.v_i = v_i; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.quantize_dimension ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__quantize_dimension( ++ const wuffs_jpeg__decoder* self, ++ uint32_t a_width, ++ uint8_t a_h, ++ uint8_t a_max_incl_h) { ++ uint32_t v_ratio = 0; ++ ++ v_ratio = 0u; ++ if (a_h > 0u) { ++ v_ratio = ((uint32_t)(((uint8_t)(a_max_incl_h / a_h)))); ++ } ++ if (v_ratio == 1u) { ++ return ((a_width + 7u) / 8u); ++ } else if (v_ratio == 2u) { ++ return ((a_width + 15u) / 16u); ++ } else if (v_ratio == 3u) { ++ return ((a_width + 23u) / 24u); ++ } ++ return ((a_width + 31u) / 32u); ++} ++ ++// -------- func jpeg.decoder.decode_frame_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_jpeg__decoder__decode_frame_config( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 2)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_jpeg__decoder__do_decode_frame_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func jpeg.decoder.do_decode_frame_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__do_decode_frame_config( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_jpeg__decoder__do_decode_image_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); ++ goto exit; ++ } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ self->private_impl.f_call_sequence = 96u; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height), ++ ((wuffs_base__flicks)(0u)), ++ 0u, ++ self->private_impl.f_frame_config_io_position, ++ 0u, ++ true, ++ false, ++ 4278190080u); ++ } ++ self->private_impl.f_call_sequence = 64u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_jpeg__decoder__decode_frame( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 3)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_ddf_status = wuffs_base__make_status(NULL); ++ wuffs_base__status v_swizzle_status = wuffs_base__make_status(NULL); ++ uint32_t v_scan_count = 0; ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ v_scan_count = self->private_impl.f_scan_count; ++ { ++ wuffs_base__status t_0 = wuffs_jpeg__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); ++ v_ddf_status = t_0; ++ } ++ if ((v_ddf_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ v_ddf_status = wuffs_base__make_status(wuffs_jpeg__error__truncated_input); ++ } ++ if ( ! self->private_impl.f_swizzle_immediately && (wuffs_base__status__is_error(&v_ddf_status) || (v_scan_count < self->private_impl.f_scan_count))) { ++ if (self->private_impl.f_sof_marker >= 194u) { ++ wuffs_jpeg__decoder__apply_progressive_idct(self, a_workbuf); ++ } ++ if (self->private_impl.f_num_components == 1u) { ++ v_swizzle_status = wuffs_jpeg__decoder__swizzle_gray(self, ++ a_dst, ++ a_workbuf, ++ 0u, ++ 4294967295u, ++ 0u, ++ 4294967295u, ++ ((uint64_t)(self->private_impl.f_components_workbuf_widths[0u]))); ++ } else { ++ v_swizzle_status = wuffs_jpeg__decoder__swizzle_colorful(self, ++ a_dst, ++ a_workbuf, ++ 0u, ++ 4294967295u, ++ 0u, ++ 4294967295u); ++ } ++ if (wuffs_base__status__is_error(&v_ddf_status)) { ++ status = v_ddf_status; ++ goto exit; ++ } else if (wuffs_base__status__is_error(&v_swizzle_status)) { ++ status = v_swizzle_status; ++ goto exit; ++ } ++ } ++ status = v_ddf_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func jpeg.decoder.do_decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__do_decode_frame( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_pixfmt = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint8_t v_c8 = 0; ++ uint8_t v_marker = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame; ++ if (coro_susp_point) { ++ v_marker = self->private_data.s_do_decode_frame.v_marker; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_jpeg__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ v_pixfmt = 536870920u; ++ if (self->private_impl.f_num_components > 1u) { ++ v_pixfmt = 2415954056u; ++ } ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), ++ wuffs_base__utility__make_pixel_format(v_pixfmt), ++ wuffs_base__utility__empty_slice_u8(), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ self->private_impl.f_swizzle_immediately = false; ++ if (self->private_impl.f_components_workbuf_offsets[8u] > ((uint64_t)(a_workbuf.len))) { ++ if (self->private_impl.f_sof_marker >= 194u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; ++ } ++ self->private_impl.f_swizzle_immediately = self->private_impl.f_use_lower_quality; ++ self->private_impl.f_swizzle_immediately_status = wuffs_base__make_status(NULL); ++ } else if (self->private_impl.f_components_workbuf_offsets[4u] < self->private_impl.f_components_workbuf_offsets[8u]) { ++ wuffs_private_impl__bulk_memset(a_workbuf.ptr + self->private_impl.f_components_workbuf_offsets[4u], (self->private_impl.f_components_workbuf_offsets[8u] - self->private_impl.f_components_workbuf_offsets[4u]), 0u); ++ } ++ if (self->private_impl.f_components_workbuf_offsets[4u] <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_private_impl__bulk_memset(a_workbuf.ptr, self->private_impl.f_components_workbuf_offsets[4u], 128u); ++ } ++ while (true) { ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (v_c8 == 255u) { ++ break; ++ } ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (v_c8 != 255u) { ++ v_marker = v_c8; ++ break; ++ } ++ } ++ if (v_marker == 0u) { ++ continue; ++ } else if ((208u <= v_marker) && (v_marker <= 217u)) { ++ if (v_marker <= 215u) { ++ continue; ++ } ++ } else { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_2 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_frame.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_frame.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); ++ if (num_bits_2 == 8) { ++ t_2 = ((uint32_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)); ++ } ++ } ++ self->private_impl.f_payload_length = t_2; ++ } ++ if (self->private_impl.f_payload_length < 2u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length -= 2u; ++ } ++ if (v_marker < 192u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); ++ goto exit; ++ } else if (v_marker < 208u) { ++ if (v_marker == 196u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ status = wuffs_jpeg__decoder__decode_dht(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ continue; ++ } else if (v_marker == 200u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sof_marker); ++ goto exit; ++ } else if (v_marker < 224u) { ++ if (v_marker < 217u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_marker); ++ goto exit; ++ } else if (v_marker == 217u) { ++ break; ++ } else if (v_marker == 218u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ status = wuffs_jpeg__decoder__decode_sos(self, a_dst, a_src, a_workbuf); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ continue; ++ } else if (v_marker == 219u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ status = wuffs_jpeg__decoder__decode_dqt(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ continue; ++ } else if (v_marker == 221u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ status = wuffs_jpeg__decoder__decode_dri(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ continue; ++ } else { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); ++ goto exit; ++ } ++ } else if (v_marker < 240u) { ++ } else { ++ if (v_marker == 254u) { ++ } else { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_marker); ++ goto exit; ++ } ++ } ++ self->private_data.s_do_decode_frame.scratch = self->private_impl.f_payload_length; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ if (self->private_data.s_do_decode_frame.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_frame.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_frame.scratch; ++ self->private_impl.f_payload_length = 0u; ++ } ++ self->private_impl.f_call_sequence = 96u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_frame.v_marker = v_marker; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.decode_dht ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_dht( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint8_t v_tc = 0; ++ uint8_t v_th = 0; ++ uint8_t v_tc4_th = 0; ++ uint32_t v_working_total_count = 0; ++ uint32_t v_total_count = 0; ++ uint32_t v_i = 0; ++ bool v_failed = false; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_dht; ++ if (coro_susp_point) { ++ v_tc4_th = self->private_data.s_decode_dht.v_tc4_th; ++ v_total_count = self->private_data.s_decode_dht.v_total_count; ++ v_i = self->private_data.s_decode_dht.v_i; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_sof_marker == 0u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } ++ while (self->private_impl.f_payload_length > 0u) { ++ if (self->private_impl.f_payload_length < 17u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length -= 17u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if ((((uint8_t)(v_c8 >> 4u)) > 1u) || (((uint8_t)(v_c8 & 15u)) > 3u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } ++ v_tc = ((uint8_t)(v_c8 >> 4u)); ++ v_th = ((uint8_t)(v_c8 & 15u)); ++ v_tc4_th = ((uint8_t)(((uint8_t)(((uint8_t)(v_tc * 4u)) | v_th)))); ++ if ((self->private_impl.f_sof_marker == 192u) && (((uint8_t)(v_tc4_th & 3u)) > 1u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } ++ v_i = 0u; ++ while (v_i < 16u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ self->private_data.f_dht_temp_counts[v_i] = t_1; ++ } ++ v_i += 1u; ++ } ++ v_working_total_count = 0u; ++ v_i = 0u; ++ while (v_i < 16u) { ++ v_working_total_count = ((v_working_total_count + ((uint32_t)(self->private_data.f_dht_temp_counts[v_i]))) & 65535u); ++ v_i += 1u; ++ } ++ if ((v_working_total_count <= 0u) || (256u < v_working_total_count)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } ++ v_total_count = v_working_total_count; ++ if (self->private_impl.f_payload_length < v_total_count) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length -= v_total_count; ++ v_i = 0u; ++ while (v_i < v_total_count) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ self->private_impl.f_huff_tables_symbols[v_tc4_th][v_i] = t_2; ++ } ++ v_i += 1u; ++ } ++ while (v_i < 256u) { ++ self->private_impl.f_huff_tables_symbols[v_tc4_th][v_i] = 0u; ++ v_i += 1u; ++ } ++ if (((uint8_t)(v_tc4_th & 4u)) == 0u) { ++ v_i = 0u; ++ while (v_i < v_total_count) { ++ if (self->private_impl.f_huff_tables_symbols[v_tc4_th][v_i] > 15u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } ++ v_i += 1u; ++ } ++ } ++ v_failed = wuffs_jpeg__decoder__calculate_huff_tables(self, v_tc4_th, v_total_count); ++ if (v_failed) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_dht_marker); ++ goto exit; ++ } ++ self->private_impl.f_seen_dht[v_tc4_th] = true; ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_dht = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_dht = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_dht.v_tc4_th = v_tc4_th; ++ self->private_data.s_decode_dht.v_total_count = v_total_count; ++ self->private_data.s_decode_dht.v_i = v_i; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.calculate_huff_tables ++ ++WUFFS_BASE__GENERATED_C_CODE ++static bool ++wuffs_jpeg__decoder__calculate_huff_tables( ++ wuffs_jpeg__decoder* self, ++ uint8_t a_tc4_th, ++ uint32_t a_total_count) { ++ uint32_t v_i = 0; ++ uint8_t v_j = 0; ++ uint8_t v_k = 0; ++ uint32_t v_bit_length_minus_one = 0; ++ uint8_t v_bit_length = 0; ++ uint32_t v_bit_string = 0; ++ uint32_t v_slow = 0; ++ uint8_t v_prefix = 0; ++ uint16_t v_fast = 0; ++ uint32_t v_reps = 0; ++ ++ v_i = 0u; ++ v_k = 0u; ++ v_bit_length_minus_one = 0u; ++ while (v_i < a_total_count) { ++ while (v_k >= self->private_data.f_dht_temp_counts[v_bit_length_minus_one]) { ++ v_k = 0u; ++ v_bit_length_minus_one = ((v_bit_length_minus_one + 1u) & 15u); ++ } ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_k += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ self->private_data.f_dht_temp_bit_lengths[v_i] = ((uint8_t)((v_bit_length_minus_one + 1u))); ++ v_i += 1u; ++ } ++ v_bit_length = 0u; ++ v_bit_string = 0u; ++ v_i = 0u; ++ while (v_i < a_total_count) { ++ while (v_bit_length < self->private_data.f_dht_temp_bit_lengths[v_i]) { ++ if (v_bit_length >= 16u) { ++ return true; ++ } ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_bit_length += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_bit_string <<= 1u; ++ } ++ self->private_data.f_dht_temp_bit_strings[v_i] = ((uint16_t)(v_bit_string)); ++ v_bit_string += 1u; ++ if ((v_bit_string >> v_bit_length) > 0u) { ++ return true; ++ } ++ v_i += 1u; ++ } ++ v_k = 0u; ++ v_bit_length_minus_one = 0u; ++ while (true) { ++ if (self->private_data.f_dht_temp_counts[v_bit_length_minus_one] == 0u) { ++ self->private_impl.f_huff_tables_slow[a_tc4_th][v_bit_length_minus_one] = 0u; ++ } else { ++ v_slow = (255u & ((uint32_t)(((uint32_t)(v_k)) - ((uint32_t)(self->private_data.f_dht_temp_bit_strings[v_k]))))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_k += self->private_data.f_dht_temp_counts[v_bit_length_minus_one]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ self->private_impl.f_huff_tables_slow[a_tc4_th][v_bit_length_minus_one] = (v_slow | ((((uint32_t)(self->private_data.f_dht_temp_bit_strings[((uint8_t)(v_k - 1u))])) + 1u) << 8u)); ++ } ++ v_bit_length_minus_one = ((v_bit_length_minus_one + 1u) & 15u); ++ if (v_bit_length_minus_one == 0u) { ++ break; ++ } ++ } ++ v_i = 0u; ++ while (v_i < 256u) { ++ self->private_impl.f_huff_tables_fast[a_tc4_th][v_i] = 65535u; ++ v_i += 1u; ++ } ++ v_j = 0u; ++ v_bit_length_minus_one = 0u; ++ while (v_bit_length_minus_one < 8u) { ++ v_k = 0u; ++ while (v_k < self->private_data.f_dht_temp_counts[v_bit_length_minus_one]) { ++ v_prefix = ((uint8_t)((((uint32_t)(self->private_data.f_dht_temp_bit_strings[v_j])) << (7u - v_bit_length_minus_one)))); ++ v_fast = ((uint16_t)(((((uint32_t)((v_bit_length_minus_one + 1u))) << 8u) | ((uint32_t)(self->private_impl.f_huff_tables_symbols[a_tc4_th][v_j]))))); ++ v_reps = (((uint32_t)(1u)) << (7u - v_bit_length_minus_one)); ++ while (v_reps > 0u) { ++ self->private_impl.f_huff_tables_fast[a_tc4_th][v_prefix] = v_fast; ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_prefix += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_reps -= 1u; ++ } ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_k += 1u; ++ v_j += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } ++ v_bit_length_minus_one += 1u; ++ } ++ return false; ++} ++ ++// -------- func jpeg.decoder.decode_sos ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__decode_sos( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_my = 0; ++ uint32_t v_mx = 0; ++ uint32_t v_decode_mcu_result = 0; ++ uint32_t v_bitstream_length = 0; ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_sos; ++ if (coro_susp_point) { ++ v_my = self->private_data.s_decode_sos.v_my; ++ v_mx = self->private_data.s_decode_sos.v_mx; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_scan_count >= 32u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_scan_count); ++ goto exit; ++ } else if ((self->private_impl.f_scan_count > 0u) && ! self->private_impl.f_expect_multiple_scans) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_scan_count); ++ goto exit; ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_jpeg__decoder__prepare_scan(self, a_src); ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_next_restart_marker = 0u; ++ self->private_impl.f_mcu_previous_dc_values[0u] = 0u; ++ self->private_impl.f_mcu_previous_dc_values[1u] = 0u; ++ self->private_impl.f_mcu_previous_dc_values[2u] = 0u; ++ self->private_impl.f_mcu_previous_dc_values[3u] = 0u; ++ self->private_impl.f_restarts_remaining = self->private_impl.f_restart_interval; ++ self->private_impl.f_eob_run = 0u; ++ self->private_impl.f_bitstream_bits = 0u; ++ self->private_impl.f_bitstream_n_bits = 0u; ++ self->private_impl.f_bitstream_ri = 0u; ++ self->private_impl.f_bitstream_wi = 0u; ++ self->private_impl.f_bitstream_padding = 12345u; ++ wuffs_jpeg__decoder__fill_bitstream(self, a_src); ++ v_my = 0u; ++ while (v_my < self->private_impl.f_scan_height_in_mcus) { ++ v_mx = 0u; ++ while (v_mx < self->private_impl.f_scan_width_in_mcus) { ++ self->private_impl.f_mcu_current_block = 0u; ++ self->private_impl.f_mcu_zig_index = ((uint32_t)(self->private_impl.f_scan_ss)); ++ if (self->private_impl.f_sof_marker >= 194u) { ++ wuffs_jpeg__decoder__load_mcu_blocks(self, v_mx, v_my, a_workbuf); ++ } ++ while (true) { ++ v_decode_mcu_result = wuffs_jpeg__decoder__decode_mcu(self, ++ a_dst, ++ a_workbuf, ++ v_mx, ++ v_my); ++ if (v_decode_mcu_result == 0u) { ++ break; ++ } else if (v_decode_mcu_result == 1u) { ++ } else if (v_decode_mcu_result == 2u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__internal_error_inconsistent_decoder_state); ++ goto exit; ++ } else { ++ status = self->private_impl.f_swizzle_immediately_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ while (true) { ++ v_bitstream_length = ((uint32_t)(self->private_impl.f_bitstream_wi - self->private_impl.f_bitstream_ri)); ++ wuffs_jpeg__decoder__fill_bitstream(self, a_src); ++ if (v_bitstream_length < ((uint32_t)(self->private_impl.f_bitstream_wi - self->private_impl.f_bitstream_ri))) { ++ break; ++ } else if (self->private_impl.f_bitstream_padding == 0u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } else if ((a_src && a_src->meta.closed) && ! self->private_impl.f_bitstream_is_closed) { ++ if (self->private_impl.f_bitstream_wi < 1024u) { ++ wuffs_private_impl__bulk_memset(&self->private_data.f_bitstream_buffer[self->private_impl.f_bitstream_wi], 264u, 0u); ++ self->private_impl.f_bitstream_wi += 264u; ++ self->private_impl.f_bitstream_is_closed = true; ++ } ++ break; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ } ++ } ++ if (self->private_impl.f_sof_marker >= 194u) { ++ wuffs_jpeg__decoder__save_mcu_blocks(self, v_mx, v_my, a_workbuf); ++ } ++ if (self->private_impl.f_restarts_remaining > 0u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_restarts_remaining -= 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ if (self->private_impl.f_restarts_remaining == 0u) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_jpeg__decoder__skip_past_the_next_restart_marker(self, a_src); ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_mcu_previous_dc_values[0u] = 0u; ++ self->private_impl.f_mcu_previous_dc_values[1u] = 0u; ++ self->private_impl.f_mcu_previous_dc_values[2u] = 0u; ++ self->private_impl.f_mcu_previous_dc_values[3u] = 0u; ++ self->private_impl.f_restarts_remaining = self->private_impl.f_restart_interval; ++ self->private_impl.f_eob_run = 0u; ++ self->private_impl.f_bitstream_bits = 0u; ++ self->private_impl.f_bitstream_n_bits = 0u; ++ self->private_impl.f_bitstream_ri = 0u; ++ self->private_impl.f_bitstream_wi = 0u; ++ self->private_impl.f_bitstream_padding = 12345u; ++ } ++ } ++ v_mx += 1u; ++ } ++ v_my += 1u; ++ } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_scan_count, 1u); ++ ++ ok: ++ self->private_impl.p_decode_sos = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_sos = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_sos.v_my = v_my; ++ self->private_data.s_decode_sos.v_mx = v_mx; ++ ++ goto exit; ++ exit: ++ return status; ++} ++ ++// -------- func jpeg.decoder.prepare_scan ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__prepare_scan( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_i = 0; ++ uint32_t v_j = 0; ++ uint32_t v_j_max_incl = 0; ++ bool v_failed = false; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_prepare_scan; ++ if (coro_susp_point) { ++ v_i = self->private_data.s_prepare_scan.v_i; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if ((self->private_impl.f_payload_length < 6u) || (self->private_impl.f_payload_length > 12u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if ((v_c8 < 1u) || (v_c8 > 4u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ self->private_impl.f_scan_num_components = ((uint32_t)(v_c8)); ++ if ((self->private_impl.f_scan_num_components > self->private_impl.f_num_components) || (self->private_impl.f_payload_length != (4u + (2u * self->private_impl.f_scan_num_components)))) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ self->private_impl.f_payload_length = 0u; ++ v_i = 0u; ++ while (v_i < self->private_impl.f_scan_num_components) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ v_j = 0u; ++ while (true) { ++ if (v_j >= self->private_impl.f_num_components) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ if (v_c8 == self->private_impl.f_components_c[v_j]) { ++ if ( ! self->private_impl.f_seen_dqt[self->private_impl.f_components_tq[v_j]]) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__missing_quantization_table); ++ goto exit; ++ } ++ self->private_impl.f_scan_comps_cselector[v_i] = ((uint8_t)(v_j)); ++ break; ++ } ++ v_j += 1u; ++ } ++ v_j = 0u; ++ while (v_j < v_i) { ++ if (self->private_impl.f_scan_comps_cselector[v_i] == self->private_impl.f_scan_comps_cselector[v_j]) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ v_j += 1u; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ if ((((uint8_t)(v_c8 >> 4u)) > 3u) || (((uint8_t)(v_c8 & 15u)) > 3u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ self->private_impl.f_scan_comps_td[v_i] = ((uint8_t)(v_c8 >> 4u)); ++ self->private_impl.f_scan_comps_ta[v_i] = ((uint8_t)(v_c8 & 15u)); ++ if (self->private_impl.f_sof_marker == 192u) { ++ if ((self->private_impl.f_scan_comps_td[v_i] > 1u) || (self->private_impl.f_scan_comps_ta[v_i] > 1u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ } ++ v_i += 1u; ++ } ++ if (self->private_impl.f_scan_count == 0u) { ++ self->private_impl.f_expect_multiple_scans = ((self->private_impl.f_sof_marker >= 194u) || (self->private_impl.f_scan_num_components < self->private_impl.f_num_components)); ++ } ++ if (self->private_impl.f_sof_marker < 194u) { ++ self->private_data.s_prepare_scan.scratch = 3u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (self->private_data.s_prepare_scan.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_prepare_scan.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_prepare_scan.scratch; ++ self->private_impl.f_scan_ss = 0u; ++ self->private_impl.f_scan_se = 63u; ++ self->private_impl.f_scan_ah = 0u; ++ self->private_impl.f_scan_al = 0u; ++ } else { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ if (v_c8 > 63u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ self->private_impl.f_scan_ss = v_c8; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; ++ } ++ if ((v_c8 > 63u) || (v_c8 < self->private_impl.f_scan_ss)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ self->private_impl.f_scan_se = v_c8; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; ++ } ++ if ((((uint8_t)(v_c8 >> 4u)) > 14u) || (((uint8_t)(v_c8 & 15u)) > 13u)) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ self->private_impl.f_scan_ah = ((uint8_t)(v_c8 >> 4u)); ++ self->private_impl.f_scan_al = ((uint8_t)(v_c8 & 15u)); ++ if (self->private_impl.f_scan_ah > 0u) { ++ if (((uint8_t)(self->private_impl.f_scan_ah - 1u)) != self->private_impl.f_scan_al) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ } ++ if (self->private_impl.f_scan_ss == 0u) { ++ if (self->private_impl.f_scan_se != 0u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } else if (self->private_impl.f_scan_ah == 0u) { ++ self->private_impl.choosy_decode_mcu = ( ++ &wuffs_jpeg__decoder__decode_mcu_progressive_dc_high_bits); ++ } else { ++ self->private_impl.choosy_decode_mcu = ( ++ &wuffs_jpeg__decoder__decode_mcu_progressive_dc_low_bit); ++ } ++ } else { ++ if (self->private_impl.f_scan_num_components != 1u) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } else if (self->private_impl.f_scan_ah == 0u) { ++ self->private_impl.choosy_decode_mcu = ( ++ &wuffs_jpeg__decoder__decode_mcu_progressive_ac_high_bits); ++ } else { ++ self->private_impl.choosy_decode_mcu = ( ++ &wuffs_jpeg__decoder__decode_mcu_progressive_ac_low_bit); ++ } ++ } ++ } ++ v_i = 0u; ++ while (v_i < self->private_impl.f_scan_num_components) { ++ if ((self->private_impl.f_scan_ss == 0u) && ! self->private_impl.f_seen_dht[((uint8_t)(0u | self->private_impl.f_scan_comps_td[v_i]))]) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ status = wuffs_jpeg__decoder__use_default_huffman_table(self, ((uint8_t)(0u | self->private_impl.f_scan_comps_td[v_i]))); ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ if ((self->private_impl.f_scan_se != 0u) && ! self->private_impl.f_seen_dht[((uint8_t)(4u | self->private_impl.f_scan_comps_ta[v_i]))]) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ status = wuffs_jpeg__decoder__use_default_huffman_table(self, ((uint8_t)(4u | self->private_impl.f_scan_comps_ta[v_i]))); ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ v_j = ((uint32_t)(self->private_impl.f_scan_ss)); ++ v_j_max_incl = ((uint32_t)(wuffs_base__u8__min(self->private_impl.f_scan_se, 9u))); ++ while (v_j <= v_j_max_incl) { ++ self->private_impl.f_block_smoothing_lowest_scan_al[self->private_impl.f_scan_comps_cselector[v_i]][v_j] = self->private_impl.f_scan_al; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ if (self->private_impl.f_scan_num_components == 1u) { ++ wuffs_jpeg__decoder__calculate_single_component_scan_fields(self); ++ } else { ++ v_failed = wuffs_jpeg__decoder__calculate_multiple_component_scan_fields(self); ++ if (v_failed) { ++ status = wuffs_base__make_status(wuffs_jpeg__error__bad_sos_marker); ++ goto exit; ++ } ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_prepare_scan = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_prepare_scan = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_prepare_scan.v_i = v_i; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.use_default_huffman_table ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__use_default_huffman_table( ++ wuffs_jpeg__decoder* self, ++ uint8_t a_tc4_th) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__slice_u8 v_data = {0}; ++ wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_r = &u_r; ++ const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ if (a_tc4_th == 0u) { ++ v_data = wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_JPEG__DEFAULT_HUFF_TABLE_DC_LUMA), 29); ++ } else if (a_tc4_th == 1u) { ++ v_data = wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_JPEG__DEFAULT_HUFF_TABLE_DC_CHROMA), 29); ++ } else if (a_tc4_th == 4u) { ++ v_data = wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_JPEG__DEFAULT_HUFF_TABLE_AC_LUMA), 179); ++ } else if (a_tc4_th == 5u) { ++ v_data = wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_JPEG__DEFAULT_HUFF_TABLE_AC_CHROMA), 179); ++ } else { ++ status = wuffs_base__make_status(wuffs_jpeg__error__missing_huffman_table); ++ goto exit; ++ } ++ { ++ wuffs_base__io_buffer* o_0_v_r = v_r; ++ const uint8_t* o_0_iop_v_r = iop_v_r; ++ const uint8_t* o_0_io0_v_r = io0_v_r; ++ const uint8_t* o_0_io1_v_r = io1_v_r; ++ const uint8_t* o_0_io2_v_r = io2_v_r; ++ v_r = wuffs_private_impl__io_reader__set( ++ &u_r, ++ &iop_v_r, ++ &io0_v_r, ++ &io1_v_r, ++ &io2_v_r, ++ v_data, ++ 0u); ++ self->private_impl.f_payload_length = ((uint32_t)((((uint64_t)(v_data.len)) & 65535u))); ++ { ++ wuffs_base__status t_0 = wuffs_jpeg__decoder__decode_dht(self, v_r); ++ v_status = t_0; ++ } ++ v_r = o_0_v_r; ++ iop_v_r = o_0_iop_v_r; ++ io0_v_r = o_0_io0_v_r; ++ io1_v_r = o_0_io1_v_r; ++ io2_v_r = o_0_io2_v_r; ++ } ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ ++ ok: ++ goto exit; ++ exit: ++ return status; ++} ++ ++// -------- func jpeg.decoder.calculate_single_component_scan_fields ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__calculate_single_component_scan_fields( ++ wuffs_jpeg__decoder* self) { ++ uint8_t v_csel = 0; ++ ++ self->private_impl.f_scan_comps_bx_offset[0u] = 0u; ++ self->private_impl.f_scan_comps_by_offset[0u] = 0u; ++ self->private_impl.f_mcu_num_blocks = 1u; ++ self->private_impl.f_mcu_blocks_sselector[0u] = 0u; ++ v_csel = self->private_impl.f_scan_comps_cselector[0u]; ++ self->private_impl.f_mcu_blocks_offset[0u] = self->private_impl.f_components_workbuf_offsets[v_csel]; ++ self->private_impl.f_mcu_blocks_mx_mul[0u] = 8u; ++ self->private_impl.f_mcu_blocks_my_mul[0u] = (8u * self->private_impl.f_components_workbuf_widths[v_csel]); ++ self->private_impl.f_mcu_blocks_dc_hselector[0u] = ((uint8_t)(0u | self->private_impl.f_scan_comps_td[0u])); ++ self->private_impl.f_mcu_blocks_ac_hselector[0u] = ((uint8_t)(4u | self->private_impl.f_scan_comps_ta[0u])); ++ self->private_impl.f_scan_width_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_width, self->private_impl.f_components_h[v_csel], self->private_impl.f_max_incl_components_h); ++ self->private_impl.f_scan_height_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_height, self->private_impl.f_components_v[v_csel], self->private_impl.f_max_incl_components_v); ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func jpeg.decoder.calculate_multiple_component_scan_fields ++ ++WUFFS_BASE__GENERATED_C_CODE ++static bool ++wuffs_jpeg__decoder__calculate_multiple_component_scan_fields( ++ wuffs_jpeg__decoder* self) { ++ uint32_t v_i = 0; ++ uint32_t v_h = 0; ++ uint32_t v_v = 0; ++ uint32_t v_hv = 0; ++ uint32_t v_total_hv = 0; ++ uint32_t v_b = 0; ++ uint32_t v_bx_offset = 0; ++ uint32_t v_by_offset = 0; ++ uint32_t v_sibo = 0; ++ uint8_t v_ssel = 0; ++ uint8_t v_csel = 0; ++ ++ v_total_hv = 0u; ++ v_i = 0u; ++ v_b = 0u; ++ v_bx_offset = 0u; ++ v_by_offset = 0u; ++ while (v_i < self->private_impl.f_scan_num_components) { ++ v_h = ((uint32_t)(self->private_impl.f_components_h[self->private_impl.f_scan_comps_cselector[v_i]])); ++ v_v = ((uint32_t)(self->private_impl.f_components_v[self->private_impl.f_scan_comps_cselector[v_i]])); ++ v_hv = (((uint32_t)(self->private_impl.f_components_h[self->private_impl.f_scan_comps_cselector[v_i]])) * ((uint32_t)(self->private_impl.f_components_v[self->private_impl.f_scan_comps_cselector[v_i]]))); ++ self->private_impl.f_swizzle_immediately_c_offsets[v_i] = ((uint32_t)(64u * v_total_hv)); ++ v_total_hv += v_hv; ++ while (v_hv > 0u) { ++ self->private_impl.f_scan_comps_bx_offset[(v_b & 15u)] = ((uint8_t)((v_bx_offset & 3u))); ++ self->private_impl.f_scan_comps_by_offset[(v_b & 15u)] = ((uint8_t)((v_by_offset & 3u))); ++ self->private_impl.f_mcu_blocks_sselector[(v_b & 15u)] = ((uint8_t)(v_i)); ++ v_b += 1u; ++ v_bx_offset += 1u; ++ if (v_bx_offset == v_h) { ++ v_bx_offset = 0u; ++ v_by_offset += 1u; ++ if (v_by_offset == v_v) { ++ v_by_offset = 0u; ++ } ++ } ++ v_hv -= 1u; ++ } ++ v_i += 1u; ++ } ++ if (v_total_hv > 10u) { ++ return true; ++ } ++ self->private_impl.f_mcu_num_blocks = v_total_hv; ++ self->private_impl.f_swizzle_immediately_c_offsets[self->private_impl.f_scan_num_components] = ((uint32_t)(64u * v_total_hv)); ++ v_b = 0u; ++ while (v_b < self->private_impl.f_mcu_num_blocks) { ++ v_ssel = self->private_impl.f_mcu_blocks_sselector[v_b]; ++ v_csel = self->private_impl.f_scan_comps_cselector[v_ssel]; ++ self->private_impl.f_mcu_blocks_offset[v_b] = (self->private_impl.f_components_workbuf_offsets[v_csel] + (8u * ((uint64_t)(self->private_impl.f_scan_comps_bx_offset[v_b]))) + (8u * ((uint64_t)(self->private_impl.f_scan_comps_by_offset[v_b])) * ((uint64_t)(self->private_impl.f_components_workbuf_widths[v_csel])))); ++ self->private_impl.f_mcu_blocks_mx_mul[v_b] = (8u * ((uint32_t)(self->private_impl.f_components_h[v_csel]))); ++ self->private_impl.f_mcu_blocks_my_mul[v_b] = (8u * ((uint32_t)(self->private_impl.f_components_v[v_csel])) * self->private_impl.f_components_workbuf_widths[v_csel]); ++ self->private_impl.f_mcu_blocks_dc_hselector[v_b] = ((uint8_t)(0u | self->private_impl.f_scan_comps_td[v_ssel])); ++ self->private_impl.f_mcu_blocks_ac_hselector[v_b] = ((uint8_t)(4u | self->private_impl.f_scan_comps_ta[v_ssel])); ++ v_sibo = ((uint32_t)(self->private_impl.f_swizzle_immediately_c_offsets[v_csel] + ((8u * ((uint32_t)(self->private_impl.f_scan_comps_bx_offset[v_b]))) + (64u * ((uint32_t)(self->private_impl.f_scan_comps_by_offset[v_b])) * ((uint32_t)(self->private_impl.f_components_h[v_csel])))))); ++ self->private_impl.f_swizzle_immediately_b_offsets[v_b] = wuffs_base__u32__min(v_sibo, 576u); ++ v_b += 1u; ++ } ++ self->private_impl.f_scan_width_in_mcus = self->private_impl.f_width_in_mcus; ++ self->private_impl.f_scan_height_in_mcus = self->private_impl.f_height_in_mcus; ++ return false; ++} ++ ++// -------- func jpeg.decoder.fill_bitstream ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__fill_bitstream( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ uint32_t v_wi = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_new_wi = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } ++ ++ if (self->private_impl.f_bitstream_ri <= 0u) { ++ } else if (self->private_impl.f_bitstream_ri >= self->private_impl.f_bitstream_wi) { ++ self->private_impl.f_bitstream_ri = 0u; ++ self->private_impl.f_bitstream_wi = 0u; ++ } else { ++ v_wi = (self->private_impl.f_bitstream_wi - self->private_impl.f_bitstream_ri); ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_bitstream_buffer, 2048), wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, ++ self->private_impl.f_bitstream_ri, ++ self->private_impl.f_bitstream_wi)); ++ self->private_impl.f_bitstream_ri = 0u; ++ self->private_impl.f_bitstream_wi = v_wi; ++ } ++ v_wi = self->private_impl.f_bitstream_wi; ++ while ((v_wi < 2048u) && (((uint64_t)(io2_a_src - iop_a_src)) > 0u)) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if (v_c8 < 255u) { ++ self->private_data.f_bitstream_buffer[v_wi] = v_c8; ++ v_wi += 1u; ++ iop_a_src += 1u; ++ continue; ++ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 1u) { ++ break; ++ } else if (((uint16_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8u)) > 0u) { ++ break; ++ } else { ++ self->private_data.f_bitstream_buffer[v_wi] = 255u; ++ v_wi += 1u; ++ iop_a_src += 2u; ++ } ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) > 1u) { ++ if ((wuffs_base__peek_u8be__no_bounds_check(iop_a_src) >= 255u) && (((uint16_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8u)) > 0u)) { ++ v_new_wi = (wuffs_base__u32__min(v_wi, 1784u) + 264u); ++ v_new_wi = wuffs_base__u32__min(v_new_wi, (v_wi + self->private_impl.f_bitstream_padding)); ++ if (v_wi < v_new_wi) { ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_bitstream_padding, (v_new_wi - v_wi)); ++ wuffs_private_impl__bulk_memset(&self->private_data.f_bitstream_buffer[v_wi], (v_new_wi - v_wi), 0u); ++ v_wi = v_new_wi; ++ } ++ } ++ } ++ self->private_impl.f_bitstream_wi = v_wi; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func jpeg.decoder.load_mcu_blocks_for_single_component ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__load_mcu_blocks_for_single_component( ++ wuffs_jpeg__decoder* self, ++ uint32_t a_mx, ++ uint32_t a_my, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_csel) { ++ return (*self->private_impl.choosy_load_mcu_blocks_for_single_component)(self, a_mx, a_my, a_workbuf, a_csel); ++} ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__load_mcu_blocks_for_single_component__choosy_default( ++ wuffs_jpeg__decoder* self, ++ uint32_t a_mx, ++ uint32_t a_my, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_csel) { ++ uint64_t v_stride16 = 0; ++ uint64_t v_offset = 0; ++ ++ v_stride16 = ((uint64_t)((self->private_impl.f_components_workbuf_widths[a_csel] * 16u))); ++ v_offset = (self->private_impl.f_components_workbuf_offsets[(a_csel | 4u)] + (((uint64_t)(a_mx)) * 128u) + (((uint64_t)(a_my)) * v_stride16)); ++ if (v_offset <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_private_impl__bulk_load_host_endian(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); ++ } ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func jpeg.decoder.load_mcu_blocks ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__load_mcu_blocks( ++ wuffs_jpeg__decoder* self, ++ uint32_t a_mx, ++ uint32_t a_my, ++ wuffs_base__slice_u8 a_workbuf) { ++ uint32_t v_b = 0; ++ uint8_t v_csel = 0; ++ uint64_t v_h = 0; ++ uint64_t v_v = 0; ++ uint64_t v_stride16 = 0; ++ uint64_t v_offset = 0; ++ ++ v_h = 1u; ++ v_v = 1u; ++ v_b = 0u; ++ while (v_b < self->private_impl.f_mcu_num_blocks) { ++ v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[v_b]]; ++ if (self->private_impl.f_scan_num_components > 1u) { ++ v_h = ((uint64_t)(self->private_impl.f_components_h[v_csel])); ++ v_v = ((uint64_t)(self->private_impl.f_components_v[v_csel])); ++ } ++ v_stride16 = ((uint64_t)((self->private_impl.f_components_workbuf_widths[v_csel] * 16u))); ++ v_offset = (self->private_impl.f_components_workbuf_offsets[((uint8_t)(v_csel | 4u))] + (((v_h * ((uint64_t)(a_mx))) + ((uint64_t)(self->private_impl.f_scan_comps_bx_offset[v_b]))) * 128u) + (((v_v * ((uint64_t)(a_my))) + ((uint64_t)(self->private_impl.f_scan_comps_by_offset[v_b]))) * v_stride16)); ++ if (v_offset <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_private_impl__bulk_load_host_endian(&self->private_data.f_mcu_blocks[v_b], 1u * (size_t)128u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); ++ } ++ v_b += 1u; ++ } ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func jpeg.decoder.save_mcu_blocks ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__save_mcu_blocks( ++ wuffs_jpeg__decoder* self, ++ uint32_t a_mx, ++ uint32_t a_my, ++ wuffs_base__slice_u8 a_workbuf) { ++ uint32_t v_b = 0; ++ uint8_t v_csel = 0; ++ uint64_t v_h = 0; ++ uint64_t v_v = 0; ++ uint64_t v_stride16 = 0; ++ uint64_t v_offset = 0; ++ ++ v_h = 1u; ++ v_v = 1u; ++ v_b = 0u; ++ while (v_b < self->private_impl.f_mcu_num_blocks) { ++ v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[v_b]]; ++ if (self->private_impl.f_scan_num_components > 1u) { ++ v_h = ((uint64_t)(self->private_impl.f_components_h[v_csel])); ++ v_v = ((uint64_t)(self->private_impl.f_components_v[v_csel])); ++ } ++ v_stride16 = ((uint64_t)((self->private_impl.f_components_workbuf_widths[v_csel] * 16u))); ++ v_offset = (self->private_impl.f_components_workbuf_offsets[((uint8_t)(v_csel | 4u))] + (((v_h * ((uint64_t)(a_mx))) + ((uint64_t)(self->private_impl.f_scan_comps_bx_offset[v_b]))) * 128u) + (((v_v * ((uint64_t)(a_my))) + ((uint64_t)(self->private_impl.f_scan_comps_by_offset[v_b]))) * v_stride16)); ++ if (v_offset <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_private_impl__bulk_save_host_endian(&self->private_data.f_mcu_blocks[v_b], 1u * (size_t)128u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); ++ } ++ v_b += 1u; ++ } ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func jpeg.decoder.skip_past_the_next_restart_marker ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__skip_past_the_next_restart_marker( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_skip_past_the_next_restart_marker; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ continue; ++ } else if (wuffs_base__peek_u8be__no_bounds_check(iop_a_src) < 255u) { ++ iop_a_src += 1u; ++ continue; ++ } ++ v_c8 = ((uint8_t)(((uint16_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8u)))); ++ if (v_c8 < 192u) { ++ iop_a_src += 2u; ++ continue; ++ } else if ((v_c8 < 208u) || (215u < v_c8)) { ++ break; ++ } ++ v_c8 &= 7u; ++ if ((self->private_impl.f_next_restart_marker == ((uint8_t)(((uint8_t)(v_c8 + 1u)) & 7u))) || (self->private_impl.f_next_restart_marker == ((uint8_t)(((uint8_t)(v_c8 + 2u)) & 7u)))) { ++ break; ++ } else if ((self->private_impl.f_next_restart_marker == ((uint8_t)(((uint8_t)(v_c8 + 7u)) & 7u))) || (self->private_impl.f_next_restart_marker == ((uint8_t)(((uint8_t)(v_c8 + 6u)) & 7u)))) { ++ iop_a_src += 2u; ++ continue; ++ } else { ++ iop_a_src += 2u; ++ break; ++ } ++ } ++ self->private_impl.f_next_restart_marker = ((uint8_t)(((uint8_t)(self->private_impl.f_next_restart_marker + 1u)) & 7u)); ++ ++ ok: ++ self->private_impl.p_skip_past_the_next_restart_marker = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_skip_past_the_next_restart_marker = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func jpeg.decoder.apply_progressive_idct ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__apply_progressive_idct( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__slice_u8 a_workbuf) { ++ uint32_t v_csel = 0; ++ bool v_block_smoothing_applicable = false; ++ uint32_t v_scan_width_in_mcus = 0; ++ uint32_t v_scan_height_in_mcus = 0; ++ uint32_t v_mcu_blocks_mx_mul_0 = 0; ++ uint32_t v_mcu_blocks_my_mul_0 = 0; ++ uint32_t v_my = 0; ++ uint32_t v_mx = 0; ++ uint64_t v_stride = 0; ++ uint64_t v_offset = 0; ++ uint8_t v_stashed_mcu_blocks_0[128] = {0}; ++ ++ wuffs_private_impl__bulk_save_host_endian(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, wuffs_base__make_slice_u8(v_stashed_mcu_blocks_0, 128)); ++ v_block_smoothing_applicable = true; ++ v_csel = 0u; ++ while (v_csel < self->private_impl.f_num_components) { ++ if ((self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][0u] >= 16u) || wuffs_jpeg__decoder__top_left_quants_has_zero(self, ((uint32_t)(self->private_impl.f_components_tq[v_csel])))) { ++ v_block_smoothing_applicable = false; ++ } ++ v_csel += 1u; ++ } ++ v_csel = 0u; ++ while (v_csel < self->private_impl.f_num_components) { ++ v_scan_width_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_width, self->private_impl.f_components_h[v_csel], self->private_impl.f_max_incl_components_h); ++ v_scan_height_in_mcus = wuffs_jpeg__decoder__quantize_dimension(self, self->private_impl.f_height, self->private_impl.f_components_v[v_csel], self->private_impl.f_max_incl_components_v); ++ v_mcu_blocks_mx_mul_0 = 8u; ++ v_mcu_blocks_my_mul_0 = (8u * self->private_impl.f_components_workbuf_widths[v_csel]); ++ if (v_block_smoothing_applicable && (0u != (self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][1u] | ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][2u] | ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][3u] | ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][4u] | ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][5u] | ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][6u] | ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][8u] | ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][8u] | ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_csel][9u]))) { ++ self->private_impl.choosy_load_mcu_blocks_for_single_component = ( ++ &wuffs_jpeg__decoder__load_mcu_blocks_for_single_component_smooth); ++ self->private_impl.f_block_smoothing_mx_max_incl = wuffs_base__u32__sat_sub(v_scan_width_in_mcus, 1u); ++ self->private_impl.f_block_smoothing_my_max_incl = wuffs_base__u32__sat_sub(v_scan_height_in_mcus, 1u); ++ } else { ++ self->private_impl.choosy_load_mcu_blocks_for_single_component = ( ++ &wuffs_jpeg__decoder__load_mcu_blocks_for_single_component__choosy_default); ++ } ++ v_my = 0u; ++ while (v_my < v_scan_height_in_mcus) { ++ v_mx = 0u; ++ while (v_mx < v_scan_width_in_mcus) { ++ wuffs_jpeg__decoder__load_mcu_blocks_for_single_component(self, ++ v_mx, ++ v_my, ++ a_workbuf, ++ v_csel); ++ v_stride = ((uint64_t)(self->private_impl.f_components_workbuf_widths[v_csel])); ++ v_offset = (self->private_impl.f_components_workbuf_offsets[v_csel] + (((uint64_t)(v_mcu_blocks_mx_mul_0)) * ((uint64_t)(v_mx))) + (((uint64_t)(v_mcu_blocks_my_mul_0)) * ((uint64_t)(v_my)))); ++ if (v_offset <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_jpeg__decoder__decode_idct(self, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset), v_stride, ((uint32_t)(self->private_impl.f_components_tq[v_csel]))); ++ } ++ v_mx += 1u; ++ } ++ v_my += 1u; ++ } ++ v_csel += 1u; ++ } ++ wuffs_private_impl__bulk_load_host_endian(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, wuffs_base__make_slice_u8(v_stashed_mcu_blocks_0, 128)); ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func jpeg.decoder.swizzle_gray ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__swizzle_gray( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_x0, ++ uint32_t a_x1, ++ uint32_t a_y0, ++ uint32_t a_y1, ++ uint64_t a_stride) { ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_x0 = 0; ++ uint64_t v_x1 = 0; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint32_t v_y = 0; ++ uint32_t v_y1 = 0; ++ ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ } ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_x0 = ((uint64_t)((v_dst_bytes_per_pixel * wuffs_base__u32__min(a_x0, self->private_impl.f_width)))); ++ v_x1 = ((uint64_t)((v_dst_bytes_per_pixel * wuffs_base__u32__min(a_x1, self->private_impl.f_width)))); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ v_y = a_y0; ++ v_y1 = wuffs_base__u32__min(a_y1, self->private_impl.f_height); ++ while (v_y < v_y1) { ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, v_y); ++ if (v_x1 < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_x1); ++ } ++ if (v_x0 < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_x0); ++ } else { ++ v_dst = wuffs_base__utility__empty_slice_u8(); ++ } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), a_workbuf); ++ if (a_stride <= ((uint64_t)(a_workbuf.len))) { ++ a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, a_stride); ++ } else { ++ a_workbuf = wuffs_base__utility__empty_slice_u8(); ++ } ++ v_y += 1u; ++ } ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func jpeg.decoder.swizzle_colorful ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_jpeg__decoder__swizzle_colorful( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_x0, ++ uint32_t a_x1, ++ uint32_t a_y0, ++ uint32_t a_y1) { ++ uint64_t v_i = 0; ++ uint64_t v_j = 0; ++ wuffs_base__slice_u8 v_src0 = {0}; ++ wuffs_base__slice_u8 v_src1 = {0}; ++ wuffs_base__slice_u8 v_src2 = {0}; ++ wuffs_base__slice_u8 v_src3 = {0}; ++ uint32_t v_width0 = 0; ++ uint32_t v_width1 = 0; ++ uint32_t v_width2 = 0; ++ uint32_t v_width3 = 0; ++ uint32_t v_height0 = 0; ++ uint32_t v_height1 = 0; ++ uint32_t v_height2 = 0; ++ uint32_t v_height3 = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ if (self->private_impl.f_swizzle_immediately) { ++ v_i = ((uint64_t)(self->private_impl.f_swizzle_immediately_c_offsets[0u])); ++ v_j = ((uint64_t)(self->private_impl.f_swizzle_immediately_c_offsets[1u])); ++ if ((v_i <= v_j) && (v_j <= 640u)) { ++ v_src0 = wuffs_base__make_slice_u8_ij(self->private_data.f_swizzle_immediately_buffer, v_i, v_j); ++ v_width0 = (8u * ((uint32_t)(self->private_impl.f_components_h[0u]))); ++ v_height0 = (8u * ((uint32_t)(self->private_impl.f_components_v[0u]))); ++ } ++ v_i = ((uint64_t)(self->private_impl.f_swizzle_immediately_c_offsets[1u])); ++ v_j = ((uint64_t)(self->private_impl.f_swizzle_immediately_c_offsets[2u])); ++ if ((v_i <= v_j) && (v_j <= 640u)) { ++ v_src1 = wuffs_base__make_slice_u8_ij(self->private_data.f_swizzle_immediately_buffer, v_i, v_j); ++ v_width1 = (8u * ((uint32_t)(self->private_impl.f_components_h[1u]))); ++ v_height1 = (8u * ((uint32_t)(self->private_impl.f_components_v[1u]))); ++ } ++ v_i = ((uint64_t)(self->private_impl.f_swizzle_immediately_c_offsets[2u])); ++ v_j = ((uint64_t)(self->private_impl.f_swizzle_immediately_c_offsets[3u])); ++ if ((v_i <= v_j) && (v_j <= 640u)) { ++ v_src2 = wuffs_base__make_slice_u8_ij(self->private_data.f_swizzle_immediately_buffer, v_i, v_j); ++ v_width2 = (8u * ((uint32_t)(self->private_impl.f_components_h[2u]))); ++ v_height2 = (8u * ((uint32_t)(self->private_impl.f_components_v[2u]))); ++ } ++ v_i = ((uint64_t)(self->private_impl.f_swizzle_immediately_c_offsets[3u])); ++ v_j = ((uint64_t)(self->private_impl.f_swizzle_immediately_c_offsets[4u])); ++ if ((v_i <= v_j) && (v_j <= 640u)) { ++ v_src3 = wuffs_base__make_slice_u8_ij(self->private_data.f_swizzle_immediately_buffer, v_i, v_j); ++ v_width3 = (8u * ((uint32_t)(self->private_impl.f_components_h[3u]))); ++ v_height3 = (8u * ((uint32_t)(self->private_impl.f_components_v[3u]))); ++ } ++ } else { ++ if ((self->private_impl.f_components_workbuf_offsets[0u] <= self->private_impl.f_components_workbuf_offsets[1u]) && (self->private_impl.f_components_workbuf_offsets[1u] <= ((uint64_t)(a_workbuf.len)))) { ++ v_src0 = wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ self->private_impl.f_components_workbuf_offsets[0u], ++ self->private_impl.f_components_workbuf_offsets[1u]); ++ v_width0 = self->private_impl.f_components_workbuf_widths[0u]; ++ v_height0 = self->private_impl.f_components_workbuf_heights[0u]; ++ } ++ if ((self->private_impl.f_components_workbuf_offsets[1u] <= self->private_impl.f_components_workbuf_offsets[2u]) && (self->private_impl.f_components_workbuf_offsets[2u] <= ((uint64_t)(a_workbuf.len)))) { ++ v_src1 = wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ self->private_impl.f_components_workbuf_offsets[1u], ++ self->private_impl.f_components_workbuf_offsets[2u]); ++ v_width1 = self->private_impl.f_components_workbuf_widths[1u]; ++ v_height1 = self->private_impl.f_components_workbuf_heights[1u]; ++ } ++ if ((self->private_impl.f_components_workbuf_offsets[2u] <= self->private_impl.f_components_workbuf_offsets[3u]) && (self->private_impl.f_components_workbuf_offsets[3u] <= ((uint64_t)(a_workbuf.len)))) { ++ v_src2 = wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ self->private_impl.f_components_workbuf_offsets[2u], ++ self->private_impl.f_components_workbuf_offsets[3u]); ++ v_width2 = self->private_impl.f_components_workbuf_widths[2u]; ++ v_height2 = self->private_impl.f_components_workbuf_heights[2u]; ++ } ++ if ((self->private_impl.f_components_workbuf_offsets[3u] <= self->private_impl.f_components_workbuf_offsets[4u]) && (self->private_impl.f_components_workbuf_offsets[4u] <= ((uint64_t)(a_workbuf.len)))) { ++ v_src3 = wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ self->private_impl.f_components_workbuf_offsets[3u], ++ self->private_impl.f_components_workbuf_offsets[4u]); ++ v_width3 = self->private_impl.f_components_workbuf_widths[3u]; ++ v_height3 = self->private_impl.f_components_workbuf_heights[3u]; ++ } ++ } ++ v_status = wuffs_base__pixel_swizzler__swizzle_ycck(&self->private_impl.f_swizzler, ++ a_dst, ++ wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), ++ (a_x0 & 65535u), ++ wuffs_base__u32__min(a_x1, self->private_impl.f_width), ++ (a_y0 & 65535u), ++ wuffs_base__u32__min(a_y1, self->private_impl.f_height), ++ v_src0, ++ v_src1, ++ v_src2, ++ v_src3, ++ v_width0, ++ v_width1, ++ v_width2, ++ v_width3, ++ v_height0, ++ v_height1, ++ v_height2, ++ v_height3, ++ v_width0, ++ v_width1, ++ v_width2, ++ v_width3, ++ self->private_impl.f_components_h[0u], ++ self->private_impl.f_components_h[1u], ++ self->private_impl.f_components_h[2u], ++ self->private_impl.f_components_h[3u], ++ self->private_impl.f_components_v[0u], ++ self->private_impl.f_components_v[1u], ++ self->private_impl.f_components_v[2u], ++ self->private_impl.f_components_v[3u], ++ self->private_impl.f_is_rgb_or_cmyk, ++ ! self->private_impl.f_use_lower_quality, ++ wuffs_base__make_slice_u8(self->private_data.f_swizzle_ycck_scratch_buffer_2k, 2048)); ++ return wuffs_private_impl__status__ensure_not_a_suspension(v_status); ++} ++ ++// -------- func jpeg.decoder.frame_dirty_rect ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_jpeg__decoder__frame_dirty_rect( ++ const wuffs_jpeg__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ ++ return wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height); ++} ++ ++// -------- func jpeg.decoder.num_animation_loops ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_jpeg__decoder__num_animation_loops( ++ const wuffs_jpeg__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func jpeg.decoder.num_decoded_frame_configs ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_jpeg__decoder__num_decoded_frame_configs( ++ const wuffs_jpeg__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 32u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func jpeg.decoder.num_decoded_frames ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_jpeg__decoder__num_decoded_frames( ++ const wuffs_jpeg__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 64u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func jpeg.decoder.restart_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_jpeg__decoder__restart_frame( ++ wuffs_jpeg__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ uint32_t v_i = 0; ++ uint32_t v_j = 0; ++ ++ if (self->private_impl.f_call_sequence < 32u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } ++ if (a_index != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_call_sequence = 40u; ++ self->private_impl.f_bitstream_is_closed = false; ++ self->private_impl.f_expect_multiple_scans = false; ++ self->private_impl.f_frame_config_io_position = a_io_position; ++ self->private_impl.f_scan_count = 0u; ++ self->private_impl.f_restart_interval = self->private_impl.f_saved_restart_interval; ++ v_i = 0u; ++ while (v_i < 4u) { ++ self->private_impl.f_seen_dqt[v_i] = self->private_impl.f_saved_seen_dqt[v_i]; ++ v_j = 0u; ++ while (v_j < 64u) { ++ self->private_impl.f_quant_tables[v_i][v_j] = self->private_impl.f_saved_quant_tables[v_i][v_j]; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 4u) { ++ v_j = 0u; ++ while (v_j < 10u) { ++ self->private_impl.f_block_smoothing_lowest_scan_al[v_i][v_j] = 16u; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 8u) { ++ self->private_impl.f_seen_dht[v_i] = false; ++ v_i += 1u; ++ } ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func jpeg.decoder.set_report_metadata ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_jpeg__decoder__set_report_metadata( ++ wuffs_jpeg__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func jpeg.decoder.tell_me_more ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_jpeg__decoder__tell_me_more( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); ++ goto exit; ++ ++ goto ok; ++ ok: ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func jpeg.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_jpeg__decoder__workbuf_len( ++ const wuffs_jpeg__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ if (self->private_impl.f_use_lower_quality && (self->private_impl.f_sof_marker < 194u)) { ++ return wuffs_base__utility__make_range_ii_u64(0u, self->private_impl.f_components_workbuf_offsets[8u]); ++ } ++ return wuffs_base__utility__make_range_ii_u64(self->private_impl.f_components_workbuf_offsets[8u], self->private_impl.f_components_workbuf_offsets[8u]); ++} ++ ++// -------- func jpeg.decoder.top_left_quants_has_zero ++ ++WUFFS_BASE__GENERATED_C_CODE ++static bool ++wuffs_jpeg__decoder__top_left_quants_has_zero( ++ const wuffs_jpeg__decoder* self, ++ uint32_t a_q) { ++ return ((self->private_impl.f_quant_tables[a_q][0u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][1u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][2u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][3u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][8u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][9u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][10u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][16u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][17u] == 0u) || ++ (self->private_impl.f_quant_tables[a_q][24u] == 0u)); ++} ++ ++// -------- func jpeg.decoder.load_mcu_blocks_for_single_component_smooth ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_jpeg__decoder__load_mcu_blocks_for_single_component_smooth( ++ wuffs_jpeg__decoder* self, ++ uint32_t a_mx, ++ uint32_t a_my, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_csel) { ++ uint64_t v_stride16 = 0; ++ uint64_t v_offset = 0; ++ uint32_t v_dx = 0; ++ uint32_t v_dy = 0; ++ uint32_t v_mx = 0; ++ uint32_t v_my = 0; ++ uint8_t v_q = 0; ++ uint32_t v_q_00 = 0; ++ uint32_t v_q_xy = 0; ++ uint8_t v_al = 0; ++ uint32_t v_scratch = 0; ++ uint32_t v_limit = 0; ++ ++ v_stride16 = ((uint64_t)((self->private_impl.f_components_workbuf_widths[a_csel] * 16u))); ++ v_offset = (self->private_impl.f_components_workbuf_offsets[(a_csel | 4u)] + (((uint64_t)(a_mx)) * 128u) + (((uint64_t)(a_my)) * v_stride16)); ++ if (v_offset <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_private_impl__bulk_load_host_endian(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); ++ } ++ v_dy = 0u; ++ while (v_dy < 5u) { ++ v_my = wuffs_base__u32__min(self->private_impl.f_block_smoothing_my_max_incl, wuffs_base__u32__sat_sub((a_my + v_dy), 2u)); ++ v_dx = 0u; ++ while (v_dx < 5u) { ++ v_mx = wuffs_base__u32__min(self->private_impl.f_block_smoothing_mx_max_incl, wuffs_base__u32__sat_sub((a_mx + v_dx), 2u)); ++ v_offset = (self->private_impl.f_components_workbuf_offsets[(a_csel | 4u)] + (((uint64_t)(v_mx)) * 128u) + (((uint64_t)(v_my)) * v_stride16)); ++ if (v_offset <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_private_impl__bulk_load_host_endian(&self->private_impl.f_block_smoothing_dc_values[v_dy][v_dx], 1u * (size_t)2u, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset)); ++ } ++ v_dx += 1u; ++ } ++ v_dy += 1u; ++ } ++ v_q = self->private_impl.f_components_tq[a_csel]; ++ v_q_00 = ((uint32_t)(self->private_impl.f_quant_tables[v_q][0u])); ++ if (v_q_00 <= 0u) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (0u != (16u & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][1u] & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][2u] & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][3u] & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][4u] & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][5u] & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][6u] & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][7u] & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][8u] & ++ self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][9u])) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(4294967288u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(6u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(42u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(6u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(4294967288u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(42u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(152u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(42u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(4294967288u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(6u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(42u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(6u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(4294967288u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(4294967290u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + 128u)) / 256u))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + 128u)) / 256u))); ++ } ++ self->private_data.f_mcu_blocks[0u][0u] = ((uint16_t)(v_scratch)); ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][1u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][1u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(4294967283u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(38u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(4294967258u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(4294967283u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][1u] = ((uint16_t)(v_scratch)); ++ } ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][2u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][2u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(4294967291u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(4294967282u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(4294967291u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][2u] = ((uint16_t)(v_scratch)); ++ } ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][3u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][3u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][3u] = ((uint16_t)(v_scratch)); ++ } ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][8u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][8u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(38u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(4294967283u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(4294967258u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(4294967283u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][8u] = ((uint16_t)(v_scratch)); ++ } ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][9u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][9u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(9u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(4294967287u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(4294967287u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(9u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][9u] = ((uint16_t)(v_scratch)); ++ } ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][10u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][10u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][10u] = ((uint16_t)(v_scratch)); ++ } ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][16u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][16u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(4294967291u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(4294967282u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(4294967291u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][16u] = ((uint16_t)(v_scratch)); ++ } ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][17u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][17u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(4294967293u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(3u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][17u] = ((uint16_t)(v_scratch)); ++ } ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][24u])); ++ if ((v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][24u] == 0u)) { ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(2u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(4294967294u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } else { ++ v_scratch = ((uint32_t)(0u - (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u)))); ++ } ++ self->private_data.f_mcu_blocks[0u][24u] = ((uint16_t)(v_scratch)); ++ } ++ } else { ++ v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][1u]; ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][1u])); ++ if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][1u] == 0u)) { ++ v_limit = ((((uint32_t)(1u)) << v_al) - 1u); ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(4294967289u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(50u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(4294967246u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } else { ++ v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } ++ self->private_data.f_mcu_blocks[0u][1u] = ((uint16_t)(v_scratch)); ++ } ++ v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][5u]; ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][2u])); ++ if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][2u] == 0u)) { ++ v_limit = ((((uint32_t)(1u)) << v_al) - 1u); ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(4294967272u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } else { ++ v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } ++ self->private_data.f_mcu_blocks[0u][2u] = ((uint16_t)(v_scratch)); ++ } ++ v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][2u]; ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][8u])); ++ if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][8u] == 0u)) { ++ v_limit = ((((uint32_t)(1u)) << v_al) - 1u); ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(4294967289u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(50u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(4294967246u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(7u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } else { ++ v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } ++ self->private_data.f_mcu_blocks[0u][8u] = ((uint16_t)(v_scratch)); ++ } ++ v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][4u]; ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][9u])); ++ if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][9u] == 0u)) { ++ v_limit = ((((uint32_t)(1u)) << v_al) - 1u); ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(10u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(4294967286u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(4294967286u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(10u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(1u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } else { ++ v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } ++ self->private_data.f_mcu_blocks[0u][9u] = ((uint16_t)(v_scratch)); ++ } ++ v_al = self->private_impl.f_block_smoothing_lowest_scan_al[a_csel][3u]; ++ v_q_xy = ((uint32_t)(self->private_impl.f_quant_tables[v_q][16u])); ++ if ((v_al > 0u) && (v_q_xy > 0u) && (self->private_data.f_mcu_blocks[0u][16u] == 0u)) { ++ v_limit = ((((uint32_t)(1u)) << v_al) - 1u); ++ v_scratch = 0u; ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][1u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[0u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][1u]))); ++ v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[1u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][1u]))); ++ v_scratch += ((uint32_t)(4294967272u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[2u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][1u]))); ++ v_scratch += ((uint32_t)(13u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[3u][4u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][0u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][1u]))); ++ v_scratch += ((uint32_t)(4294967295u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][2u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][3u]))); ++ v_scratch += ((uint32_t)(0u * wuffs_base__utility__sign_extend_convert_u16_u32(self->private_impl.f_block_smoothing_dc_values[4u][4u]))); ++ v_scratch *= v_q_00; ++ if (v_scratch < 2147483648u) { ++ v_scratch = ((uint32_t)(0u + wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u + v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } else { ++ v_scratch = ((uint32_t)(0u - wuffs_base__u32__min(v_limit, (((uint32_t)(((uint32_t)(0u - v_scratch)) + (v_q_xy << 7u))) / (v_q_xy << 8u))))); ++ } ++ self->private_data.f_mcu_blocks[0u][16u] = ((uint16_t)(v_scratch)); ++ } ++ } ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func jpeg.decoder.decode_mcu ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my) { ++ return (*self->private_impl.choosy_decode_mcu)(self, a_dst, a_workbuf, a_mx, a_my); ++} ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu__choosy_default( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my) { ++ uint32_t v_ret = 0; ++ uint64_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint8_t v_csel = 0; ++ wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_r = &u_r; ++ const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint32_t v_pos = 0; ++ uint8_t v_dc_h = 0; ++ uint32_t v_dc_symbol = 0; ++ uint32_t v_dc_ht_fast = 0; ++ uint32_t v_dc_bl = 0; ++ uint32_t v_dc_code = 0; ++ uint32_t v_dc_blm1 = 0; ++ uint32_t v_dc_ht_slow = 0; ++ uint16_t v_dc_value = 0; ++ uint16_t v_dc_extend = 0; ++ const uint16_t* v_ac_huff_table_fast = NULL; ++ uint8_t v_ac_h = 0; ++ uint32_t v_ac_symbol = 0; ++ uint32_t v_ac_ht_fast = 0; ++ uint32_t v_ac_bl = 0; ++ uint32_t v_ac_code = 0; ++ uint32_t v_ac_blm1 = 0; ++ uint32_t v_ac_ht_slow = 0; ++ uint16_t v_ac_value = 0; ++ uint16_t v_ac_extend = 0; ++ uint32_t v_ac_rrrr = 0; ++ uint32_t v_ac_ssss = 0; ++ uint32_t v_z = 0; ++ uint32_t v_mcb = 0; ++ uint64_t v_stride = 0; ++ uint64_t v_offset = 0; ++ ++ v_bits = self->private_impl.f_bitstream_bits; ++ v_n_bits = self->private_impl.f_bitstream_n_bits; ++ if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { ++ return 2u; ++ } ++ { ++ wuffs_base__io_buffer* o_0_v_r = v_r; ++ const uint8_t* o_0_iop_v_r = iop_v_r; ++ const uint8_t* o_0_io0_v_r = io0_v_r; ++ const uint8_t* o_0_io1_v_r = io1_v_r; ++ const uint8_t* o_0_io2_v_r = io2_v_r; ++ v_r = wuffs_private_impl__io_reader__set( ++ &u_r, ++ &iop_v_r, ++ &io0_v_r, ++ &io1_v_r, ++ &io2_v_r, ++ wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, ++ self->private_impl.f_bitstream_ri, ++ self->private_impl.f_bitstream_wi), ++ ((uint64_t)(self->private_impl.f_bitstream_ri))); ++ do { ++ while (self->private_impl.f_mcu_current_block < self->private_impl.f_mcu_num_blocks) { ++ while (self->private_impl.f_mcu_zig_index <= 0u) { ++ wuffs_private_impl__bulk_memset(&self->private_data.f_mcu_blocks[0], 1u * (size_t)128u, 0u); ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { ++ v_ret = 1u; ++ goto label__goto_done__break; ++ } ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ v_dc_h = self->private_impl.f_mcu_blocks_dc_hselector[self->private_impl.f_mcu_current_block]; ++ v_dc_ht_fast = ((uint32_t)(self->private_impl.f_huff_tables_fast[v_dc_h][(v_bits >> 56u)])); ++ v_dc_bl = (v_dc_ht_fast >> 8u); ++ if (v_n_bits >= v_dc_bl) { ++ v_dc_symbol = (15u & v_dc_ht_fast); ++ v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; ++ v_bits <<= (v_dc_bl & 63u); ++ v_n_bits -= v_dc_bl; ++ } else { ++ v_dc_code = ((uint32_t)((v_bits >> 55u))); ++ v_dc_blm1 = 8u; ++ v_bits <<= 9u; ++ v_n_bits -= 9u; ++ while (true) { ++ v_dc_ht_slow = self->private_impl.f_huff_tables_slow[v_dc_h][v_dc_blm1]; ++ if (v_dc_code < (v_dc_ht_slow >> 8u)) { ++ v_dc_symbol = (15u & ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_dc_h][(255u & ((uint32_t)(v_dc_code + v_dc_ht_slow)))]))); ++ v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; ++ break; ++ } ++ v_dc_code = (((uint32_t)(v_dc_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ v_dc_blm1 = ((v_dc_blm1 + 1u) & 15u); ++ if (v_dc_blm1 == 0u) { ++ v_dc_symbol = 0u; ++ v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; ++ break; ++ } ++ } ++ } ++ v_dc_value = ((uint16_t)(((v_bits >> 32u) >> (32u - v_dc_symbol)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_dc_value += ((uint16_t)(v_dc_extend & ((uint16_t)(((uint16_t)(wuffs_base__utility__sign_extend_rshift_u64(v_bits, 63u))) ^ 65535u)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_bits <<= v_dc_symbol; ++ v_n_bits -= v_dc_symbol; ++ v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[self->private_impl.f_mcu_current_block]]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_mcu_previous_dc_values[v_csel] += v_dc_value; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ self->private_data.f_mcu_blocks[0u][0u] = self->private_impl.f_mcu_previous_dc_values[v_csel]; ++ self->private_impl.f_mcu_zig_index = 1u; ++ break; ++ } ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { ++ v_ret = 1u; ++ goto label__goto_done__break; ++ } ++ if (v_n_bits < 16u) { ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ } ++ v_z = 1u; ++ self->private_impl.f_mcu_zig_index = 0u; ++ v_ac_h = self->private_impl.f_mcu_blocks_ac_hselector[self->private_impl.f_mcu_current_block]; ++ v_ac_huff_table_fast = &self->private_impl.f_huff_tables_fast[v_ac_h][0u]; ++ while (v_z < 64u) { ++ v_ac_ht_fast = ((uint32_t)(v_ac_huff_table_fast[(v_bits >> 56u)])); ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { ++ v_ret = 2u; ++ goto label__goto_done__break; ++ } ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ v_ac_bl = (v_ac_ht_fast >> 8u); ++ if (v_n_bits >= v_ac_bl) { ++ v_ac_symbol = (255u & v_ac_ht_fast); ++ v_bits <<= (v_ac_bl & 63u); ++ v_n_bits -= v_ac_bl; ++ } else { ++ v_ac_code = ((uint32_t)((v_bits >> 55u))); ++ v_ac_blm1 = 8u; ++ v_bits <<= 9u; ++ v_n_bits -= 9u; ++ while (true) { ++ v_ac_ht_slow = self->private_impl.f_huff_tables_slow[v_ac_h][v_ac_blm1]; ++ if (v_ac_code < (v_ac_ht_slow >> 8u)) { ++ v_ac_symbol = ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_ac_h][(255u & ((uint32_t)(v_ac_code + v_ac_ht_slow)))])); ++ break; ++ } ++ v_ac_code = (((uint32_t)(v_ac_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ v_ac_blm1 = ((v_ac_blm1 + 1u) & 15u); ++ if (v_ac_blm1 == 0u) { ++ v_ac_symbol = 0u; ++ break; ++ } ++ } ++ } ++ v_ac_rrrr = (v_ac_symbol >> 4u); ++ v_z += (v_ac_rrrr + 1u); ++ v_ac_ssss = (v_ac_symbol & 15u); ++ v_ac_extend = WUFFS_JPEG__EXTEND[v_ac_ssss]; ++ if (v_ac_ssss > 0u) { ++ v_ac_value = ((uint16_t)((v_bits >> (64u - v_ac_ssss)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_ac_value += ((uint16_t)(v_ac_extend & ((uint16_t)(((uint16_t)(wuffs_base__utility__sign_extend_rshift_u64(v_bits, 63u))) ^ 65535u)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_bits <<= v_ac_ssss; ++ v_n_bits -= v_ac_ssss; ++ self->private_data.f_mcu_blocks[0u][WUFFS_JPEG__UNZIG[v_z]] = v_ac_value; ++ } else if (v_ac_rrrr < 15u) { ++ break; ++ } ++ } ++ v_mcb = self->private_impl.f_mcu_current_block; ++ self->private_impl.f_mcu_current_block += 1u; ++ if (self->private_impl.f_test_only_interrupt_decode_mcu) { ++ goto label__goto_done__break; ++ } ++ if ( ! self->private_impl.f_swizzle_immediately) { ++ v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[v_mcb]]; ++ v_stride = ((uint64_t)(self->private_impl.f_components_workbuf_widths[v_csel])); ++ v_offset = (self->private_impl.f_mcu_blocks_offset[v_mcb] + (((uint64_t)(self->private_impl.f_mcu_blocks_mx_mul[v_mcb])) * ((uint64_t)(a_mx))) + (((uint64_t)(self->private_impl.f_mcu_blocks_my_mul[v_mcb])) * ((uint64_t)(a_my)))); ++ if (v_offset <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_jpeg__decoder__decode_idct(self, wuffs_base__slice_u8__subslice_i(a_workbuf, v_offset), v_stride, ((uint32_t)(self->private_impl.f_components_tq[v_csel]))); ++ } ++ } else if (self->private_impl.f_num_components == 1u) { ++ wuffs_jpeg__decoder__decode_idct(self, wuffs_base__make_slice_u8(self->private_data.f_swizzle_immediately_buffer, 64), 8u, ((uint32_t)(self->private_impl.f_components_tq[v_csel]))); ++ self->private_impl.f_swizzle_immediately_status = wuffs_jpeg__decoder__swizzle_gray(self, ++ a_dst, ++ wuffs_base__make_slice_u8(self->private_data.f_swizzle_immediately_buffer, 64), ++ ((a_mx + 0u) * 8u), ++ ((a_mx + 1u) * 8u), ++ ((a_my + 0u) * 8u), ++ ((a_my + 1u) * 8u), ++ 8u); ++ if ( ! wuffs_base__status__is_ok(&self->private_impl.f_swizzle_immediately_status)) { ++ v_ret = 3u; ++ goto label__goto_done__break; ++ } ++ break; ++ } else { ++ v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[v_mcb]]; ++ v_stride = (8u * ((uint64_t)(self->private_impl.f_components_h[v_csel]))); ++ wuffs_jpeg__decoder__decode_idct(self, wuffs_base__make_slice_u8_ij(self->private_data.f_swizzle_immediately_buffer, self->private_impl.f_swizzle_immediately_b_offsets[v_mcb], 640), v_stride, ((uint32_t)(self->private_impl.f_components_tq[v_csel]))); ++ if (self->private_impl.f_mcu_current_block < self->private_impl.f_mcu_num_blocks) { ++ continue; ++ } ++ self->private_impl.f_swizzle_immediately_status = wuffs_jpeg__decoder__swizzle_colorful(self, ++ a_dst, ++ wuffs_base__utility__empty_slice_u8(), ++ ((a_mx + 0u) * 8u * ((uint32_t)(self->private_impl.f_max_incl_components_h))), ++ ((a_mx + 1u) * 8u * ((uint32_t)(self->private_impl.f_max_incl_components_h))), ++ ((a_my + 0u) * 8u * ((uint32_t)(self->private_impl.f_max_incl_components_v))), ++ ((a_my + 1u) * 8u * ((uint32_t)(self->private_impl.f_max_incl_components_v)))); ++ if ( ! wuffs_base__status__is_ok(&self->private_impl.f_swizzle_immediately_status)) { ++ v_ret = 3u; ++ goto label__goto_done__break; ++ } ++ break; ++ } ++ } ++ self->private_impl.f_mcu_current_block = 0u; ++ } while (0); ++ label__goto_done__break:; ++ v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); ++ if (v_pos > self->private_impl.f_bitstream_wi) { ++ v_ret = 2u; ++ } else { ++ self->private_impl.f_bitstream_ri = v_pos; ++ } ++ v_r = o_0_v_r; ++ iop_v_r = o_0_iop_v_r; ++ io0_v_r = o_0_io0_v_r; ++ io1_v_r = o_0_io1_v_r; ++ io2_v_r = o_0_io2_v_r; ++ } ++ self->private_impl.f_bitstream_bits = v_bits; ++ self->private_impl.f_bitstream_n_bits = v_n_bits; ++ return v_ret; ++} ++ ++// -------- func jpeg.decoder.decode_mcu_progressive_ac_high_bits ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu_progressive_ac_high_bits( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my) { ++ uint32_t v_ret = 0; ++ uint64_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_r = &u_r; ++ const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint32_t v_pos = 0; ++ const uint16_t* v_ac_huff_table_fast = NULL; ++ uint8_t v_ac_h = 0; ++ uint32_t v_ac_symbol = 0; ++ uint32_t v_ac_ht_fast = 0; ++ uint32_t v_ac_bl = 0; ++ uint32_t v_ac_code = 0; ++ uint32_t v_ac_blm1 = 0; ++ uint32_t v_ac_ht_slow = 0; ++ uint16_t v_ac_value = 0; ++ uint16_t v_ac_extend = 0; ++ uint32_t v_ac_rrrr = 0; ++ uint32_t v_ac_ssss = 0; ++ uint32_t v_z = 0; ++ ++ if (self->private_impl.f_eob_run > 0u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_eob_run -= 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ return 0u; ++ } ++ v_bits = self->private_impl.f_bitstream_bits; ++ v_n_bits = self->private_impl.f_bitstream_n_bits; ++ if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { ++ return 2u; ++ } ++ { ++ wuffs_base__io_buffer* o_0_v_r = v_r; ++ const uint8_t* o_0_iop_v_r = iop_v_r; ++ const uint8_t* o_0_io0_v_r = io0_v_r; ++ const uint8_t* o_0_io1_v_r = io1_v_r; ++ const uint8_t* o_0_io2_v_r = io2_v_r; ++ v_r = wuffs_private_impl__io_reader__set( ++ &u_r, ++ &iop_v_r, ++ &io0_v_r, ++ &io1_v_r, ++ &io2_v_r, ++ wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, ++ self->private_impl.f_bitstream_ri, ++ self->private_impl.f_bitstream_wi), ++ ((uint64_t)(self->private_impl.f_bitstream_ri))); ++ do { ++ do { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { ++ v_ret = 1u; ++ goto label__goto_done__break; ++ } ++ if (v_n_bits < 16u) { ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ } ++ v_z = self->private_impl.f_mcu_zig_index; ++ self->private_impl.f_mcu_zig_index = 0u; ++ v_ac_h = self->private_impl.f_mcu_blocks_ac_hselector[0u]; ++ v_ac_huff_table_fast = &self->private_impl.f_huff_tables_fast[v_ac_h][0u]; ++ while (v_z <= ((uint32_t)(self->private_impl.f_scan_se))) { ++ v_ac_ht_fast = ((uint32_t)(v_ac_huff_table_fast[(v_bits >> 56u)])); ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { ++ v_ret = 2u; ++ goto label__goto_done__break; ++ } ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ v_ac_bl = (v_ac_ht_fast >> 8u); ++ if (v_n_bits >= v_ac_bl) { ++ v_ac_symbol = (255u & v_ac_ht_fast); ++ v_bits <<= (v_ac_bl & 63u); ++ v_n_bits -= v_ac_bl; ++ } else { ++ v_ac_code = ((uint32_t)((v_bits >> 55u))); ++ v_ac_blm1 = 8u; ++ v_bits <<= 9u; ++ v_n_bits -= 9u; ++ while (true) { ++ v_ac_ht_slow = self->private_impl.f_huff_tables_slow[v_ac_h][v_ac_blm1]; ++ if (v_ac_code < (v_ac_ht_slow >> 8u)) { ++ v_ac_symbol = ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_ac_h][(255u & ((uint32_t)(v_ac_code + v_ac_ht_slow)))])); ++ break; ++ } ++ v_ac_code = (((uint32_t)(v_ac_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ v_ac_blm1 = ((v_ac_blm1 + 1u) & 15u); ++ if (v_ac_blm1 == 0u) { ++ v_ac_symbol = 0u; ++ break; ++ } ++ } ++ } ++ v_ac_rrrr = (v_ac_symbol >> 4u); ++ v_z += (v_ac_rrrr + 1u); ++ v_ac_ssss = (v_ac_symbol & 15u); ++ v_ac_extend = WUFFS_JPEG__EXTEND[v_ac_ssss]; ++ if (v_ac_ssss > 0u) { ++ v_ac_value = ((uint16_t)((v_bits >> (64u - v_ac_ssss)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_ac_value += ((uint16_t)(v_ac_extend & ((uint16_t)(((uint16_t)(wuffs_base__utility__sign_extend_rshift_u64(v_bits, 63u))) ^ 65535u)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_bits <<= v_ac_ssss; ++ v_n_bits -= v_ac_ssss; ++ self->private_data.f_mcu_blocks[0u][WUFFS_JPEG__UNZIG[v_z]] = ((uint16_t)(((uint16_t)(v_ac_value << self->private_impl.f_scan_al)))); ++ } else if (v_ac_rrrr < 15u) { ++ self->private_impl.f_eob_run = ((uint16_t)(((uint16_t)(((uint16_t)(((uint16_t)(1u)) << v_ac_rrrr)) - 1u)))); ++ if (v_ac_rrrr > 0u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_eob_run += ((uint16_t)((v_bits >> (64u - v_ac_rrrr)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_bits <<= v_ac_rrrr; ++ v_n_bits -= v_ac_rrrr; ++ } ++ break; ++ } ++ } ++ } while (0); ++ } while (0); ++ label__goto_done__break:; ++ v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); ++ if (v_pos > self->private_impl.f_bitstream_wi) { ++ v_ret = 2u; ++ } else { ++ self->private_impl.f_bitstream_ri = v_pos; ++ } ++ v_r = o_0_v_r; ++ iop_v_r = o_0_iop_v_r; ++ io0_v_r = o_0_io0_v_r; ++ io1_v_r = o_0_io1_v_r; ++ io2_v_r = o_0_io2_v_r; ++ } ++ self->private_impl.f_bitstream_bits = v_bits; ++ self->private_impl.f_bitstream_n_bits = v_n_bits; ++ return v_ret; ++} ++ ++// -------- func jpeg.decoder.decode_mcu_progressive_ac_low_bit ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu_progressive_ac_low_bit( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my) { ++ uint32_t v_ret = 0; ++ uint64_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint16_t v_one_lshift_scan_al = 0; ++ wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_r = &u_r; ++ const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint32_t v_pos = 0; ++ const uint16_t* v_ac_huff_table_fast = NULL; ++ uint8_t v_ac_h = 0; ++ uint32_t v_ac_symbol = 0; ++ uint32_t v_ac_ht_fast = 0; ++ uint32_t v_ac_bl = 0; ++ uint32_t v_ac_code = 0; ++ uint32_t v_ac_blm1 = 0; ++ uint32_t v_ac_ht_slow = 0; ++ uint16_t v_ac_value = 0; ++ uint32_t v_ac_rrrr = 0; ++ uint32_t v_ac_ssss = 0; ++ uint8_t v_unzig = 0; ++ bool v_bit = false; ++ ++ v_bits = self->private_impl.f_bitstream_bits; ++ v_n_bits = self->private_impl.f_bitstream_n_bits; ++ v_one_lshift_scan_al = ((uint16_t)(((uint16_t)(1u)) << self->private_impl.f_scan_al)); ++ if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { ++ return 2u; ++ } ++ { ++ wuffs_base__io_buffer* o_0_v_r = v_r; ++ const uint8_t* o_0_iop_v_r = iop_v_r; ++ const uint8_t* o_0_io0_v_r = io0_v_r; ++ const uint8_t* o_0_io1_v_r = io1_v_r; ++ const uint8_t* o_0_io2_v_r = io2_v_r; ++ v_r = wuffs_private_impl__io_reader__set( ++ &u_r, ++ &iop_v_r, ++ &io0_v_r, ++ &io1_v_r, ++ &io2_v_r, ++ wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, ++ self->private_impl.f_bitstream_ri, ++ self->private_impl.f_bitstream_wi), ++ ((uint64_t)(self->private_impl.f_bitstream_ri))); ++ do { ++ do { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { ++ v_ret = 1u; ++ goto label__goto_done__break; ++ } ++ while (true) { ++ if (self->private_impl.f_eob_run > 0u) { ++ break; ++ } ++ v_ac_h = self->private_impl.f_mcu_blocks_ac_hselector[0u]; ++ v_ac_huff_table_fast = &self->private_impl.f_huff_tables_fast[v_ac_h][0u]; ++ while (true) { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { ++ v_ret = 2u; ++ goto label__goto_done__break; ++ } ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ v_ac_ht_fast = ((uint32_t)(v_ac_huff_table_fast[(v_bits >> 56u)])); ++ v_ac_bl = (v_ac_ht_fast >> 8u); ++ if (v_n_bits >= v_ac_bl) { ++ v_ac_symbol = (255u & v_ac_ht_fast); ++ v_bits <<= (v_ac_bl & 63u); ++ v_n_bits -= v_ac_bl; ++ } else { ++ v_ac_code = ((uint32_t)((v_bits >> 55u))); ++ v_ac_blm1 = 8u; ++ v_bits <<= 9u; ++ v_n_bits -= 9u; ++ while (true) { ++ v_ac_ht_slow = self->private_impl.f_huff_tables_slow[v_ac_h][v_ac_blm1]; ++ if (v_ac_code < (v_ac_ht_slow >> 8u)) { ++ v_ac_symbol = ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_ac_h][(255u & ((uint32_t)(v_ac_code + v_ac_ht_slow)))])); ++ break; ++ } ++ v_ac_code = (((uint32_t)(v_ac_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ v_ac_blm1 = ((v_ac_blm1 + 1u) & 15u); ++ if (v_ac_blm1 == 0u) { ++ v_ac_symbol = 0u; ++ break; ++ } ++ } ++ } ++ v_ac_rrrr = (v_ac_symbol >> 4u); ++ v_ac_ssss = (v_ac_symbol & 15u); ++ v_ac_value = 0u; ++ if (v_ac_ssss > 0u) { ++ v_ac_value = ((uint16_t)(((uint16_t)(1u)) << self->private_impl.f_scan_al)); ++ if ((v_bits >> 63u) == 0u) { ++ v_ac_value = ((uint16_t)(((uint16_t)(65535u)) << self->private_impl.f_scan_al)); ++ } ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ } else if (v_ac_rrrr < 15u) { ++ self->private_impl.f_eob_run = ((uint16_t)(((uint16_t)(1u)) << v_ac_rrrr)); ++ if (v_ac_rrrr > 0u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_eob_run += ((uint16_t)((v_bits >> (64u - v_ac_rrrr)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_bits <<= v_ac_rrrr; ++ v_n_bits -= v_ac_rrrr; ++ } ++ goto label__goto_do_eob__break; ++ } ++ while (true) { ++ v_unzig = WUFFS_JPEG__UNZIG[(1u + self->private_impl.f_mcu_zig_index)]; ++ if (self->private_data.f_mcu_blocks[0u][v_unzig] != 0u) { ++ if (v_n_bits == 0u) { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { ++ v_ret = 2u; ++ goto label__goto_done__break; ++ } ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ } ++ v_bit = ((v_bits >> 63u) > 0u); ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ if (v_bit) { ++ if (self->private_data.f_mcu_blocks[0u][v_unzig] < 32768u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_data.f_mcu_blocks[0u][v_unzig] += v_one_lshift_scan_al; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_data.f_mcu_blocks[0u][v_unzig] -= v_one_lshift_scan_al; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } ++ } ++ } else if (v_ac_rrrr <= 0u) { ++ break; ++ } else { ++ v_ac_rrrr -= 1u; ++ } ++ if (self->private_impl.f_mcu_zig_index >= ((uint32_t)(self->private_impl.f_scan_se))) { ++ break; ++ } ++ self->private_impl.f_mcu_zig_index += 1u; ++ } ++ if (v_ac_value != 0u) { ++ self->private_data.f_mcu_blocks[0u][WUFFS_JPEG__UNZIG[(1u + self->private_impl.f_mcu_zig_index)]] = v_ac_value; ++ } ++ if (self->private_impl.f_mcu_zig_index >= ((uint32_t)(self->private_impl.f_scan_se))) { ++ break; ++ } ++ self->private_impl.f_mcu_zig_index += 1u; ++ } ++ goto label__block__break; ++ } ++ label__goto_do_eob__break:; ++ if (self->private_impl.f_eob_run <= 0u) { ++ v_ret = 2u; ++ goto label__goto_done__break; ++ } ++ while (true) { ++ v_unzig = WUFFS_JPEG__UNZIG[(1u + self->private_impl.f_mcu_zig_index)]; ++ if (self->private_data.f_mcu_blocks[0u][v_unzig] != 0u) { ++ if (v_n_bits == 0u) { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { ++ v_ret = 2u; ++ goto label__goto_done__break; ++ } ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ } ++ v_bit = ((v_bits >> 63u) > 0u); ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ if (v_bit) { ++ if (self->private_data.f_mcu_blocks[0u][v_unzig] < 32768u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_data.f_mcu_blocks[0u][v_unzig] += v_one_lshift_scan_al; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_data.f_mcu_blocks[0u][v_unzig] -= v_one_lshift_scan_al; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } ++ } ++ } ++ if (self->private_impl.f_mcu_zig_index >= ((uint32_t)(self->private_impl.f_scan_se))) { ++ break; ++ } ++ self->private_impl.f_mcu_zig_index += 1u; ++ } ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_eob_run -= 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } while (0); ++ label__block__break:; ++ } while (0); ++ label__goto_done__break:; ++ v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); ++ if (v_pos > self->private_impl.f_bitstream_wi) { ++ v_ret = 2u; ++ } else { ++ self->private_impl.f_bitstream_ri = v_pos; ++ } ++ v_r = o_0_v_r; ++ iop_v_r = o_0_iop_v_r; ++ io0_v_r = o_0_io0_v_r; ++ io1_v_r = o_0_io1_v_r; ++ io2_v_r = o_0_io2_v_r; ++ } ++ self->private_impl.f_bitstream_bits = v_bits; ++ self->private_impl.f_bitstream_n_bits = v_n_bits; ++ return v_ret; ++} ++ ++// -------- func jpeg.decoder.decode_mcu_progressive_dc_high_bits ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu_progressive_dc_high_bits( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my) { ++ uint32_t v_ret = 0; ++ uint64_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint8_t v_csel = 0; ++ wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_r = &u_r; ++ const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint32_t v_pos = 0; ++ uint8_t v_dc_h = 0; ++ uint32_t v_dc_symbol = 0; ++ uint32_t v_dc_ht_fast = 0; ++ uint32_t v_dc_bl = 0; ++ uint32_t v_dc_code = 0; ++ uint32_t v_dc_blm1 = 0; ++ uint32_t v_dc_ht_slow = 0; ++ uint16_t v_dc_value = 0; ++ uint16_t v_dc_extend = 0; ++ ++ v_bits = self->private_impl.f_bitstream_bits; ++ v_n_bits = self->private_impl.f_bitstream_n_bits; ++ if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { ++ return 2u; ++ } ++ { ++ wuffs_base__io_buffer* o_0_v_r = v_r; ++ const uint8_t* o_0_iop_v_r = iop_v_r; ++ const uint8_t* o_0_io0_v_r = io0_v_r; ++ const uint8_t* o_0_io1_v_r = io1_v_r; ++ const uint8_t* o_0_io2_v_r = io2_v_r; ++ v_r = wuffs_private_impl__io_reader__set( ++ &u_r, ++ &iop_v_r, ++ &io0_v_r, ++ &io1_v_r, ++ &io2_v_r, ++ wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, ++ self->private_impl.f_bitstream_ri, ++ self->private_impl.f_bitstream_wi), ++ ((uint64_t)(self->private_impl.f_bitstream_ri))); ++ do { ++ while (self->private_impl.f_mcu_current_block < self->private_impl.f_mcu_num_blocks) { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { ++ v_ret = 1u; ++ goto label__goto_done__break; ++ } ++ do { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { ++ v_ret = 2u; ++ goto label__goto_done__break; ++ } ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ v_dc_h = self->private_impl.f_mcu_blocks_dc_hselector[self->private_impl.f_mcu_current_block]; ++ v_dc_ht_fast = ((uint32_t)(self->private_impl.f_huff_tables_fast[v_dc_h][(v_bits >> 56u)])); ++ v_dc_bl = (v_dc_ht_fast >> 8u); ++ if (v_n_bits >= v_dc_bl) { ++ v_dc_symbol = (15u & v_dc_ht_fast); ++ v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; ++ v_bits <<= (v_dc_bl & 63u); ++ v_n_bits -= v_dc_bl; ++ } else { ++ v_dc_code = ((uint32_t)((v_bits >> 55u))); ++ v_dc_blm1 = 8u; ++ v_bits <<= 9u; ++ v_n_bits -= 9u; ++ while (true) { ++ v_dc_ht_slow = self->private_impl.f_huff_tables_slow[v_dc_h][v_dc_blm1]; ++ if (v_dc_code < (v_dc_ht_slow >> 8u)) { ++ v_dc_symbol = (15u & ((uint32_t)(self->private_impl.f_huff_tables_symbols[v_dc_h][(255u & ((uint32_t)(v_dc_code + v_dc_ht_slow)))]))); ++ v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; ++ break; ++ } ++ v_dc_code = (((uint32_t)(v_dc_code << 1u)) | ((uint32_t)((v_bits >> 63u)))); ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ v_dc_blm1 = ((v_dc_blm1 + 1u) & 15u); ++ if (v_dc_blm1 == 0u) { ++ v_dc_symbol = 0u; ++ v_dc_extend = WUFFS_JPEG__EXTEND[v_dc_symbol]; ++ break; ++ } ++ } ++ } ++ v_dc_value = ((uint16_t)(((v_bits >> 32u) >> (32u - v_dc_symbol)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_dc_value += ((uint16_t)(v_dc_extend & ((uint16_t)(((uint16_t)(wuffs_base__utility__sign_extend_rshift_u64(v_bits, 63u))) ^ 65535u)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_bits <<= v_dc_symbol; ++ v_n_bits -= v_dc_symbol; ++ v_csel = self->private_impl.f_scan_comps_cselector[self->private_impl.f_mcu_blocks_sselector[self->private_impl.f_mcu_current_block]]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_mcu_previous_dc_values[v_csel] += v_dc_value; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ self->private_data.f_mcu_blocks[self->private_impl.f_mcu_current_block][0u] = ((uint16_t)(self->private_impl.f_mcu_previous_dc_values[v_csel] << self->private_impl.f_scan_al)); ++ } while (0); ++ self->private_impl.f_mcu_current_block += 1u; ++ } ++ self->private_impl.f_mcu_current_block = 0u; ++ } while (0); ++ label__goto_done__break:; ++ v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); ++ if (v_pos > self->private_impl.f_bitstream_wi) { ++ v_ret = 2u; ++ } else { ++ self->private_impl.f_bitstream_ri = v_pos; ++ } ++ v_r = o_0_v_r; ++ iop_v_r = o_0_iop_v_r; ++ io0_v_r = o_0_io0_v_r; ++ io1_v_r = o_0_io1_v_r; ++ io2_v_r = o_0_io2_v_r; ++ } ++ self->private_impl.f_bitstream_bits = v_bits; ++ self->private_impl.f_bitstream_n_bits = v_n_bits; ++ return v_ret; ++} ++ ++// -------- func jpeg.decoder.decode_mcu_progressive_dc_low_bit ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_jpeg__decoder__decode_mcu_progressive_dc_low_bit( ++ wuffs_jpeg__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf, ++ uint32_t a_mx, ++ uint32_t a_my) { ++ uint32_t v_ret = 0; ++ uint64_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint16_t v_one_lshift_scan_al = 0; ++ wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_r = &u_r; ++ const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint32_t v_pos = 0; ++ ++ v_bits = self->private_impl.f_bitstream_bits; ++ v_n_bits = self->private_impl.f_bitstream_n_bits; ++ v_one_lshift_scan_al = ((uint16_t)(((uint16_t)(1u)) << self->private_impl.f_scan_al)); ++ if (self->private_impl.f_bitstream_ri > self->private_impl.f_bitstream_wi) { ++ return 2u; ++ } ++ { ++ wuffs_base__io_buffer* o_0_v_r = v_r; ++ const uint8_t* o_0_iop_v_r = iop_v_r; ++ const uint8_t* o_0_io0_v_r = io0_v_r; ++ const uint8_t* o_0_io1_v_r = io1_v_r; ++ const uint8_t* o_0_io2_v_r = io2_v_r; ++ v_r = wuffs_private_impl__io_reader__set( ++ &u_r, ++ &iop_v_r, ++ &io0_v_r, ++ &io1_v_r, ++ &io2_v_r, ++ wuffs_base__make_slice_u8_ij(self->private_data.f_bitstream_buffer, ++ self->private_impl.f_bitstream_ri, ++ self->private_impl.f_bitstream_wi), ++ ((uint64_t)(self->private_impl.f_bitstream_ri))); ++ do { ++ while (self->private_impl.f_mcu_current_block < self->private_impl.f_mcu_num_blocks) { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 264u) { ++ v_ret = 1u; ++ goto label__goto_done__break; ++ } ++ do { ++ if (((uint64_t)(io2_v_r - iop_v_r)) < 8u) { ++ v_ret = 2u; ++ goto label__goto_done__break; ++ } ++ v_bits |= (wuffs_base__peek_u64be__no_bounds_check(iop_v_r) >> (v_n_bits & 63u)); ++ iop_v_r += ((63u - (v_n_bits & 63u)) >> 3u); ++ v_n_bits |= 56u; ++ if ((v_bits >> 63u) != 0u) { ++ self->private_data.f_mcu_blocks[self->private_impl.f_mcu_current_block][0u] |= v_one_lshift_scan_al; ++ } ++ v_bits <<= 1u; ++ v_n_bits -= 1u; ++ } while (0); ++ self->private_impl.f_mcu_current_block += 1u; ++ } ++ self->private_impl.f_mcu_current_block = 0u; ++ } while (0); ++ label__goto_done__break:; ++ v_pos = ((uint32_t)(wuffs_base__u64__sat_add((v_r ? v_r->meta.pos : 0), ((uint64_t)(iop_v_r - io0_v_r))))); ++ if (v_pos > self->private_impl.f_bitstream_wi) { ++ v_ret = 2u; ++ } else { ++ self->private_impl.f_bitstream_ri = v_pos; ++ } ++ v_r = o_0_v_r; ++ iop_v_r = o_0_iop_v_r; ++ io0_v_r = o_0_io0_v_r; ++ io1_v_r = o_0_io1_v_r; ++ io2_v_r = o_0_io2_v_r; ++ } ++ self->private_impl.f_bitstream_bits = v_bits; ++ self->private_impl.f_bitstream_n_bits = v_n_bits; ++ return v_ret; ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JPEG) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_json__error__bad_c0_control_code[] = "#json: bad C0 control code"; ++const char wuffs_json__error__bad_utf_8[] = "#json: bad UTF-8"; ++const char wuffs_json__error__bad_backslash_escape[] = "#json: bad backslash-escape"; ++const char wuffs_json__error__bad_input[] = "#json: bad input"; ++const char wuffs_json__error__bad_new_line_in_a_string[] = "#json: bad new-line in a string"; ++const char wuffs_json__error__bad_quirk_combination[] = "#json: bad quirk combination"; ++const char wuffs_json__error__unsupported_number_length[] = "#json: unsupported number length"; ++const char wuffs_json__error__unsupported_recursion_depth[] = "#json: unsupported recursion depth"; ++const char wuffs_json__error__internal_error_inconsistent_i_o[] = "#json: internal error: inconsistent I/O"; ++ ++// ---------------- Private Consts ++ ++#define WUFFS_JSON__DECODER_NUMBER_LENGTH_MAX_INCL 99u ++ ++static const uint8_t ++WUFFS_JSON__LUT_BACKSLASHES[256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 3u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 162u, 0u, 0u, 0u, 0u, 5u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 175u, ++ 7u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 4u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 220u, 0u, 0u, 0u, ++ 0u, 1u, 136u, 0u, 0u, 2u, 140u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 138u, 0u, ++ 0u, 0u, 141u, 0u, 137u, 0u, 6u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++}; ++ ++static const uint8_t ++WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 1u, 3u, 4u, 5u, 6u, 7u, 10u, ++}; ++ ++static const uint8_t ++WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_CHARS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 7u, 27u, 10u, 63u, 39u, 11u, 0u, ++}; ++ ++static const uint8_t ++WUFFS_JSON__LUT_CHARS[256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 128u, 129u, 130u, 131u, 132u, 133u, 134u, 135u, ++ 136u, 137u, 138u, 139u, 140u, 141u, 142u, 143u, ++ 144u, 145u, 146u, 147u, 148u, 149u, 150u, 151u, ++ 152u, 153u, 154u, 155u, 156u, 157u, 158u, 159u, ++ 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 2u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, ++ 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, ++ 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, ++ 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, ++ 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, ++ 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, ++ 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, ++ 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, ++ 32u, 32u, 3u, 3u, 3u, 3u, 3u, 3u, ++ 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, ++ 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, ++ 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, ++ 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, ++ 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, ++ 5u, 5u, 5u, 5u, 5u, 32u, 32u, 32u, ++ 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, ++}; ++ ++#define WUFFS_JSON__CLASS_WHITESPACE 0u ++ ++#define WUFFS_JSON__CLASS_STRING 1u ++ ++#define WUFFS_JSON__CLASS_COMMA 2u ++ ++#define WUFFS_JSON__CLASS_COLON 3u ++ ++#define WUFFS_JSON__CLASS_NUMBER 4u ++ ++#define WUFFS_JSON__CLASS_OPEN_CURLY_BRACE 5u ++ ++#define WUFFS_JSON__CLASS_CLOSE_CURLY_BRACE 6u ++ ++#define WUFFS_JSON__CLASS_OPEN_SQUARE_BRACKET 7u ++ ++#define WUFFS_JSON__CLASS_CLOSE_SQUARE_BRACKET 8u ++ ++#define WUFFS_JSON__CLASS_FALSE 9u ++ ++#define WUFFS_JSON__CLASS_TRUE 10u ++ ++#define WUFFS_JSON__CLASS_NULL_NAN_INF 11u ++ ++#define WUFFS_JSON__CLASS_COMMENT 12u ++ ++#define WUFFS_JSON__EXPECT_VALUE 7858u ++ ++#define WUFFS_JSON__EXPECT_NON_STRING_VALUE 7856u ++ ++#define WUFFS_JSON__EXPECT_STRING 4098u ++ ++#define WUFFS_JSON__EXPECT_COMMA 4100u ++ ++#define WUFFS_JSON__EXPECT_COLON 4104u ++ ++#define WUFFS_JSON__EXPECT_NUMBER 4112u ++ ++#define WUFFS_JSON__EXPECT_CLOSE_CURLY_BRACE 4160u ++ ++#define WUFFS_JSON__EXPECT_CLOSE_SQUARE_BRACKET 4352u ++ ++static const uint8_t ++WUFFS_JSON__LUT_CLASSES[256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 0u, 0u, 15u, 15u, 0u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 0u, 15u, 1u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 11u, 2u, 4u, 15u, 12u, ++ 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, ++ 4u, 4u, 3u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 11u, 15u, 15u, 15u, 15u, 11u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 7u, 15u, 8u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 9u, 15u, ++ 15u, 11u, 15u, 15u, 15u, 15u, 11u, 15u, ++ 15u, 15u, 15u, 15u, 10u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 5u, 15u, 6u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++ 15u, 15u, 15u, 15u, 15u, 15u, 15u, 15u, ++}; ++ ++static const uint8_t ++WUFFS_JSON__LUT_DECIMAL_DIGITS[256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 128u, 129u, 130u, 131u, 132u, 133u, 134u, 135u, ++ 136u, 137u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++}; ++ ++static const uint8_t ++WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 128u, 129u, 130u, 131u, 132u, 133u, 134u, 135u, ++ 136u, 137u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 138u, 139u, 140u, 141u, 142u, 143u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 138u, 139u, 140u, 141u, 142u, 143u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++}; ++ ++#define WUFFS_JSON__QUIRKS_BASE 1225364480u ++ ++#define WUFFS_JSON__QUIRKS_COUNT 21u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_json__decoder__decode_number( ++ wuffs_json__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_json__decoder__decode_digits( ++ wuffs_json__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_n); ++ ++WUFFS_BASE__GENERATED_C_CODE ++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__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_json__decoder__decode_comment( ++ wuffs_json__decoder* self, ++ wuffs_base__token_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_json__decoder__decode_inf_nan( ++ wuffs_json__decoder* self, ++ wuffs_base__token_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_json__decoder__decode_trailer( ++ wuffs_json__decoder* self, ++ wuffs_base__token_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++// ---------------- VTables ++ ++const wuffs_base__token_decoder__func_ptrs ++wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__token_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_json__decoder__decode_tokens), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_json__decoder__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_json__decoder__set_quirk), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_json__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_json__decoder__initialize( ++ wuffs_json__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name = ++ wuffs_base__token_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers = ++ (const void*)(&wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_json__decoder* ++wuffs_json__decoder__alloc(void) { ++ wuffs_json__decoder* x = ++ (wuffs_json__decoder*)(calloc(1, sizeof(wuffs_json__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_json__decoder__initialize( ++ x, sizeof(wuffs_json__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_json__decoder(void) { ++ return sizeof(wuffs_json__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func json.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_json__decoder__get_quirk( ++ const wuffs_json__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ uint32_t v_key = 0; ++ ++ if (a_key >= 1225364480u) { ++ v_key = (a_key - 1225364480u); ++ if (v_key < 21u) { ++ if (self->private_impl.f_quirks[v_key]) { ++ return 1u; ++ } ++ } ++ } ++ return 0u; ++} ++ ++// -------- func json.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_json__decoder__set_quirk( ++ wuffs_json__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (a_key >= 1225364480u) { ++ a_key -= 1225364480u; ++ if (a_key < 21u) { ++ self->private_impl.f_quirks[a_key] = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } ++ } ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func json.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_json__decoder__workbuf_len( ++ const wuffs_json__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__empty_range_ii_u64(); ++} ++ ++// -------- func json.decoder.decode_tokens ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_json__decoder__decode_tokens( ++ wuffs_json__decoder* self, ++ wuffs_base__token_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_vminor = 0; ++ uint32_t v_number_length = 0; ++ uint32_t v_number_status = 0; ++ uint32_t v_string_length = 0; ++ uint32_t v_whitespace_length = 0; ++ uint32_t v_depth = 0; ++ uint32_t v_stack_byte = 0; ++ uint32_t v_stack_bit = 0; ++ uint32_t v_match = 0; ++ uint32_t v_c32 = 0; ++ uint8_t v_c8 = 0; ++ uint8_t v_backslash = 0; ++ uint8_t v_char = 0; ++ uint8_t v_class = 0; ++ uint32_t v_multi_byte_utf8 = 0; ++ uint8_t v_backslash_x_ok = 0; ++ uint8_t v_backslash_x_value = 0; ++ uint32_t v_backslash_x_string = 0; ++ uint8_t v_uni4_ok = 0; ++ uint64_t v_uni4_string = 0; ++ uint32_t v_uni4_value = 0; ++ uint32_t v_uni4_high_surrogate = 0; ++ uint8_t v_uni8_ok = 0; ++ uint64_t v_uni8_string = 0; ++ uint32_t v_uni8_value = 0; ++ uint32_t v_expect = 0; ++ uint32_t v_expect_after_value = 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 && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_tokens; ++ if (coro_susp_point) { ++ v_depth = self->private_data.s_decode_tokens.v_depth; ++ v_expect = self->private_data.s_decode_tokens.v_expect; ++ v_expect_after_value = self->private_data.s_decode_tokens.v_expect_after_value; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_end_of_data) { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ if (self->private_impl.f_quirks[18u]) { ++ if (self->private_impl.f_quirks[11u] || self->private_impl.f_quirks[12u] || self->private_impl.f_quirks[17u]) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_quirk_combination); ++ goto exit; ++ } ++ } ++ if (self->private_impl.f_quirks[15u] || self->private_impl.f_quirks[16u]) { ++ 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 = 7858u; ++ label__outer__continue:; ++ while (true) { ++ while (true) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ goto label__outer__continue; ++ } ++ v_whitespace_length = 0u; ++ v_c8 = 0u; ++ v_class = 0u; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (v_whitespace_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_whitespace_length = 0u; ++ } ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ goto label__outer__continue; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ v_class = WUFFS_JSON__LUT_CLASSES[v_c8]; ++ if (v_class != 0u) { ++ break; ++ } ++ iop_a_src += 1u; ++ if (v_whitespace_length >= 65534u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(65535u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_whitespace_length = 0u; ++ goto label__outer__continue; ++ } ++ v_whitespace_length += 1u; ++ } ++ if (v_whitespace_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_whitespace_length = 0u; ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ goto label__outer__continue; ++ } ++ } ++ if (0u == (v_expect & (((uint32_t)(1u)) << v_class))) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ if (v_class == 1u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 1u; ++ label__string_loop_outer__continue:; ++ while (true) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ continue; ++ } ++ v_string_length = 0u; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (v_string_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ } ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ goto label__string_loop_outer__continue; ++ } ++ while (((uint64_t)(io2_a_src - iop_a_src)) > 4u) { ++ v_c32 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ if (0u != (WUFFS_JSON__LUT_CHARS[(255u & (v_c32 >> 0u))] | ++ WUFFS_JSON__LUT_CHARS[(255u & (v_c32 >> 8u))] | ++ WUFFS_JSON__LUT_CHARS[(255u & (v_c32 >> 16u))] | ++ WUFFS_JSON__LUT_CHARS[(255u & (v_c32 >> 24u))])) { ++ break; ++ } ++ iop_a_src += 4u; ++ if (v_string_length > 65527u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)((v_string_length + 4u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ goto label__string_loop_outer__continue; ++ } ++ v_string_length += 4u; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ v_char = WUFFS_JSON__LUT_CHARS[v_c8]; ++ if (v_char == 0u) { ++ iop_a_src += 1u; ++ if (v_string_length >= 65531u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(65532u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ goto label__string_loop_outer__continue; ++ } ++ v_string_length += 1u; ++ continue; ++ } else if (v_char == 1u) { ++ if (v_string_length != 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ } ++ goto label__string_loop_outer__break; ++ } else if (v_char == 2u) { ++ if (v_string_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ goto label__string_loop_outer__continue; ++ } ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); ++ goto label__string_loop_outer__continue; ++ } ++ v_c8 = ((uint8_t)(((uint16_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8u)))); ++ v_backslash = WUFFS_JSON__LUT_BACKSLASHES[v_c8]; ++ if (((uint8_t)(v_backslash & 128u)) != 0u) { ++ iop_a_src += 2u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((6291456u | ((uint32_t)(((uint8_t)(v_backslash & 127u))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } else if (v_backslash != 0u) { ++ if (self->private_impl.f_quirks[WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[((uint8_t)(v_backslash & 7u))]]) { ++ iop_a_src += 2u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((6291456u | ((uint32_t)(WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_CHARS[((uint8_t)(v_backslash & 7u))]))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } ++ } else if (v_c8 == 117u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 6u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); ++ goto label__string_loop_outer__continue; ++ } ++ v_uni4_string = (((uint64_t)(wuffs_base__peek_u48le__no_bounds_check(iop_a_src))) >> 16u); ++ v_uni4_value = 0u; ++ v_uni4_ok = 128u; ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 0u))]; ++ v_uni4_ok &= v_c8; ++ v_uni4_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 12u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 8u))]; ++ v_uni4_ok &= v_c8; ++ v_uni4_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 8u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 16u))]; ++ v_uni4_ok &= v_c8; ++ v_uni4_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 4u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 24u))]; ++ v_uni4_ok &= v_c8; ++ v_uni4_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 0u); ++ if (v_uni4_ok == 0u) { ++ } else if ((v_uni4_value < 55296u) || (57343u < v_uni4_value)) { ++ iop_a_src += 6u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((6291456u | v_uni4_value))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(6u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } else if (v_uni4_value >= 56320u) { ++ } else { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 12u) { ++ if (a_src && a_src->meta.closed) { ++ if (self->private_impl.f_quirks[20u]) { ++ iop_a_src += 6u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(6u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); ++ goto label__string_loop_outer__continue; ++ } ++ v_uni4_string = (wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 4u) >> 16u); ++ if (((255u & (v_uni4_string >> 0u)) != 92u) || ((255u & (v_uni4_string >> 8u)) != 117u)) { ++ v_uni4_high_surrogate = 0u; ++ v_uni4_value = 0u; ++ v_uni4_ok = 0u; ++ } else { ++ v_uni4_high_surrogate = (65536u + ((v_uni4_value - 55296u) << 10u)); ++ v_uni4_value = 0u; ++ v_uni4_ok = 128u; ++ v_uni4_string >>= 16u; ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 0u))]; ++ v_uni4_ok &= v_c8; ++ v_uni4_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 12u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 8u))]; ++ v_uni4_ok &= v_c8; ++ v_uni4_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 8u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 16u))]; ++ v_uni4_ok &= v_c8; ++ v_uni4_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 4u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni4_string >> 24u))]; ++ v_uni4_ok &= v_c8; ++ v_uni4_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 0u); ++ } ++ if ((v_uni4_ok != 0u) && (56320u <= v_uni4_value) && (v_uni4_value <= 57343u)) { ++ v_uni4_value -= 56320u; ++ iop_a_src += 12u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((6291456u | v_uni4_high_surrogate | v_uni4_value))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(12u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } ++ } ++ if (self->private_impl.f_quirks[20u]) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 6u) { ++ status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ iop_a_src += 6u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(6u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } ++ } else if ((v_c8 == 85u) && self->private_impl.f_quirks[2u]) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 10u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); ++ goto label__string_loop_outer__continue; ++ } ++ v_uni8_string = wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 2u); ++ v_uni8_value = 0u; ++ v_uni8_ok = 128u; ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 0u))]; ++ v_uni8_ok &= v_c8; ++ v_uni8_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 28u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 8u))]; ++ v_uni8_ok &= v_c8; ++ v_uni8_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 24u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 16u))]; ++ v_uni8_ok &= v_c8; ++ v_uni8_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 20u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 24u))]; ++ v_uni8_ok &= v_c8; ++ v_uni8_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 16u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 32u))]; ++ v_uni8_ok &= v_c8; ++ v_uni8_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 12u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 40u))]; ++ v_uni8_ok &= v_c8; ++ v_uni8_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 8u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 48u))]; ++ v_uni8_ok &= v_c8; ++ v_uni8_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 4u); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_uni8_string >> 56u))]; ++ v_uni8_ok &= v_c8; ++ v_uni8_value |= (((uint32_t)(((uint8_t)(v_c8 & 15u)))) << 0u); ++ if (v_uni8_ok == 0u) { ++ } else if ((v_uni8_value < 55296u) || ((57343u < v_uni8_value) && (v_uni8_value <= 1114111u))) { ++ iop_a_src += 10u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((6291456u | (v_uni8_value & 2097151u)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(10u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } else if (self->private_impl.f_quirks[20u]) { ++ iop_a_src += 10u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(10u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } ++ } else if ((v_c8 == 120u) && self->private_impl.f_quirks[9u]) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); ++ goto label__string_loop_outer__continue; ++ } ++ v_backslash_x_string = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ v_backslash_x_ok = 128u; ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_backslash_x_string >> 16u))]; ++ v_backslash_x_ok &= v_c8; ++ v_backslash_x_value = ((uint8_t)(((uint8_t)(((uint8_t)(v_c8 & 15u)) << 4u)))); ++ v_c8 = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255u & (v_backslash_x_string >> 24u))]; ++ v_backslash_x_ok &= v_c8; ++ v_backslash_x_value = ((uint8_t)(((uint8_t)(v_backslash_x_value | ((uint8_t)(v_c8 & 15u)))))); ++ if ((v_backslash_x_ok == 0u) || ((v_backslash_x_string & 65535u) != 30812u)) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); ++ goto exit; ++ } ++ iop_a_src += 4u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((6291456u | ((uint32_t)(v_backslash_x_value))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__string_loop_outer__continue; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape); ++ goto exit; ++ } else if (v_char == 3u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { ++ if (v_string_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ goto label__string_loop_outer__continue; ++ } ++ } ++ if (a_src && a_src->meta.closed) { ++ if (self->private_impl.f_quirks[20u]) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 1u; ++ goto label__string_loop_outer__continue; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_utf_8); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); ++ goto label__string_loop_outer__continue; ++ } ++ v_multi_byte_utf8 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ if ((v_multi_byte_utf8 & 49152u) == 32768u) { ++ v_multi_byte_utf8 = ((1984u & ((uint32_t)(v_multi_byte_utf8 << 6u))) | (63u & (v_multi_byte_utf8 >> 8u))); ++ iop_a_src += 2u; ++ if (v_string_length >= 65528u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)((v_string_length + 2u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ goto label__string_loop_outer__continue; ++ } ++ v_string_length += 2u; ++ continue; ++ } ++ } else if (v_char == 4u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 3u) { ++ if (v_string_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ goto label__string_loop_outer__continue; ++ } ++ } ++ if (a_src && a_src->meta.closed) { ++ if (self->private_impl.f_quirks[20u]) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 1u; ++ goto label__string_loop_outer__continue; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_utf_8); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12); ++ goto label__string_loop_outer__continue; ++ } ++ v_multi_byte_utf8 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); ++ if ((v_multi_byte_utf8 & 12632064u) == 8421376u) { ++ v_multi_byte_utf8 = ((61440u & ((uint32_t)(v_multi_byte_utf8 << 12u))) | (4032u & (v_multi_byte_utf8 >> 2u)) | (63u & (v_multi_byte_utf8 >> 16u))); ++ if ((2047u < v_multi_byte_utf8) && ((v_multi_byte_utf8 < 55296u) || (57343u < v_multi_byte_utf8))) { ++ iop_a_src += 3u; ++ if (v_string_length >= 65528u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)((v_string_length + 3u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ goto label__string_loop_outer__continue; ++ } ++ v_string_length += 3u; ++ continue; ++ } ++ } ++ } else if (v_char == 5u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ if (v_string_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ goto label__string_loop_outer__continue; ++ } ++ } ++ if (a_src && a_src->meta.closed) { ++ if (self->private_impl.f_quirks[20u]) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 1u; ++ goto label__string_loop_outer__continue; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_utf_8); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(13); ++ goto label__string_loop_outer__continue; ++ } ++ v_multi_byte_utf8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ if ((v_multi_byte_utf8 & 3233857536u) == 2155905024u) { ++ v_multi_byte_utf8 = ((1835008u & ((uint32_t)(v_multi_byte_utf8 << 18u))) | ++ (258048u & ((uint32_t)(v_multi_byte_utf8 << 4u))) | ++ (4032u & (v_multi_byte_utf8 >> 10u)) | ++ (63u & (v_multi_byte_utf8 >> 24u))); ++ if ((65535u < v_multi_byte_utf8) && (v_multi_byte_utf8 <= 1114111u)) { ++ iop_a_src += 4u; ++ if (v_string_length >= 65528u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)((v_string_length + 4u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ goto label__string_loop_outer__continue; ++ } ++ v_string_length += 4u; ++ continue; ++ } ++ } ++ } ++ if (v_string_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194819u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_string_length = 0u; ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ goto label__string_loop_outer__continue; ++ } ++ } ++ if (((uint8_t)(v_char & 128u)) != 0u) { ++ if (self->private_impl.f_quirks[0u]) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((6291456u | ((uint32_t)(((uint8_t)(v_char & 127u))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 1u; ++ goto label__string_loop_outer__continue; ++ } ++ if (v_char == 138u) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_new_line_in_a_string); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_c0_control_code); ++ goto exit; ++ } ++ if (self->private_impl.f_quirks[20u]) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(6356989u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 1u; ++ goto label__string_loop_outer__continue; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_utf_8); ++ goto exit; ++ } ++ } ++ label__string_loop_outer__break:; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14); ++ continue; ++ } ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15); ++ continue; ++ } ++ iop_a_src += 1u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4194579u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ break; ++ } ++ if (0u == (v_expect & (((uint32_t)(1u)) << 4u))) { ++ v_expect = 4104u; ++ goto label__outer__continue; ++ } ++ break; ++ } else if (v_class == 2u) { ++ iop_a_src += 1u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (0u == (v_expect & (((uint32_t)(1u)) << 8u))) { ++ if (self->private_impl.f_quirks[13u]) { ++ v_expect = 4162u; ++ } else { ++ v_expect = 4098u; ++ } ++ } else { ++ if (self->private_impl.f_quirks[13u]) { ++ v_expect = 8114u; ++ } else { ++ v_expect = 7858u; ++ } ++ } ++ goto label__outer__continue; ++ } else if (v_class == 3u) { ++ iop_a_src += 1u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_expect = 7858u; ++ goto label__outer__continue; ++ } else if (v_class == 4u) { ++ while (true) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_number_length = wuffs_json__decoder__decode_number(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ v_number_status = (v_number_length >> 8u); ++ v_vminor = 10486787u; ++ if ((v_number_length & 128u) != 0u) { ++ v_vminor = 10486785u; ++ } ++ v_number_length = (v_number_length & 127u); ++ if (v_number_status == 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_number_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ break; ++ } ++ while (v_number_length > 0u) { ++ v_number_length -= 1u; ++ if (iop_a_src > io1_a_src) { ++ iop_a_src--; ++ } else { ++ status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ } ++ if (v_number_status == 1u) { ++ if (self->private_impl.f_quirks[14u]) { ++ 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(16); ++ status = wuffs_json__decoder__decode_inf_nan(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; ++ } ++ break; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } else if (v_number_status == 2u) { ++ status = wuffs_base__make_status(wuffs_json__error__unsupported_number_length); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17); ++ while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(18); ++ } ++ } ++ } ++ break; ++ } else if (v_class == 5u) { ++ v_vminor = 2113553u; ++ if (v_depth == 0u) { ++ } else if (0u != (v_expect_after_value & (((uint32_t)(1u)) << 6u))) { ++ v_vminor = 2113601u; ++ } else { ++ v_vminor = 2113569u; ++ } ++ if (v_depth >= 1024u) { ++ status = wuffs_base__make_status(wuffs_json__error__unsupported_recursion_depth); ++ goto exit; ++ } ++ v_stack_byte = (v_depth / 32u); ++ v_stack_bit = (v_depth & 31u); ++ self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(1u)) << v_stack_bit); ++ v_depth += 1u; ++ iop_a_src += 1u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_expect = 4162u; ++ v_expect_after_value = 4164u; ++ goto label__outer__continue; ++ } else if (v_class == 6u) { ++ iop_a_src += 1u; ++ if (v_depth <= 1u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2101314u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__outer__break; ++ } ++ v_depth -= 1u; ++ v_stack_byte = ((v_depth - 1u) / 32u); ++ v_stack_bit = ((v_depth - 1u) & 31u); ++ if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2105410u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_expect = 4356u; ++ v_expect_after_value = 4356u; ++ } else { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2113602u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_expect = 4164u; ++ v_expect_after_value = 4164u; ++ } ++ goto label__outer__continue; ++ } else if (v_class == 7u) { ++ v_vminor = 2105361u; ++ if (v_depth == 0u) { ++ } else if (0u != (v_expect_after_value & (((uint32_t)(1u)) << 6u))) { ++ v_vminor = 2105409u; ++ } else { ++ v_vminor = 2105377u; ++ } ++ if (v_depth >= 1024u) { ++ status = wuffs_base__make_status(wuffs_json__error__unsupported_recursion_depth); ++ goto exit; ++ } ++ v_stack_byte = (v_depth / 32u); ++ v_stack_bit = (v_depth & 31u); ++ self->private_data.f_stack[v_stack_byte] &= (4294967295u ^ (((uint32_t)(1u)) << v_stack_bit)); ++ v_depth += 1u; ++ iop_a_src += 1u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_expect = 8114u; ++ v_expect_after_value = 4356u; ++ goto label__outer__continue; ++ } else if (v_class == 8u) { ++ iop_a_src += 1u; ++ if (v_depth <= 1u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2101282u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ goto label__outer__break; ++ } ++ v_depth -= 1u; ++ v_stack_byte = ((v_depth - 1u) / 32u); ++ v_stack_bit = ((v_depth - 1u) & 31u); ++ if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2105378u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_expect = 4356u; ++ v_expect_after_value = 4356u; ++ } else { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2113570u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ v_expect = 4164u; ++ v_expect_after_value = 4164u; ++ } ++ goto label__outer__continue; ++ } else if (v_class == 9u) { ++ v_match = wuffs_private_impl__io_reader__match7(iop_a_src, io2_a_src, a_src, 111546413966853u); ++ if (v_match == 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(8388612u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(5u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 5u) { ++ status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ iop_a_src += 5u; ++ break; ++ } else if (v_match == 1u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(19); ++ goto label__outer__continue; ++ } ++ } else if (v_class == 10u) { ++ v_match = wuffs_private_impl__io_reader__match7(iop_a_src, io2_a_src, a_src, 435762131972u); ++ if (v_match == 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(8388616u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ iop_a_src += 4u; ++ break; ++ } else if (v_match == 1u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(20); ++ goto label__outer__continue; ++ } ++ } else if (v_class == 11u) { ++ v_match = wuffs_private_impl__io_reader__match7(iop_a_src, io2_a_src, a_src, 465676103172u); ++ if (v_match == 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(8388610u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ iop_a_src += 4u; ++ break; ++ } else if (v_match == 1u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(21); ++ goto label__outer__continue; ++ } ++ if (self->private_impl.f_quirks[14u]) { ++ 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(22); ++ status = wuffs_json__decoder__decode_inf_nan(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; ++ } ++ break; ++ } ++ } else if (v_class == 12u) { ++ if (self->private_impl.f_quirks[11u] || self->private_impl.f_quirks[12u]) { ++ 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(23); ++ status = wuffs_json__decoder__decode_comment(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; ++ } ++ if (self->private_impl.f_comment_type > 0u) { ++ goto label__outer__continue; ++ } ++ } ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ if (v_depth == 0u) { ++ break; ++ } ++ v_expect = v_expect_after_value; ++ } ++ label__outer__break:; ++ if (self->private_impl.f_quirks[17u] || self->private_impl.f_quirks[18u]) { ++ 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(24); ++ status = wuffs_json__decoder__decode_trailer(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; ++ } ++ } ++ self->private_impl.f_end_of_data = true; ++ ++ ok: ++ self->private_impl.p_decode_tokens = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_tokens = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ self->private_data.s_decode_tokens.v_depth = v_depth; ++ self->private_data.s_decode_tokens.v_expect = v_expect; ++ self->private_data.s_decode_tokens.v_expect_after_value = v_expect_after_value; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func json.decoder.decode_number ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_json__decoder__decode_number( ++ wuffs_json__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ uint8_t v_c8 = 0; ++ uint32_t v_n = 0; ++ uint32_t v_floating_point = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } ++ ++ do { ++ v_n = 0u; ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if ( ! (a_src && a_src->meta.closed)) { ++ v_n |= 768u; ++ } ++ break; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if (v_c8 != 45u) { ++ } else { ++ v_n += 1u; ++ iop_a_src += 1u; ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if ( ! (a_src && a_src->meta.closed)) { ++ v_n |= 768u; ++ } ++ v_n |= 256u; ++ break; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ } ++ if (v_c8 == 48u) { ++ v_n += 1u; ++ iop_a_src += 1u; ++ } else { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (v_n > 99u) { ++ break; ++ } ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if ( ! (a_src && a_src->meta.closed)) { ++ v_n |= 768u; ++ } ++ break; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if (v_c8 != 46u) { ++ } else { ++ if (v_n >= 99u) { ++ v_n |= 512u; ++ break; ++ } ++ v_n += 1u; ++ iop_a_src += 1u; ++ v_floating_point = 128u; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (v_n > 99u) { ++ break; ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if ( ! (a_src && a_src->meta.closed)) { ++ v_n |= 768u; ++ } ++ break; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ } ++ if ((v_c8 != 69u) && (v_c8 != 101u)) { ++ break; ++ } ++ if (v_n >= 99u) { ++ v_n |= 512u; ++ break; ++ } ++ v_n += 1u; ++ iop_a_src += 1u; ++ v_floating_point = 128u; ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if ( ! (a_src && a_src->meta.closed)) { ++ v_n |= 768u; ++ } ++ v_n |= 256u; ++ break; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if ((v_c8 != 43u) && (v_c8 != 45u)) { ++ } else { ++ if (v_n >= 99u) { ++ v_n |= 512u; ++ break; ++ } ++ v_n += 1u; ++ iop_a_src += 1u; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } while (0); ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ return (v_n | v_floating_point); ++} ++ ++// -------- func json.decoder.decode_digits ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_json__decoder__decode_digits( ++ wuffs_json__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_n) { ++ uint8_t v_c8 = 0; ++ uint32_t v_n = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } ++ ++ v_n = a_n; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if ( ! (a_src && a_src->meta.closed)) { ++ v_n |= 768u; ++ } ++ break; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if (0u == WUFFS_JSON__LUT_DECIMAL_DIGITS[v_c8]) { ++ break; ++ } ++ if (v_n >= 99u) { ++ v_n |= 512u; ++ break; ++ } ++ v_n += 1u; ++ iop_a_src += 1u; ++ } ++ if (v_n == a_n) { ++ v_n |= 256u; ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ return v_n; ++} ++ ++// -------- func json.decoder.decode_leading ++ ++WUFFS_BASE__GENERATED_C_CODE ++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_c8 = 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 && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ self->private_impl.f_allow_leading_ars = self->private_impl.f_quirks[15u]; ++ self->private_impl.f_allow_leading_ubom = self->private_impl.f_quirks[16u]; ++ while (self->private_impl.f_allow_leading_ars || self->private_impl.f_allow_leading_ubom) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ continue; ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ break; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ continue; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if ((v_c8 == 30u) && self->private_impl.f_allow_leading_ars) { ++ self->private_impl.f_allow_leading_ars = false; ++ iop_a_src += 1u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ continue; ++ } else if ((v_c8 == 239u) && self->private_impl.f_allow_leading_ubom) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 3u) { ++ if (a_src && a_src->meta.closed) { ++ break; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ continue; ++ } ++ v_u = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); ++ if (v_u == 12565487u) { ++ self->private_impl.f_allow_leading_ubom = false; ++ iop_a_src += 3u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(3u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ continue; ++ } ++ } ++ break; ++ } ++ ++ ok: ++ self->private_impl.p_decode_leading = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_leading = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func json.decoder.decode_comment ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_json__decoder__decode_comment( ++ 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_c8 = 0; ++ uint16_t v_c16 = 0; ++ uint32_t v_length = 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 && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_comment; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ self->private_impl.f_comment_type = 0u; ++ while ((((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) || (((uint64_t)(io2_a_src - iop_a_src)) <= 1u)) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ continue; ++ } ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ } ++ v_c16 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); ++ if ((v_c16 == 10799u) && self->private_impl.f_quirks[11u]) { ++ iop_a_src += 2u; ++ v_length = 2u; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 1u) { ++ if (v_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ } ++ v_length = 0u; ++ continue; ++ } ++ v_c16 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); ++ if (v_c16 == 12074u) { ++ iop_a_src += 2u; ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)((v_length + 2u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ self->private_impl.f_comment_type = 1u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ iop_a_src += 1u; ++ if (v_length >= 65533u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)((v_length + 1u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ } ++ v_length = 0u; ++ continue; ++ } ++ v_length += 1u; ++ } ++ } else if ((v_c16 == 12079u) && self->private_impl.f_quirks[12u]) { ++ iop_a_src += 2u; ++ v_length = 2u; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ self->private_impl.f_comment_type = 2u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } else if (v_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); ++ while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); ++ } ++ v_length = 0u; ++ continue; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if (v_c8 == 10u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ self->private_impl.f_comment_type = 2u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ iop_a_src += 1u; ++ if (v_length >= 65533u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | ++ (((uint64_t)((v_length + 1u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); ++ } ++ v_length = 0u; ++ continue; ++ } ++ v_length += 1u; ++ } ++ } ++ ++ ok: ++ self->private_impl.p_decode_comment = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_comment = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func json.decoder.decode_inf_nan ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_json__decoder__decode_inf_nan( ++ 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); ++ ++ uint32_t v_c32 = 0; ++ uint32_t v_neg = 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 && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_inf_nan; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ continue; ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 2u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ continue; ++ } ++ v_c32 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); ++ if ((v_c32 | 2105376u) == 6712937u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) > 7u) { ++ if ((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) | 2314885530818453536u) == 8751735898823356009u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(10485792u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(8u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 8u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ } else if ( ! (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ continue; ++ } ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(10485792u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(3u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 3u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } else if ((v_c32 | 2105376u) == 7233902u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(10485888u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(3u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 3u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } else if ((v_c32 & 255u) == 43u) { ++ v_neg = 0u; ++ } else if ((v_c32 & 255u) == 45u) { ++ v_neg = 1u; ++ } else { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 3u) { ++ if (a_src && a_src->meta.closed) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ continue; ++ } ++ v_c32 = (wuffs_base__peek_u32le__no_bounds_check(iop_a_src) >> 8u); ++ if ((v_c32 | 2105376u) == 6712937u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) > 8u) { ++ if ((wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 1u) | 2314885530818453536u) == 8751735898823356009u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((10485760u | (((uint32_t)(32u)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(9u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 9u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ } else if ( ! (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ continue; ++ } ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((10485760u | (((uint32_t)(32u)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 4u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } else if ((v_c32 | 2105376u) == 7233902u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)((10485760u | (((uint32_t)(128u)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ iop_a_src += 4u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto exit; ++ } ++ ++ ok: ++ self->private_impl.p_decode_inf_nan = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_inf_nan = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func json.decoder.decode_trailer ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_json__decoder__decode_trailer( ++ 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_c8 = 0; ++ uint32_t v_whitespace_length = 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 && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_trailer; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_quirks[18u]) { ++ self->private_impl.f_trailer_stop = 10u; ++ } else { ++ self->private_impl.f_trailer_stop = 0u; ++ } ++ label__outer__continue:; ++ while (true) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ continue; ++ } ++ v_whitespace_length = 0u; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (v_whitespace_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } ++ if (a_src && a_src->meta.closed) { ++ goto label__outer__break; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ goto label__outer__continue; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if (WUFFS_JSON__LUT_CLASSES[v_c8] != 0u) { ++ if (v_whitespace_length > 0u) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ } ++ if (self->private_impl.f_trailer_stop > 0u) { ++ status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ goto 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)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_json__decoder__decode_comment(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; ++ } ++ if (self->private_impl.f_comment_type > 0u) { ++ goto label__outer__continue; ++ } ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ iop_a_src += 1u; ++ if ((v_whitespace_length >= 65534u) || (v_c8 == self->private_impl.f_trailer_stop)) { ++ *iop_a_dst++ = wuffs_base__make_token( ++ (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | ++ (((uint64_t)((v_whitespace_length + 1u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ if (v_c8 == self->private_impl.f_trailer_stop) { ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ goto label__outer__continue; ++ } ++ v_whitespace_length += 1u; ++ } ++ } ++ label__outer__break:; ++ ++ ok: ++ self->private_impl.p_decode_trailer = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_trailer = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ 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) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZMA) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_lzma__error__bad_lzma2_header[] = "#lzma: bad LZMA2 header"; ++const char wuffs_lzma__error__bad_bitstream_trailer[] = "#lzma: bad bitstream trailer"; ++const char wuffs_lzma__error__bad_code[] = "#lzma: bad code"; ++const char wuffs_lzma__error__bad_decoded_length[] = "#lzma: bad decoded length"; ++const char wuffs_lzma__error__bad_distance[] = "#lzma: bad distance"; ++const char wuffs_lzma__error__bad_header[] = "#lzma: bad header"; ++const char wuffs_lzma__error__truncated_input[] = "#lzma: truncated input"; ++const char wuffs_lzma__error__unsupported_decoded_length[] = "#lzma: unsupported decoded length"; ++const char wuffs_lzma__error__unsupported_properties[] = "#lzma: unsupported properties"; ++const char wuffs_lzma__error__internal_error_inconsistent_i_o[] = "#lzma: internal error: inconsistent I/O"; ++const char wuffs_lzma__error__internal_error_inconsistent_dictionary_state[] = "#lzma: internal error: inconsistent dictionary state"; ++ ++// ---------------- Private Consts ++ ++static const uint8_t ++WUFFS_LZMA__STATE_TRANSITION_LITERAL[12] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 0u, 0u, 1u, 2u, 3u, 4u, ++ 5u, 6u, 4u, 5u, ++}; ++ ++static const uint8_t ++WUFFS_LZMA__STATE_TRANSITION_MATCH[12] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 7u, 7u, 7u, 7u, 7u, 7u, 7u, 10u, ++ 10u, 10u, 10u, 10u, ++}; ++ ++static const uint8_t ++WUFFS_LZMA__STATE_TRANSITION_LONGREP[12] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 8u, 8u, 8u, 8u, 8u, 8u, 8u, 11u, ++ 11u, 11u, 11u, 11u, ++}; ++ ++static const uint8_t ++WUFFS_LZMA__STATE_TRANSITION_SHORTREP[12] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 9u, 9u, 9u, 9u, 9u, 9u, 9u, 11u, ++ 11u, 11u, 11u, 11u, ++}; ++ ++static const uint8_t ++WUFFS_LZMA__CLAMP_NO_MORE_THAN_3[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 1u, 2u, 3u, 3u, 3u, 3u, 3u, ++}; ++ ++#define WUFFS_LZMA__QUIRKS_BASE 1348001792u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__decode_bitstream_fast( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__decode_bitstream_slow( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__add_history( ++ wuffs_lzma__decoder* self, ++ wuffs_base__slice_u8 a_hist, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__do_transform_io( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__decode_bitstream( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__update_stashed_bytes( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__decode_optional_end_of_stream( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_lzma__decoder__initialize_dict( ++ wuffs_lzma__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_lzma__decoder__initialize_probs( ++ wuffs_lzma__decoder* self); ++ ++// ---------------- VTables ++ ++const wuffs_base__io_transformer__func_ptrs ++wuffs_lzma__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++ (wuffs_base__optional_u63(*)(const void*))(&wuffs_lzma__decoder__dst_history_retain_length), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_lzma__decoder__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_lzma__decoder__set_quirk), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_lzma__decoder__transform_io), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_lzma__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_lzma__decoder__initialize( ++ wuffs_lzma__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = ++ wuffs_base__io_transformer__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = ++ (const void*)(&wuffs_lzma__decoder__func_ptrs_for__wuffs_base__io_transformer); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_lzma__decoder* ++wuffs_lzma__decoder__alloc(void) { ++ wuffs_lzma__decoder* x = ++ (wuffs_lzma__decoder*)(calloc(1, sizeof(wuffs_lzma__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_lzma__decoder__initialize( ++ x, sizeof(wuffs_lzma__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_lzma__decoder(void) { ++ return sizeof(wuffs_lzma__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func lzma.decoder.decode_bitstream_fast ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__decode_bitstream_fast( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_bits = 0; ++ uint32_t v_range = 0; ++ uint32_t v_state = 0; ++ uint32_t v_rep0 = 0; ++ uint32_t v_rep1 = 0; ++ uint32_t v_rep2 = 0; ++ uint32_t v_rep3 = 0; ++ uint32_t v_reptmp = 0; ++ uint32_t v_rep = 0; ++ uint64_t v_pos = 0; ++ uint64_t v_pos_end = 0; ++ uint32_t v_lc = 0; ++ uint64_t v_lp_mask = 0; ++ uint64_t v_pb_mask = 0; ++ uint32_t v_prob = 0; ++ uint32_t v_threshold = 0; ++ uint32_t v_tree_node = 0; ++ uint8_t v_prev_byte = 0; ++ uint32_t v_match_byte = 0; ++ uint32_t v_match_cusp = 0; ++ uint32_t v_len_state = 0; ++ uint32_t v_slot = 0; ++ uint32_t v_len = 0; ++ uint32_t v_lanl_offset = 0; ++ uint32_t v_lanl_old_offset = 0; ++ uint32_t v_lanl_index = 0; ++ uint32_t v_num_extra_bits = 0; ++ uint32_t v_dist_extra_bits = 0; ++ uint32_t v_high_bit_was_on = 0; ++ uint32_t v_i = 0; ++ uint32_t v_index_ao00 = 0; ++ uint32_t v_index_ao41 = 0; ++ uint32_t v_index_lit = 0; ++ uint32_t v_index_len = 0; ++ uint32_t v_index_small_dist_base = 0; ++ uint32_t v_index_small_dist_extra = 0; ++ uint32_t v_index_small_dist = 0; ++ uint32_t v_index_large_dist = 0; ++ uint32_t v_dist = 0; ++ uint32_t v_adj_dist = 0; ++ uint64_t v_wb_index = 0; ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } ++ ++ v_prev_byte = self->private_impl.f_stashed_bytes[0u]; ++ v_match_byte = ((uint32_t)(self->private_impl.f_stashed_bytes[1u])); ++ v_bits = self->private_impl.f_stashed_bits; ++ v_range = self->private_impl.f_stashed_range; ++ v_state = self->private_impl.f_stashed_state; ++ v_rep0 = self->private_impl.f_stashed_rep0; ++ v_rep1 = self->private_impl.f_stashed_rep1; ++ v_rep2 = self->private_impl.f_stashed_rep2; ++ v_rep3 = self->private_impl.f_stashed_rep3; ++ v_pos = self->private_impl.f_stashed_pos; ++ v_pos_end = self->private_impl.f_stashed_pos_end; ++ v_lc = self->private_impl.f_lc; ++ v_lp_mask = ((((uint64_t)(1u)) << self->private_impl.f_lp) - 1u); ++ v_pb_mask = ((((uint64_t)(1u)) << self->private_impl.f_pb) - 1u); ++ while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 282u) && (((uint64_t)(io2_a_src - iop_a_src)) >= 48u)) { ++ if (v_pos >= v_pos_end) { ++ self->private_impl.f_end_of_chunk = true; ++ break; ++ } ++ v_index_ao00 = ((v_state << 4u) | ((uint32_t)((v_pos & v_pb_mask)))); ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao00[v_index_ao00])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao00[v_index_ao00] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_lit = (15u & ((((uint32_t)((v_pos & v_lp_mask))) << v_lc) | (((uint32_t)(v_prev_byte)) >> (8u - v_lc)))); ++ v_lanl_offset = 0u; ++ if (v_state >= 7u) { ++ v_lanl_offset = 256u; ++ } ++ v_tree_node = 1u; ++ while (v_tree_node < 256u) { ++ v_match_byte <<= 1u; ++ v_lanl_old_offset = v_lanl_offset; ++ v_lanl_offset &= v_match_byte; ++ v_lanl_index = (v_lanl_offset + v_lanl_old_offset + v_tree_node); ++ v_prob = ((uint32_t)(self->private_data.f_probs_lit[v_index_lit][v_lanl_index])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_lanl_offset = ((v_lanl_offset ^ v_lanl_old_offset) & 256u); ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_lit[v_index_lit][v_lanl_index] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_lit[v_index_lit][v_lanl_index] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_prev_byte = ((uint8_t)(v_tree_node)); ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_prev_byte), iop_a_dst += 1); ++ v_pos += 1u; ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_LITERAL[v_state])); ++ continue; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao00[v_index_ao00] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } else { ++ } ++ do { ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao20[v_state])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao20[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } else { ++ } ++ do { ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_low[0u][0u])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_low[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_len = ((uint32_t)((v_pos & v_pb_mask))); ++ v_tree_node = 1u; ++ while (v_tree_node < 8u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_low[v_index_len][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_low[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_low[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len_state = ((uint32_t)(WUFFS_LZMA__CLAMP_NO_MORE_THAN_3[(v_tree_node & 7u)])); ++ v_len = ((v_tree_node & 7u) + 2u); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_low[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_mid[0u][0u])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_mid[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_len = ((uint32_t)((v_pos & v_pb_mask))); ++ v_tree_node = 1u; ++ while (v_tree_node < 8u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_mid[v_index_len][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_mid[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_mid[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 7u) + 10u); ++ v_len_state = 3u; ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_mid[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_tree_node = 1u; ++ while (v_tree_node < 256u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_high[0u][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_high[0u][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_high[0u][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 255u) + 18u); ++ v_len_state = 3u; ++ } while (0); ++ v_slot = 1u; ++ while (v_slot < 64u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_slot[v_len_state][v_slot])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_slot[v_len_state][v_slot] = ((uint16_t)(v_prob)); ++ v_slot = (v_slot << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_slot[v_len_state][v_slot] = ((uint16_t)(v_prob)); ++ v_slot = ((v_slot << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_slot &= 63u; ++ v_rep = v_slot; ++ if (v_slot < 4u) { ++ } else if (v_slot < 14u) { ++ v_num_extra_bits = ((v_slot >> 1u) - 1u); ++ v_rep = ((2u | (v_slot & 1u)) << v_num_extra_bits); ++ v_index_small_dist_base = ((uint32_t)(v_rep - v_slot)); ++ v_index_small_dist_extra = 1u; ++ v_dist_extra_bits = 0u; ++ v_i = 0u; ++ while (v_i < v_num_extra_bits) { ++ v_index_small_dist = (((uint32_t)(v_index_small_dist_base + v_index_small_dist_extra)) & 127u); ++ v_prob = ((uint32_t)(self->private_data.f_probs_small_dist[v_index_small_dist])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_small_dist[v_index_small_dist] = ((uint16_t)(v_prob)); ++ v_index_small_dist_extra = ((uint32_t)(v_index_small_dist_extra << 1u)); ++ v_i += 1u; ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_small_dist[v_index_small_dist] = ((uint16_t)(v_prob)); ++ v_index_small_dist_extra = (((uint32_t)(v_index_small_dist_extra << 1u)) | 1u); ++ v_dist_extra_bits |= (((uint32_t)(1u)) << v_i); ++ v_i += 1u; ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_rep += v_dist_extra_bits; ++ } else { ++ v_num_extra_bits = ((v_slot >> 1u) - 1u); ++ v_rep = ((2u | (v_slot & 1u)) << v_num_extra_bits); ++ v_dist_extra_bits = 0u; ++ while (true) { ++ v_range >>= 1u; ++ v_bits -= v_range; ++ v_high_bit_was_on = ((uint32_t)(0u - (v_bits >> 31u))); ++ v_bits += (v_range & v_high_bit_was_on); ++ v_dist_extra_bits = (((uint32_t)(v_dist_extra_bits << 1u)) | (((uint32_t)(v_high_bit_was_on + 1u)) & 1u)); ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_num_extra_bits -= 1u; ++ if (v_num_extra_bits <= 4u) { ++ break; ++ } ++ } ++ v_dist_extra_bits <<= 4u; ++ v_index_large_dist = 1u; ++ while (true) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_large_dist[v_index_large_dist])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_large_dist[v_index_large_dist] = ((uint16_t)(v_prob)); ++ v_index_large_dist = (15u & ((uint32_t)(v_index_large_dist << 1u))); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_large_dist[v_index_large_dist] = ((uint16_t)(v_prob)); ++ v_index_large_dist = (15u & (((uint32_t)(v_index_large_dist << 1u)) | 1u)); ++ v_dist_extra_bits |= (((uint32_t)(1u)) << (4u - v_num_extra_bits)); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_num_extra_bits -= 1u; ++ if (v_num_extra_bits <= 0u) { ++ break; ++ } ++ } ++ v_rep += v_dist_extra_bits; ++ } ++ if (v_rep >= 4294967295u) { ++ self->private_impl.f_end_of_chunk = true; ++ goto label__outer__break; ++ } ++ v_rep3 = v_rep2; ++ v_rep2 = v_rep1; ++ v_rep1 = v_rep0; ++ v_rep0 = v_rep; ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_MATCH[v_state])); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao20[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } else { ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao40[v_state])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao40[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } else { ++ } ++ v_index_ao41 = ((v_state << 4u) | ((uint32_t)((v_pos & v_pb_mask)))); ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao41[v_index_ao41])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao41[v_index_ao41] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_len = 1u; ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_SHORTREP[v_state])); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao41[v_index_ao41] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao40[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } else { ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao60[v_state])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao60[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_reptmp = v_rep1; ++ v_rep1 = v_rep0; ++ v_rep0 = v_reptmp; ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao60[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } else { ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao63[v_state])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao63[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_reptmp = v_rep2; ++ v_rep2 = v_rep1; ++ v_rep1 = v_rep0; ++ v_rep0 = v_reptmp; ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao63[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_reptmp = v_rep3; ++ v_rep3 = v_rep2; ++ v_rep2 = v_rep1; ++ v_rep1 = v_rep0; ++ v_rep0 = v_reptmp; ++ } ++ } ++ } ++ do { ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_low[0u][0u])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_low[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_len = ((uint32_t)((v_pos & v_pb_mask))); ++ v_tree_node = 1u; ++ while (v_tree_node < 8u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_low[v_index_len][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_low[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_low[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 7u) + 2u); ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_LONGREP[v_state])); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_low[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_mid[0u][0u])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_mid[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_len = ((uint32_t)((v_pos & v_pb_mask))); ++ v_tree_node = 1u; ++ while (v_tree_node < 8u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_mid[v_index_len][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_mid[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_mid[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 7u) + 10u); ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_LONGREP[v_state])); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_mid[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_tree_node = 1u; ++ while (v_tree_node < 256u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_high[0u][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_high[0u][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_high[0u][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 255u) + 18u); ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_LONGREP[v_state])); ++ } while (0); ++ } while (0); ++ v_dist = (v_rep0 + 1u); ++ if ((((uint64_t)(v_dist)) > v_pos) || (((uint64_t)(v_dist)) > ((uint64_t)(self->private_impl.f_dict_size)))) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_distance); ++ goto exit; ++ } ++ v_pos += ((uint64_t)(v_len)); ++ if (((uint64_t)(v_dist)) > ((uint64_t)(iop_a_dst - io0_a_dst))) { ++ v_adj_dist = ((uint32_t)((((uint64_t)(v_dist)) - ((uint64_t)(iop_a_dst - io0_a_dst))))); ++ if (v_adj_dist > self->private_impl.f_dict_seen) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_distance); ++ goto exit; ++ } ++ v_wb_index = ((uint64_t)(((uint64_t)(self->private_impl.f_dict_workbuf_index)) - ((uint64_t)(v_adj_dist)))); ++ while (v_wb_index >= 9223372036854775808u) { ++ v_wb_index += ((uint64_t)(self->private_impl.f_dict_size)); ++ } ++ if (v_wb_index >= ((uint64_t)(a_workbuf.len))) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ if (v_len < v_adj_dist) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,(v_len + 1u), wuffs_base__slice_u8__subslice_i(a_workbuf, v_wb_index)); ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ v_match_byte = ((uint32_t)(iop_a_dst[-1])); ++ iop_a_dst--; ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ v_prev_byte = iop_a_dst[-1]; ++ continue; ++ } else if (v_len == v_adj_dist) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,v_len, wuffs_base__slice_u8__subslice_i(a_workbuf, v_wb_index)); ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history( ++ &iop_a_dst, io0_a_dst, io2_a_dst, 1u, v_dist); ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ v_match_byte = ((uint32_t)(iop_a_dst[-1])); ++ iop_a_dst--; ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ v_prev_byte = iop_a_dst[-1]; ++ continue; ++ } ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,v_adj_dist, wuffs_base__slice_u8__subslice_i(a_workbuf, v_wb_index)); ++ v_len -= v_adj_dist; ++ if ((((uint64_t)(v_len)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_len + 8u))) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)(v_dist)) > ((uint64_t)(iop_a_dst - io0_a_dst)))) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ } ++ if (v_dist >= 8u) { ++ v_match_cusp = wuffs_private_impl__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast_return_cusp( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_len, v_dist); ++ v_match_byte = (v_match_cusp >> 8u); ++ v_prev_byte = ((uint8_t)(v_match_cusp)); ++ } else { ++ v_match_cusp = wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast_return_cusp( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_len, v_dist); ++ v_match_byte = (v_match_cusp >> 8u); ++ v_prev_byte = ((uint8_t)(v_match_cusp)); ++ } ++ } ++ label__outer__break:; ++ self->private_impl.f_stashed_bytes[0u] = v_prev_byte; ++ self->private_impl.f_stashed_bytes[1u] = ((uint8_t)(v_match_byte)); ++ self->private_impl.f_stashed_bits = v_bits; ++ self->private_impl.f_stashed_range = v_range; ++ self->private_impl.f_stashed_state = v_state; ++ self->private_impl.f_stashed_rep0 = v_rep0; ++ self->private_impl.f_stashed_rep1 = v_rep1; ++ self->private_impl.f_stashed_rep2 = v_rep2; ++ self->private_impl.f_stashed_rep3 = v_rep3; ++ self->private_impl.f_stashed_pos = v_pos; ++ self->private_impl.f_stashed_pos_end = v_pos_end; ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func lzma.decoder.decode_bitstream_slow ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__decode_bitstream_slow( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_bits = 0; ++ uint32_t v_range = 0; ++ uint32_t v_state = 0; ++ uint32_t v_rep0 = 0; ++ uint32_t v_rep1 = 0; ++ uint32_t v_rep2 = 0; ++ uint32_t v_rep3 = 0; ++ uint32_t v_reptmp = 0; ++ uint32_t v_rep = 0; ++ uint64_t v_pos = 0; ++ uint64_t v_pos_end = 0; ++ uint32_t v_lc = 0; ++ uint64_t v_lp_mask = 0; ++ uint64_t v_pb_mask = 0; ++ uint32_t v_prob = 0; ++ uint32_t v_threshold = 0; ++ uint32_t v_tree_node = 0; ++ uint8_t v_prev_byte = 0; ++ uint32_t v_match_byte = 0; ++ uint32_t v_match_cusp = 0; ++ uint32_t v_len_state = 0; ++ uint32_t v_slot = 0; ++ uint32_t v_len = 0; ++ uint32_t v_lanl_offset = 0; ++ uint32_t v_lanl_old_offset = 0; ++ uint32_t v_lanl_index = 0; ++ uint32_t v_num_extra_bits = 0; ++ uint32_t v_dist_extra_bits = 0; ++ uint32_t v_high_bit_was_on = 0; ++ uint32_t v_i = 0; ++ uint32_t v_index_ao00 = 0; ++ uint32_t v_index_ao41 = 0; ++ uint32_t v_index_lit = 0; ++ uint32_t v_index_len = 0; ++ uint32_t v_index_small_dist_base = 0; ++ uint32_t v_index_small_dist_extra = 0; ++ uint32_t v_index_small_dist = 0; ++ uint32_t v_index_large_dist = 0; ++ uint32_t v_dist = 0; ++ uint32_t v_adj_dist = 0; ++ uint64_t v_wb_index = 0; ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_bitstream_slow; ++ if (coro_susp_point) { ++ v_bits = self->private_data.s_decode_bitstream_slow.v_bits; ++ v_range = self->private_data.s_decode_bitstream_slow.v_range; ++ v_state = self->private_data.s_decode_bitstream_slow.v_state; ++ v_rep0 = self->private_data.s_decode_bitstream_slow.v_rep0; ++ v_rep1 = self->private_data.s_decode_bitstream_slow.v_rep1; ++ v_rep2 = self->private_data.s_decode_bitstream_slow.v_rep2; ++ v_rep3 = self->private_data.s_decode_bitstream_slow.v_rep3; ++ v_rep = self->private_data.s_decode_bitstream_slow.v_rep; ++ v_pos = self->private_data.s_decode_bitstream_slow.v_pos; ++ v_pos_end = self->private_data.s_decode_bitstream_slow.v_pos_end; ++ v_lc = self->private_data.s_decode_bitstream_slow.v_lc; ++ v_lp_mask = self->private_data.s_decode_bitstream_slow.v_lp_mask; ++ v_pb_mask = self->private_data.s_decode_bitstream_slow.v_pb_mask; ++ v_tree_node = self->private_data.s_decode_bitstream_slow.v_tree_node; ++ v_prev_byte = self->private_data.s_decode_bitstream_slow.v_prev_byte; ++ v_match_byte = self->private_data.s_decode_bitstream_slow.v_match_byte; ++ v_len_state = self->private_data.s_decode_bitstream_slow.v_len_state; ++ v_slot = self->private_data.s_decode_bitstream_slow.v_slot; ++ v_len = self->private_data.s_decode_bitstream_slow.v_len; ++ v_lanl_offset = self->private_data.s_decode_bitstream_slow.v_lanl_offset; ++ v_num_extra_bits = self->private_data.s_decode_bitstream_slow.v_num_extra_bits; ++ v_dist_extra_bits = self->private_data.s_decode_bitstream_slow.v_dist_extra_bits; ++ v_i = self->private_data.s_decode_bitstream_slow.v_i; ++ v_index_lit = self->private_data.s_decode_bitstream_slow.v_index_lit; ++ v_index_len = self->private_data.s_decode_bitstream_slow.v_index_len; ++ v_index_small_dist_base = self->private_data.s_decode_bitstream_slow.v_index_small_dist_base; ++ v_index_small_dist_extra = self->private_data.s_decode_bitstream_slow.v_index_small_dist_extra; ++ v_index_large_dist = self->private_data.s_decode_bitstream_slow.v_index_large_dist; ++ v_dist = self->private_data.s_decode_bitstream_slow.v_dist; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ v_prev_byte = self->private_impl.f_stashed_bytes[0u]; ++ v_match_byte = ((uint32_t)(self->private_impl.f_stashed_bytes[1u])); ++ v_bits = self->private_impl.f_stashed_bits; ++ v_range = self->private_impl.f_stashed_range; ++ v_state = self->private_impl.f_stashed_state; ++ v_rep0 = self->private_impl.f_stashed_rep0; ++ v_rep1 = self->private_impl.f_stashed_rep1; ++ v_rep2 = self->private_impl.f_stashed_rep2; ++ v_rep3 = self->private_impl.f_stashed_rep3; ++ v_pos = self->private_impl.f_stashed_pos; ++ v_pos_end = self->private_impl.f_stashed_pos_end; ++ v_lc = self->private_impl.f_lc; ++ v_lp_mask = ((((uint64_t)(1u)) << self->private_impl.f_lp) - 1u); ++ v_pb_mask = ((((uint64_t)(1u)) << self->private_impl.f_pb) - 1u); ++ while ( ! (self->private_impl.p_decode_bitstream_slow != 0)) { ++ if (v_pos >= v_pos_end) { ++ self->private_impl.f_end_of_chunk = true; ++ break; ++ } ++ v_index_ao00 = ((v_state << 4u) | ((uint32_t)((v_pos & v_pb_mask)))); ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao00[v_index_ao00])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao00[v_index_ao00] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_lit = (15u & ((((uint32_t)((v_pos & v_lp_mask))) << v_lc) | (((uint32_t)(v_prev_byte)) >> (8u - v_lc)))); ++ if (v_state >= 7u) { ++ v_lanl_offset = 256u; ++ v_tree_node = 1u; ++ while (v_tree_node < 256u) { ++ v_match_byte <<= 1u; ++ v_lanl_old_offset = v_lanl_offset; ++ v_lanl_offset &= v_match_byte; ++ v_lanl_index = (v_lanl_offset + v_lanl_old_offset + v_tree_node); ++ v_prob = ((uint32_t)(self->private_data.f_probs_lit[v_index_lit][v_lanl_index])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_lanl_offset = ((v_lanl_offset ^ v_lanl_old_offset) & 256u); ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_lit[v_index_lit][v_lanl_index] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_lit[v_index_lit][v_lanl_index] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ } else { ++ v_tree_node = 1u; ++ while (v_tree_node < 256u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_lit[v_index_lit][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_lit[v_index_lit][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_lit[v_index_lit][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ } ++ v_prev_byte = ((uint8_t)(v_tree_node)); ++ self->private_data.s_decode_bitstream_slow.scratch = v_prev_byte; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (iop_a_dst == io2_a_dst) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ goto suspend; ++ } ++ *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_bitstream_slow.scratch)); ++ v_pos += 1u; ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_LITERAL[v_state])); ++ continue; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao00[v_index_ao00] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ do { ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao20[v_state])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao20[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ do { ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_low[0u][0u])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_low[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_len = ((uint32_t)((v_pos & v_pb_mask))); ++ v_tree_node = 1u; ++ while (v_tree_node < 8u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_low[v_index_len][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_low[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_low[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len_state = ((uint32_t)(WUFFS_LZMA__CLAMP_NO_MORE_THAN_3[(v_tree_node & 7u)])); ++ v_len = ((v_tree_node & 7u) + 2u); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_low[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_7 = *iop_a_src++; ++ v_c8 = t_7; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_mid[0u][0u])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_mid[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_8 = *iop_a_src++; ++ v_c8 = t_8; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_len = ((uint32_t)((v_pos & v_pb_mask))); ++ v_tree_node = 1u; ++ while (v_tree_node < 8u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_mid[v_index_len][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_mid[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_mid[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_9 = *iop_a_src++; ++ v_c8 = t_9; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 7u) + 10u); ++ v_len_state = 3u; ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_mid[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_10 = *iop_a_src++; ++ v_c8 = t_10; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_tree_node = 1u; ++ while (v_tree_node < 256u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_match_len_high[0u][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_match_len_high[0u][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_match_len_high[0u][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_11 = *iop_a_src++; ++ v_c8 = t_11; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 255u) + 18u); ++ v_len_state = 3u; ++ } while (0); ++ v_slot = 1u; ++ while (v_slot < 64u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_slot[v_len_state][v_slot])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_slot[v_len_state][v_slot] = ((uint16_t)(v_prob)); ++ v_slot = (v_slot << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_slot[v_len_state][v_slot] = ((uint16_t)(v_prob)); ++ v_slot = ((v_slot << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_12 = *iop_a_src++; ++ v_c8 = t_12; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_slot &= 63u; ++ v_rep = v_slot; ++ if (v_slot < 4u) { ++ } else if (v_slot < 14u) { ++ v_num_extra_bits = ((v_slot >> 1u) - 1u); ++ v_rep = ((2u | (v_slot & 1u)) << v_num_extra_bits); ++ v_index_small_dist_base = ((uint32_t)(v_rep - v_slot)); ++ v_index_small_dist_extra = 1u; ++ v_dist_extra_bits = 0u; ++ v_i = 0u; ++ while (v_i < v_num_extra_bits) { ++ v_index_small_dist = (((uint32_t)(v_index_small_dist_base + v_index_small_dist_extra)) & 127u); ++ v_prob = ((uint32_t)(self->private_data.f_probs_small_dist[v_index_small_dist])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_small_dist[v_index_small_dist] = ((uint16_t)(v_prob)); ++ v_index_small_dist_extra = ((uint32_t)(v_index_small_dist_extra << 1u)); ++ v_i += 1u; ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_small_dist[v_index_small_dist] = ((uint16_t)(v_prob)); ++ v_index_small_dist_extra = (((uint32_t)(v_index_small_dist_extra << 1u)) | 1u); ++ v_dist_extra_bits |= (((uint32_t)(1u)) << v_i); ++ v_i += 1u; ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_13 = *iop_a_src++; ++ v_c8 = t_13; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_rep += v_dist_extra_bits; ++ } else { ++ v_num_extra_bits = ((v_slot >> 1u) - 1u); ++ v_rep = ((2u | (v_slot & 1u)) << v_num_extra_bits); ++ v_dist_extra_bits = 0u; ++ while (true) { ++ v_range >>= 1u; ++ v_bits -= v_range; ++ v_high_bit_was_on = ((uint32_t)(0u - (v_bits >> 31u))); ++ v_bits += (v_range & v_high_bit_was_on); ++ v_dist_extra_bits = (((uint32_t)(v_dist_extra_bits << 1u)) | (((uint32_t)(v_high_bit_was_on + 1u)) & 1u)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_14 = *iop_a_src++; ++ v_c8 = t_14; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_num_extra_bits -= 1u; ++ if (v_num_extra_bits <= 4u) { ++ break; ++ } ++ } ++ v_dist_extra_bits <<= 4u; ++ v_index_large_dist = 1u; ++ while (true) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_large_dist[v_index_large_dist])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_large_dist[v_index_large_dist] = ((uint16_t)(v_prob)); ++ v_index_large_dist = (15u & ((uint32_t)(v_index_large_dist << 1u))); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_large_dist[v_index_large_dist] = ((uint16_t)(v_prob)); ++ v_index_large_dist = (15u & (((uint32_t)(v_index_large_dist << 1u)) | 1u)); ++ v_dist_extra_bits |= (((uint32_t)(1u)) << (4u - v_num_extra_bits)); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_15 = *iop_a_src++; ++ v_c8 = t_15; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_num_extra_bits -= 1u; ++ if (v_num_extra_bits <= 0u) { ++ break; ++ } ++ } ++ v_rep += v_dist_extra_bits; ++ } ++ if (v_rep >= 4294967295u) { ++ self->private_impl.f_end_of_chunk = true; ++ goto label__outer__break; ++ } ++ v_rep3 = v_rep2; ++ v_rep2 = v_rep1; ++ v_rep1 = v_rep0; ++ v_rep0 = v_rep; ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_MATCH[v_state])); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao20[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_16 = *iop_a_src++; ++ v_c8 = t_16; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao40[v_state])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao40[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_17 = *iop_a_src++; ++ v_c8 = t_17; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_ao41 = ((v_state << 4u) | ((uint32_t)((v_pos & v_pb_mask)))); ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao41[v_index_ao41])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao41[v_index_ao41] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_18 = *iop_a_src++; ++ v_c8 = t_18; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_len = 1u; ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_SHORTREP[v_state])); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao41[v_index_ao41] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_19 = *iop_a_src++; ++ v_c8 = t_19; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao40[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_20 = *iop_a_src++; ++ v_c8 = t_20; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao60[v_state])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao60[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_21 = *iop_a_src++; ++ v_c8 = t_21; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_reptmp = v_rep1; ++ v_rep1 = v_rep0; ++ v_rep0 = v_reptmp; ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao60[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_22 = *iop_a_src++; ++ v_c8 = t_22; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_ao63[v_state])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_ao63[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(25); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_23 = *iop_a_src++; ++ v_c8 = t_23; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_reptmp = v_rep2; ++ v_rep2 = v_rep1; ++ v_rep1 = v_rep0; ++ v_rep0 = v_reptmp; ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_ao63[v_state] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(26); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_24 = *iop_a_src++; ++ v_c8 = t_24; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_reptmp = v_rep3; ++ v_rep3 = v_rep2; ++ v_rep2 = v_rep1; ++ v_rep1 = v_rep0; ++ v_rep0 = v_reptmp; ++ } ++ } ++ } ++ do { ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_low[0u][0u])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_low[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(27); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_25 = *iop_a_src++; ++ v_c8 = t_25; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_len = ((uint32_t)((v_pos & v_pb_mask))); ++ v_tree_node = 1u; ++ while (v_tree_node < 8u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_low[v_index_len][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_low[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_low[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(28); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_26 = *iop_a_src++; ++ v_c8 = t_26; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 7u) + 2u); ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_LONGREP[v_state])); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_low[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(29); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_27 = *iop_a_src++; ++ v_c8 = t_27; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_mid[0u][0u])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_mid[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(30); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_28 = *iop_a_src++; ++ v_c8 = t_28; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_index_len = ((uint32_t)((v_pos & v_pb_mask))); ++ v_tree_node = 1u; ++ while (v_tree_node < 8u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_mid[v_index_len][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_mid[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_mid[v_index_len][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(31); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_29 = *iop_a_src++; ++ v_c8 = t_29; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 7u) + 10u); ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_LONGREP[v_state])); ++ break; ++ } ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_mid[0u][0u] = ((uint16_t)(v_prob)); ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(32); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_30 = *iop_a_src++; ++ v_c8 = t_30; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ v_tree_node = 1u; ++ while (v_tree_node < 256u) { ++ v_prob = ((uint32_t)(self->private_data.f_probs_longrep_len_high[0u][v_tree_node])); ++ v_threshold = ((uint32_t)((v_range >> 11u) * v_prob)); ++ if (v_bits < v_threshold) { ++ v_range = v_threshold; ++ v_prob += (((uint32_t)(2048u - v_prob)) >> 5u); ++ self->private_data.f_probs_longrep_len_high[0u][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = (v_tree_node << 1u); ++ } else { ++ v_bits -= v_threshold; ++ v_range -= v_threshold; ++ v_prob -= (v_prob >> 5u); ++ self->private_data.f_probs_longrep_len_high[0u][v_tree_node] = ((uint16_t)(v_prob)); ++ v_tree_node = ((v_tree_node << 1u) | 1u); ++ } ++ if ((v_range >> 24u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(33); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_31 = *iop_a_src++; ++ v_c8 = t_31; ++ } ++ v_bits = (((uint32_t)(v_bits << 8u)) | ((uint32_t)(v_c8))); ++ v_range <<= 8u; ++ } ++ } ++ v_len = ((v_tree_node & 255u) + 18u); ++ v_state = ((uint32_t)(WUFFS_LZMA__STATE_TRANSITION_LONGREP[v_state])); ++ } while (0); ++ } while (0); ++ v_dist = (v_rep0 + 1u); ++ if ((((uint64_t)(v_dist)) > v_pos) || (((uint64_t)(v_dist)) > ((uint64_t)(self->private_impl.f_dict_size)))) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_distance); ++ goto exit; ++ } ++ v_pos += ((uint64_t)(v_len)); ++ while (274u > ((uint64_t)(io2_a_dst - iop_a_dst))) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(34); ++ } ++ if (((uint64_t)(v_dist)) > ((uint64_t)(iop_a_dst - io0_a_dst))) { ++ v_adj_dist = ((uint32_t)((((uint64_t)(v_dist)) - ((uint64_t)(iop_a_dst - io0_a_dst))))); ++ if (v_adj_dist > self->private_impl.f_dict_seen) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_distance); ++ goto exit; ++ } ++ v_wb_index = ((uint64_t)(((uint64_t)(self->private_impl.f_dict_workbuf_index)) - ((uint64_t)(v_adj_dist)))); ++ while (v_wb_index >= 9223372036854775808u) { ++ v_wb_index += ((uint64_t)(self->private_impl.f_dict_size)); ++ } ++ if (v_wb_index >= ((uint64_t)(a_workbuf.len))) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ if (v_len < v_adj_dist) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,(v_len + 1u), wuffs_base__slice_u8__subslice_i(a_workbuf, v_wb_index)); ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ v_match_byte = ((uint32_t)(iop_a_dst[-1])); ++ iop_a_dst--; ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ v_prev_byte = iop_a_dst[-1]; ++ continue; ++ } else if (v_len == v_adj_dist) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,v_len, wuffs_base__slice_u8__subslice_i(a_workbuf, v_wb_index)); ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history( ++ &iop_a_dst, io0_a_dst, io2_a_dst, 1u, v_dist); ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ v_match_byte = ((uint32_t)(iop_a_dst[-1])); ++ iop_a_dst--; ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ v_prev_byte = iop_a_dst[-1]; ++ continue; ++ } ++ wuffs_private_impl__io_writer__limited_copy_u32_from_slice( ++ &iop_a_dst, io2_a_dst,v_adj_dist, wuffs_base__slice_u8__subslice_i(a_workbuf, v_wb_index)); ++ v_len -= v_adj_dist; ++ if ((((uint64_t)(v_len)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)(v_dist)) > ((uint64_t)(iop_a_dst - io0_a_dst)))) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ } ++ v_match_cusp = wuffs_private_impl__io_writer__limited_copy_u32_from_history_fast_return_cusp( ++ &iop_a_dst, io0_a_dst, io2_a_dst, v_len, v_dist); ++ v_match_byte = (v_match_cusp >> 8u); ++ v_prev_byte = ((uint8_t)(v_match_cusp)); ++ } ++ label__outer__break:; ++ self->private_impl.f_stashed_bytes[0u] = v_prev_byte; ++ self->private_impl.f_stashed_bytes[1u] = ((uint8_t)(v_match_byte)); ++ self->private_impl.f_stashed_bits = v_bits; ++ self->private_impl.f_stashed_range = v_range; ++ self->private_impl.f_stashed_state = v_state; ++ self->private_impl.f_stashed_rep0 = v_rep0; ++ self->private_impl.f_stashed_rep1 = v_rep1; ++ self->private_impl.f_stashed_rep2 = v_rep2; ++ self->private_impl.f_stashed_rep3 = v_rep3; ++ self->private_impl.f_stashed_pos = v_pos; ++ self->private_impl.f_stashed_pos_end = v_pos_end; ++ ++ ok: ++ self->private_impl.p_decode_bitstream_slow = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_bitstream_slow = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_bitstream_slow.v_bits = v_bits; ++ self->private_data.s_decode_bitstream_slow.v_range = v_range; ++ self->private_data.s_decode_bitstream_slow.v_state = v_state; ++ self->private_data.s_decode_bitstream_slow.v_rep0 = v_rep0; ++ self->private_data.s_decode_bitstream_slow.v_rep1 = v_rep1; ++ self->private_data.s_decode_bitstream_slow.v_rep2 = v_rep2; ++ self->private_data.s_decode_bitstream_slow.v_rep3 = v_rep3; ++ self->private_data.s_decode_bitstream_slow.v_rep = v_rep; ++ self->private_data.s_decode_bitstream_slow.v_pos = v_pos; ++ self->private_data.s_decode_bitstream_slow.v_pos_end = v_pos_end; ++ self->private_data.s_decode_bitstream_slow.v_lc = v_lc; ++ self->private_data.s_decode_bitstream_slow.v_lp_mask = v_lp_mask; ++ self->private_data.s_decode_bitstream_slow.v_pb_mask = v_pb_mask; ++ self->private_data.s_decode_bitstream_slow.v_tree_node = v_tree_node; ++ self->private_data.s_decode_bitstream_slow.v_prev_byte = v_prev_byte; ++ self->private_data.s_decode_bitstream_slow.v_match_byte = v_match_byte; ++ self->private_data.s_decode_bitstream_slow.v_len_state = v_len_state; ++ self->private_data.s_decode_bitstream_slow.v_slot = v_slot; ++ self->private_data.s_decode_bitstream_slow.v_len = v_len; ++ self->private_data.s_decode_bitstream_slow.v_lanl_offset = v_lanl_offset; ++ self->private_data.s_decode_bitstream_slow.v_num_extra_bits = v_num_extra_bits; ++ self->private_data.s_decode_bitstream_slow.v_dist_extra_bits = v_dist_extra_bits; ++ self->private_data.s_decode_bitstream_slow.v_i = v_i; ++ self->private_data.s_decode_bitstream_slow.v_index_lit = v_index_lit; ++ self->private_data.s_decode_bitstream_slow.v_index_len = v_index_len; ++ self->private_data.s_decode_bitstream_slow.v_index_small_dist_base = v_index_small_dist_base; ++ self->private_data.s_decode_bitstream_slow.v_index_small_dist_extra = v_index_small_dist_extra; ++ self->private_data.s_decode_bitstream_slow.v_index_large_dist = v_index_large_dist; ++ self->private_data.s_decode_bitstream_slow.v_dist = v_dist; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func lzma.decoder.add_history ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__add_history( ++ wuffs_lzma__decoder* self, ++ wuffs_base__slice_u8 a_hist, ++ wuffs_base__slice_u8 a_workbuf) { ++ uint64_t v_dict_workbuf_index = 0; ++ uint64_t v_dict_size = 0; ++ uint64_t v_hist_length = 0; ++ wuffs_base__slice_u8 v_s = {0}; ++ uint64_t v_n_copied = 0; ++ uint64_t v_n = 0; ++ ++ v_dict_workbuf_index = ((uint64_t)(self->private_impl.f_dict_workbuf_index)); ++ v_dict_size = ((uint64_t)(self->private_impl.f_dict_size)); ++ if (((uint64_t)(a_hist.len)) == 0u) { ++ return wuffs_base__make_status(NULL); ++ } ++ if (((uint64_t)(a_workbuf.len)) < (v_dict_size + 273u)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ } ++ v_hist_length = ((uint64_t)(a_hist.len)); ++ if (v_hist_length > 4294967295u) { ++ self->private_impl.f_dict_seen = 4294967295u; ++ } else { ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dict_seen, ((uint32_t)(v_hist_length))); ++ } ++ v_s = a_hist; ++ if (((uint64_t)(v_s.len)) >= v_dict_size) { ++ v_s = wuffs_private_impl__slice_u8__suffix(v_s, v_dict_size); ++ wuffs_private_impl__slice_u8__copy_from_slice(a_workbuf, v_s); ++ self->private_impl.f_dict_workbuf_index = 0u; ++ } else if (v_dict_workbuf_index > v_dict_size) { ++ return wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ } else { ++ v_n_copied = wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__slice_u8__subslice_ij(a_workbuf, v_dict_workbuf_index, v_dict_size), v_s); ++ if (v_n_copied < ((uint64_t)(v_s.len))) { ++ v_n = wuffs_private_impl__slice_u8__copy_from_slice(a_workbuf, wuffs_base__slice_u8__subslice_i(v_s, v_n_copied)); ++ self->private_impl.f_dict_workbuf_index = ((uint32_t)(v_n)); ++ } else { ++ v_n = ((uint64_t)(v_dict_workbuf_index + v_n_copied)); ++ if (v_n < v_dict_size) { ++ self->private_impl.f_dict_workbuf_index = ((uint32_t)(v_n)); ++ } else { ++ self->private_impl.f_dict_workbuf_index = 0u; ++ } ++ } ++ } ++ if ((273u > v_dict_size) || (v_dict_size > ((uint64_t)(a_workbuf.len)))) { ++ return wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ } ++ wuffs_private_impl__slice_u8__copy_from_slice(wuffs_base__slice_u8__subslice_i(a_workbuf, v_dict_size), wuffs_base__slice_u8__subslice_j(a_workbuf, 273u)); ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func lzma.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_lzma__decoder__get_quirk( ++ const wuffs_lzma__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (a_key == 1348001792u) { ++ if (self->private_impl.f_allow_non_zero_initial_byte) { ++ return 1u; ++ } ++ } else if (a_key == 1348001793u) { ++ return ((uint64_t)(self->private_impl.f_format_extension)); ++ } ++ return 0u; ++} ++ ++// -------- func lzma.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_lzma__decoder__set_quirk( ++ wuffs_lzma__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ uint32_t v_v = 0; ++ uint32_t v_n = 0; ++ ++ if (a_key == 1348001792u) { ++ self->private_impl.f_allow_non_zero_initial_byte = (a_value > 0u); ++ } else if (a_key == 1348001793u) { ++ if (a_value == 0u) { ++ self->private_impl.f_format_extension = 0u; ++ return wuffs_base__make_status(NULL); ++ } else if ((a_value & 255u) == 1u) { ++ if ((a_value >> 8u) <= 255u) { ++ self->private_impl.f_format_extension = ((uint32_t)(a_value)); ++ v_v = (self->private_impl.f_format_extension >> 8u); ++ v_n = (((uint32_t)(1u)) << (v_v & 31u)); ++ wuffs_private_impl__u32__sat_sub_indirect(&v_n, ((v_n >> 4u) * ((v_v >> 5u) & 7u))); ++ if ((v_n < 4096u) || (536870912u < v_n)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_dict_size = v_n; ++ return wuffs_base__make_status(NULL); ++ } ++ } else if ((a_value & 255u) == 2u) { ++ if ((a_value >> 8u) <= 40u) { ++ self->private_impl.f_format_extension = ((uint32_t)(a_value)); ++ v_v = (self->private_impl.f_format_extension >> 8u); ++ if (v_v < 40u) { ++ self->private_impl.f_dict_size = ((2u | (v_v & 1u)) << ((v_v >> 1u) + 11u)); ++ } else { ++ self->private_impl.f_dict_size = 4294967295u; ++ } ++ return wuffs_base__make_status(NULL); ++ } ++ } ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func lzma.decoder.dst_history_retain_length ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_lzma__decoder__dst_history_retain_length( ++ const wuffs_lzma__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ ++ return wuffs_base__utility__make_optional_u63(true, 0u); ++} ++ ++// -------- func lzma.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_lzma__decoder__workbuf_len( ++ const wuffs_lzma__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ uint64_t v_m = 0; ++ ++ if (self->private_impl.f_dict_size == 0u) { ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++ } ++ v_m = (((uint64_t)(self->private_impl.f_dict_size)) + 273u); ++ return wuffs_base__utility__make_range_ii_u64(v_m, v_m); ++} ++ ++// -------- func lzma.decoder.transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_lzma__decoder__transform_io( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint64_t v_mark = 0; ++ wuffs_base__status v_dti_status = wuffs_base__make_status(NULL); ++ wuffs_base__status v_ah_status = wuffs_base__make_status(NULL); ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ ++ uint32_t coro_susp_point = self->private_impl.p_transform_io; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ v_mark = ((uint64_t)(iop_a_dst - io0_a_dst)); ++ { ++ if (a_dst) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ wuffs_base__status t_0 = wuffs_lzma__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); ++ v_dti_status = t_0; ++ if (a_dst) { ++ iop_a_dst = a_dst->data.ptr + a_dst->meta.wi; ++ } ++ } ++ if ( ! wuffs_base__status__is_suspension(&v_dti_status)) { ++ status = v_dti_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } else if ((v_dti_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__truncated_input); ++ goto exit; ++ } ++ v_ah_status = wuffs_lzma__decoder__add_history(self, wuffs_private_impl__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst), a_workbuf); ++ if (wuffs_base__status__is_error(&v_ah_status)) { ++ status = v_ah_status; ++ goto exit; ++ } ++ status = v_dti_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_transform_io = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func lzma.decoder.do_transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__do_transform_io( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_header_byte = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_c32 = 0; ++ uint8_t v_prop_byte = 0; ++ uint32_t v_lc = 0; ++ uint32_t v_lp = 0; ++ uint32_t v_pb = 0; ++ uint32_t v_length = 0; ++ uint32_t v_n_copied = 0; ++ uint64_t v_smark = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_transform_io; ++ if (coro_susp_point) { ++ v_header_byte = self->private_data.s_do_transform_io.v_header_byte; ++ v_length = self->private_data.s_do_transform_io.v_length; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ self->private_impl.f_lzma2_need_prob_reset = true; ++ self->private_impl.f_lzma2_need_properties = true; ++ self->private_impl.f_lzma2_need_dict_reset = true; ++ while (true) { ++ if ((self->private_impl.f_format_extension & 255u) == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_prop_byte = t_0; ++ } ++ if (v_prop_byte >= 225u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_header); ++ goto exit; ++ } ++ v_lc = ((uint32_t)(((uint8_t)(v_prop_byte % 9u)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_prop_byte /= 9u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_lp = ((uint32_t)(((uint8_t)(v_prop_byte % 5u)))); ++ v_pb = ((uint32_t)(((uint8_t)(v_prop_byte / 5u)))); ++ if ((v_lc + v_lp) > 4u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__unsupported_properties); ++ goto exit; ++ } ++ self->private_impl.f_lc = wuffs_base__u32__min(v_lc, 4u); ++ self->private_impl.f_lp = v_lp; ++ self->private_impl.f_pb = v_pb; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ v_c32 = t_1; ++ } ++ self->private_impl.f_dict_size = wuffs_base__u32__max(v_c32, 4096u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ uint64_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_2 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ if (num_bits_2 == 56) { ++ t_2 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)) << 56; ++ } ++ } ++ self->private_impl.f_decoded_length = t_2; ++ } ++ if ((self->private_impl.f_decoded_length >= 9223372036854775808u) && (self->private_impl.f_decoded_length != 18446744073709551615u)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__unsupported_decoded_length); ++ goto exit; ++ } ++ wuffs_lzma__decoder__initialize_probs(self); ++ } else if ((self->private_impl.f_format_extension & 255u) == 1u) { ++ self->private_impl.f_lc = 3u; ++ self->private_impl.f_lp = 0u; ++ self->private_impl.f_pb = 2u; ++ self->private_impl.f_decoded_length = 18446744073709551615u; ++ wuffs_lzma__decoder__initialize_probs(self); ++ } else { ++ while (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); ++ } ++ if (wuffs_base__peek_u8be__no_bounds_check(iop_a_src) == 0u) { ++ iop_a_src += 1u; ++ break; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_header_byte = t_3; ++ } ++ if (v_header_byte < 128u) { ++ if (v_header_byte < 2u) { ++ self->private_impl.f_lzma2_need_prob_reset = true; ++ self->private_impl.f_lzma2_need_properties = true; ++ self->private_impl.f_lzma2_need_dict_reset = false; ++ wuffs_lzma__decoder__initialize_dict(self); ++ } else if ((v_header_byte > 2u) || self->private_impl.f_lzma2_need_dict_reset) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_lzma2_header); ++ goto exit; ++ } ++ self->private_impl.f_prev_lzma2_chunk_was_uncompressed = true; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ uint32_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_4 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); ++ if (num_bits_4 == 8) { ++ t_4 = ((uint32_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)); ++ } ++ } ++ v_c32 = t_4; ++ } ++ v_length = (1u + v_c32); ++ while (true) { ++ v_n_copied = wuffs_private_impl__io_writer__limited_copy_u32_from_reader( ++ &iop_a_dst, io2_a_dst,v_length, &iop_a_src, io2_a_src); ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_stashed_pos, ((uint64_t)(v_n_copied))); ++ if (v_length <= v_n_copied) { ++ break; ++ } ++ v_length -= v_n_copied; ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) == 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); ++ } else { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); ++ } ++ } ++ continue; ++ } ++ self->private_impl.f_decoded_length = ((uint64_t)(v_header_byte)); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ uint32_t t_5; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_5 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); ++ if (num_bits_5 == 8) { ++ t_5 = ((uint32_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_5 += 8u; ++ *scratch |= ((uint64_t)(num_bits_5)); ++ } ++ } ++ v_c32 = t_5; ++ } ++ self->private_impl.f_decoded_length = (((self->private_impl.f_decoded_length & 31u) << 16u) + ((uint64_t)((1u + v_c32)))); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ uint32_t t_6; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_6 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6); ++ if (num_bits_6 == 8) { ++ t_6 = ((uint32_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_6 += 8u; ++ *scratch |= ((uint64_t)(num_bits_6)); ++ } ++ } ++ v_c32 = t_6; ++ } ++ self->private_impl.f_lzma2_encoded_length_want = ((uint64_t)((1u + v_c32))); ++ if (v_header_byte >= 160u) { ++ wuffs_lzma__decoder__initialize_probs(self); ++ self->private_impl.f_lzma2_need_prob_reset = false; ++ } ++ if (v_header_byte >= 192u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_7 = *iop_a_src++; ++ v_prop_byte = t_7; ++ } ++ if (v_prop_byte >= 225u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_lzma2_header); ++ goto exit; ++ } ++ v_lc = ((uint32_t)(((uint8_t)(v_prop_byte % 9u)))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_prop_byte /= 9u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_lp = ((uint32_t)(((uint8_t)(v_prop_byte % 5u)))); ++ v_pb = ((uint32_t)(((uint8_t)(v_prop_byte / 5u)))); ++ if ((v_lc + v_lp) > 4u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_lzma2_header); ++ goto exit; ++ } ++ self->private_impl.f_lc = wuffs_base__u32__min(v_lc, 4u); ++ self->private_impl.f_lp = v_lp; ++ self->private_impl.f_pb = v_pb; ++ self->private_impl.f_lzma2_need_properties = false; ++ } ++ if (v_header_byte >= 224u) { ++ self->private_impl.f_lzma2_need_dict_reset = false; ++ wuffs_lzma__decoder__initialize_dict(self); ++ } else if (self->private_impl.f_prev_lzma2_chunk_was_uncompressed) { ++ if (a_dst) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17); ++ status = wuffs_lzma__decoder__update_stashed_bytes(self, a_dst, a_workbuf); ++ if (a_dst) { ++ iop_a_dst = a_dst->data.ptr + a_dst->meta.wi; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ self->private_impl.f_prev_lzma2_chunk_was_uncompressed = false; ++ if (self->private_impl.f_lzma2_need_prob_reset || self->private_impl.f_lzma2_need_properties || self->private_impl.f_lzma2_need_dict_reset) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_lzma2_header); ++ goto exit; ++ } ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_8 = *iop_a_src++; ++ v_c8 = t_8; ++ } ++ if ((v_c8 != 0u) && ! self->private_impl.f_allow_non_zero_initial_byte) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_code); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19); ++ uint32_t t_9; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_9 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_9 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_9); ++ if (num_bits_9 == 24) { ++ t_9 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_9 += 8u; ++ *scratch |= ((uint64_t)(num_bits_9)); ++ } ++ } ++ self->private_impl.f_stashed_bits = t_9; ++ } ++ if (self->private_impl.f_stashed_bits == 4294967295u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_code); ++ goto exit; ++ } ++ self->private_impl.f_stashed_range = 4294967295u; ++ self->private_impl.f_stashed_pos_end = wuffs_base__u64__sat_add(self->private_impl.f_stashed_pos, self->private_impl.f_decoded_length); ++ if ((self->private_impl.f_stashed_pos_end == 18446744073709551615u) && (self->private_impl.f_decoded_length != 18446744073709551615u)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__unsupported_decoded_length); ++ goto exit; ++ } ++ self->private_impl.f_lzma2_encoded_length_have = 5u; ++ while (((uint64_t)(a_workbuf.len)) < (((uint64_t)(self->private_impl.f_dict_size)) + 273u)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_workbuf); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(21); ++ } ++ while (true) { ++ v_smark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ 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__status t_10 = wuffs_lzma__decoder__decode_bitstream(self, a_dst, a_src, a_workbuf); ++ v_status = t_10; ++ 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; ++ } ++ } ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_lzma2_encoded_length_have, wuffs_private_impl__io__count_since(v_smark, ((uint64_t)(iop_a_src - io0_a_src)))); ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(22); ++ } ++ if (self->private_impl.f_decoded_length == 18446744073709551615u) { ++ if (self->private_impl.f_stashed_bits != 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_bitstream_trailer); ++ goto exit; ++ } ++ } else if (self->private_impl.f_stashed_pos != self->private_impl.f_stashed_pos_end) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_decoded_length); ++ goto exit; ++ } else if (self->private_impl.f_stashed_bits != 0u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23); ++ status = wuffs_lzma__decoder__decode_optional_end_of_stream(self, a_src, a_workbuf); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (self->private_impl.f_stashed_bits != 0u) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_bitstream_trailer); ++ goto exit; ++ } ++ } ++ if ((self->private_impl.f_format_extension & 255u) < 2u) { ++ break; ++ } else if (self->private_impl.f_lzma2_encoded_length_have != self->private_impl.f_lzma2_encoded_length_want) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_lzma2_header); ++ goto exit; ++ } ++ } ++ ++ ok: ++ self->private_impl.p_do_transform_io = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_transform_io.v_header_byte = v_header_byte; ++ self->private_data.s_do_transform_io.v_length = v_length; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func lzma.decoder.decode_bitstream ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__decode_bitstream( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_bitstream; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ self->private_impl.f_end_of_chunk = false; ++ while (true) { ++ v_status = wuffs_lzma__decoder__decode_bitstream_fast(self, a_dst, a_src, a_workbuf); ++ if (wuffs_base__status__is_error(&v_status)) { ++ status = v_status; ++ goto exit; ++ } ++ if (self->private_impl.f_end_of_chunk) { ++ break; ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_lzma__decoder__decode_bitstream_slow(self, a_dst, a_src, a_workbuf); ++ if (status.repr) { ++ goto suspend; ++ } ++ if (self->private_impl.f_end_of_chunk) { ++ break; ++ } ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_bitstream = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_bitstream = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ return status; ++} ++ ++// -------- func lzma.decoder.update_stashed_bytes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__update_stashed_bytes( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_dist = 0; ++ uint32_t v_which = 0; ++ uint32_t v_adj_dist = 0; ++ uint64_t v_wb_index = 0; ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ ++ uint32_t coro_susp_point = self->private_impl.p_update_stashed_bytes; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ v_dist = 1u; ++ v_which = 0u; ++ while (v_which < 2u) { ++ if (((uint64_t)(v_dist)) <= ((uint64_t)(iop_a_dst - io0_a_dst))) { ++ wuffs_private_impl__io_writer__limited_copy_u32_from_history( ++ &iop_a_dst, io0_a_dst, io2_a_dst, 1u, v_dist); ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ self->private_impl.f_stashed_bytes[v_which] = iop_a_dst[-1]; ++ iop_a_dst--; ++ } else { ++ v_adj_dist = ((uint32_t)((((uint64_t)(v_dist)) - ((uint64_t)(iop_a_dst - io0_a_dst))))); ++ v_wb_index = ((uint64_t)(((uint64_t)(self->private_impl.f_dict_workbuf_index)) - ((uint64_t)(v_adj_dist)))); ++ while (v_wb_index >= 9223372036854775808u) { ++ v_wb_index += ((uint64_t)(self->private_impl.f_dict_size)); ++ } ++ if (v_wb_index >= ((uint64_t)(a_workbuf.len))) { ++ status = wuffs_base__make_status(wuffs_lzma__error__internal_error_inconsistent_dictionary_state); ++ goto exit; ++ } ++ self->private_impl.f_stashed_bytes[v_which] = a_workbuf.ptr[v_wb_index]; ++ } ++ v_dist = (1u + self->private_impl.f_stashed_rep0); ++ v_which += 1u; ++ } ++ ++ ok: ++ self->private_impl.p_update_stashed_bytes = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_update_stashed_bytes = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func lzma.decoder.decode_optional_end_of_stream ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzma__decoder__decode_optional_end_of_stream( ++ wuffs_lzma__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_w = &u_w; ++ uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_optional_end_of_stream; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ self->private_impl.f_stashed_pos_end = 18446744073709551615u; ++ while (true) { ++ { ++ wuffs_base__io_buffer* o_0_v_w = v_w; ++ uint8_t* o_0_iop_v_w = iop_v_w; ++ uint8_t* o_0_io0_v_w = io0_v_w; ++ uint8_t* o_0_io1_v_w = io1_v_w; ++ uint8_t* o_0_io2_v_w = io2_v_w; ++ v_w = wuffs_private_impl__io_writer__set( ++ &u_w, ++ &iop_v_w, ++ &io0_v_w, ++ &io1_v_w, ++ &io2_v_w, ++ wuffs_base__utility__empty_slice_u8(), ++ 0u); ++ { ++ wuffs_base__status t_0 = wuffs_lzma__decoder__decode_bitstream_slow(self, v_w, a_src, a_workbuf); ++ v_status = t_0; ++ } ++ v_w = o_0_v_w; ++ iop_v_w = o_0_iop_v_w; ++ io0_v_w = o_0_io0_v_w; ++ io1_v_w = o_0_io1_v_w; ++ io2_v_w = o_0_io2_v_w; ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } else if (v_status.repr == wuffs_base__suspension__short_write) { ++ status = wuffs_base__make_status(wuffs_lzma__error__bad_bitstream_trailer); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ self->private_impl.f_stashed_pos_end = self->private_impl.f_stashed_pos; ++ ++ ok: ++ self->private_impl.p_decode_optional_end_of_stream = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_optional_end_of_stream = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ return status; ++} ++ ++// -------- func lzma.decoder.initialize_dict ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_lzma__decoder__initialize_dict( ++ wuffs_lzma__decoder* self) { ++ self->private_impl.f_dict_workbuf_index = 0u; ++ self->private_impl.f_dict_seen = 0u; ++ self->private_impl.f_stashed_bytes[0u] = 0u; ++ self->private_impl.f_stashed_bytes[1u] = 0u; ++ self->private_impl.f_stashed_pos = 0u; ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func lzma.decoder.initialize_probs ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_lzma__decoder__initialize_probs( ++ wuffs_lzma__decoder* self) { ++ uint32_t v_i = 0; ++ uint32_t v_j = 0; ++ ++ v_i = 0u; ++ while (v_i < 192u) { ++ self->private_data.f_probs_ao00[v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 12u) { ++ self->private_data.f_probs_ao20[v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 12u) { ++ self->private_data.f_probs_ao40[v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 192u) { ++ self->private_data.f_probs_ao41[v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 12u) { ++ self->private_data.f_probs_ao60[v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 12u) { ++ self->private_data.f_probs_ao63[v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 16u) { ++ v_j = 0u; ++ while (v_j < 8u) { ++ self->private_data.f_probs_match_len_low[v_i][v_j] = 1024u; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 16u) { ++ v_j = 0u; ++ while (v_j < 8u) { ++ self->private_data.f_probs_match_len_mid[v_i][v_j] = 1024u; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 256u) { ++ self->private_data.f_probs_match_len_high[0u][v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 16u) { ++ v_j = 0u; ++ while (v_j < 8u) { ++ self->private_data.f_probs_longrep_len_low[v_i][v_j] = 1024u; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 16u) { ++ v_j = 0u; ++ while (v_j < 8u) { ++ self->private_data.f_probs_longrep_len_mid[v_i][v_j] = 1024u; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 256u) { ++ self->private_data.f_probs_longrep_len_high[0u][v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 4u) { ++ v_j = 0u; ++ while (v_j < 64u) { ++ self->private_data.f_probs_slot[v_i][v_j] = 1024u; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 128u) { ++ self->private_data.f_probs_small_dist[v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 16u) { ++ self->private_data.f_probs_large_dist[v_i] = 1024u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 16u) { ++ v_j = 0u; ++ while (v_j < 768u) { ++ self->private_data.f_probs_lit[v_i][v_j] = 1024u; ++ v_j += 1u; ++ } ++ v_i += 1u; ++ } ++ self->private_impl.f_stashed_state = 0u; ++ self->private_impl.f_stashed_rep0 = 0u; ++ self->private_impl.f_stashed_rep1 = 0u; ++ self->private_impl.f_stashed_rep2 = 0u; ++ self->private_impl.f_stashed_rep3 = 0u; ++ return wuffs_base__make_empty_struct(); ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZMA) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZIP) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_lzip__error__bad_checksum[] = "#lzip: bad checksum"; ++const char wuffs_lzip__error__bad_footer[] = "#lzip: bad footer"; ++const char wuffs_lzip__error__bad_header[] = "#lzip: bad header"; ++const char wuffs_lzip__error__truncated_input[] = "#lzip: truncated input"; ++ ++// ---------------- Private Consts ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzip__decoder__do_transform_io( ++ wuffs_lzip__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++// ---------------- VTables ++ ++const wuffs_base__io_transformer__func_ptrs ++wuffs_lzip__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++ (wuffs_base__optional_u63(*)(const void*))(&wuffs_lzip__decoder__dst_history_retain_length), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_lzip__decoder__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_lzip__decoder__set_quirk), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_lzip__decoder__transform_io), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_lzip__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_lzip__decoder__initialize( ++ wuffs_lzip__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ { ++ wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize( ++ &self->private_data.f_crc32, sizeof(self->private_data.f_crc32), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ { ++ wuffs_base__status z = wuffs_lzma__decoder__initialize( ++ &self->private_data.f_lzma, sizeof(self->private_data.f_lzma), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = ++ wuffs_base__io_transformer__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = ++ (const void*)(&wuffs_lzip__decoder__func_ptrs_for__wuffs_base__io_transformer); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_lzip__decoder* ++wuffs_lzip__decoder__alloc(void) { ++ wuffs_lzip__decoder* x = ++ (wuffs_lzip__decoder*)(calloc(1, sizeof(wuffs_lzip__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_lzip__decoder__initialize( ++ x, sizeof(wuffs_lzip__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_lzip__decoder(void) { ++ return sizeof(wuffs_lzip__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func lzip.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_lzip__decoder__get_quirk( ++ const wuffs_lzip__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if ((a_key == 1u) && self->private_impl.f_ignore_checksum) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func lzip.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_lzip__decoder__set_quirk( ++ wuffs_lzip__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (a_key == 1u) { ++ self->private_impl.f_ignore_checksum = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func lzip.decoder.dst_history_retain_length ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_lzip__decoder__dst_history_retain_length( ++ const wuffs_lzip__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ ++ return wuffs_lzma__decoder__dst_history_retain_length(&self->private_data.f_lzma); ++} ++ ++// -------- func lzip.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_lzip__decoder__workbuf_len( ++ const wuffs_lzip__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_lzma__decoder__workbuf_len(&self->private_data.f_lzma); ++} ++ ++// -------- func lzip.decoder.transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_lzip__decoder__transform_io( ++ wuffs_lzip__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_transform_io; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_lzip__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_lzip__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_transform_io = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func lzip.decoder.do_transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzip__decoder__do_transform_io( ++ wuffs_lzip__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_c32 = 0; ++ uint64_t v_c64 = 0; ++ uint64_t v_dmark = 0; ++ uint64_t v_smark = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint32_t v_checksum_want = 0; ++ uint32_t v_checksum_have = 0; ++ uint64_t v_size_want = 0; ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_transform_io; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint64_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 5)) { ++ t_0 = ((uint64_t)(wuffs_base__peek_u40le__no_bounds_check(iop_a_src))); ++ iop_a_src += 5; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 32) { ++ t_0 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ v_c64 = t_0; ++ } ++ if (v_c64 != 5641951820u) { ++ status = wuffs_base__make_status(wuffs_lzip__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ v_status = wuffs_lzma__decoder__set_quirk(&self->private_data.f_lzma, 1348001793u, (1u | (((uint64_t)(v_c8)) << 8u))); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ if (v_status.repr == wuffs_base__error__bad_argument) { ++ status = wuffs_base__make_status(wuffs_lzip__error__bad_header); ++ goto exit; ++ } ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ self->private_impl.f_ssize_have = 0u; ++ self->private_impl.f_dsize_have = 0u; ++ wuffs_lzma__decoder__set_quirk(&self->private_data.f_lzma, 1348001792u, 1u); ++ while (true) { ++ v_dmark = ((uint64_t)(iop_a_dst - io0_a_dst)); ++ v_smark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ 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__status t_2 = wuffs_lzma__decoder__transform_io(&self->private_data.f_lzma, a_dst, a_src, a_workbuf); ++ v_status = t_2; ++ 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; ++ } ++ } ++ self->private_impl.f_ssize_have += wuffs_private_impl__io__count_since(v_smark, ((uint64_t)(iop_a_src - io0_a_src))); ++ self->private_impl.f_dsize_have += wuffs_private_impl__io__count_since(v_dmark, ((uint64_t)(iop_a_dst - io0_a_dst))); ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_crc32__ieee_hasher__update(&self->private_data.f_crc32, wuffs_private_impl__io__since(v_dmark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_3 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; ++ if (num_bits_3 == 24) { ++ t_3 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ } ++ } ++ v_checksum_want = t_3; ++ } ++ if ( ! self->private_impl.f_ignore_checksum) { ++ v_checksum_have = wuffs_crc32__ieee_hasher__checksum_u32(&self->private_data.f_crc32); ++ if (v_checksum_have != v_checksum_want) { ++ status = wuffs_base__make_status(wuffs_lzip__error__bad_checksum); ++ goto exit; ++ } ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ uint64_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_4 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; ++ if (num_bits_4 == 56) { ++ t_4 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)) << 56; ++ } ++ } ++ v_size_want = t_4; ++ } ++ if (self->private_impl.f_dsize_have != v_size_want) { ++ status = wuffs_base__make_status(wuffs_lzip__error__bad_footer); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ uint64_t t_5; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_5 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_5 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_5; ++ if (num_bits_5 == 56) { ++ t_5 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_5 += 8u; ++ *scratch |= ((uint64_t)(num_bits_5)) << 56; ++ } ++ } ++ v_size_want = t_5; ++ } ++ if ((v_size_want < 26u) || (2251799813685248u < v_size_want)) { ++ status = wuffs_base__make_status(wuffs_lzip__error__bad_footer); ++ goto exit; ++ } else if (self->private_impl.f_ssize_have != (v_size_want - 26u)) { ++ status = wuffs_base__make_status(wuffs_lzip__error__bad_footer); ++ goto exit; ++ } ++ while (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ if (a_src && a_src->meta.closed) { ++ goto label__outer__break; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); ++ } ++ v_c32 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ if (v_c32 != 1346984524u) { ++ break; ++ } ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ wuffs_private_impl__ignore_status(wuffs_lzma__decoder__initialize(&self->private_data.f_lzma, ++ sizeof (wuffs_lzma__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ } ++ label__outer__break:; ++ ++ ok: ++ self->private_impl.p_do_transform_io = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZIP) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_lzw__error__bad_code[] = "#lzw: bad code"; ++const char wuffs_lzw__error__truncated_input[] = "#lzw: truncated input"; ++const char wuffs_lzw__error__internal_error_inconsistent_i_o[] = "#lzw: internal error: inconsistent I/O"; ++ ++// ---------------- Private Consts ++ ++#define WUFFS_LZW__QUIRKS_BASE 1348378624u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_lzw__decoder__read_from( ++ wuffs_lzw__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzw__decoder__write_to( ++ wuffs_lzw__decoder* self, ++ wuffs_base__io_buffer* a_dst); ++ ++// ---------------- VTables ++ ++const wuffs_base__io_transformer__func_ptrs ++wuffs_lzw__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++ (wuffs_base__optional_u63(*)(const void*))(&wuffs_lzw__decoder__dst_history_retain_length), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_lzw__decoder__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_lzw__decoder__set_quirk), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_lzw__decoder__transform_io), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_lzw__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_lzw__decoder__initialize( ++ wuffs_lzw__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = ++ wuffs_base__io_transformer__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = ++ (const void*)(&wuffs_lzw__decoder__func_ptrs_for__wuffs_base__io_transformer); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_lzw__decoder* ++wuffs_lzw__decoder__alloc(void) { ++ wuffs_lzw__decoder* x = ++ (wuffs_lzw__decoder*)(calloc(1, sizeof(wuffs_lzw__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_lzw__decoder__initialize( ++ x, sizeof(wuffs_lzw__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_lzw__decoder(void) { ++ return sizeof(wuffs_lzw__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func lzw.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_lzw__decoder__get_quirk( ++ const wuffs_lzw__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (a_key == 1348378624u) { ++ return ((uint64_t)(self->private_impl.f_pending_literal_width_plus_one)); ++ } ++ return 0u; ++} ++ ++// -------- func lzw.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_lzw__decoder__set_quirk( ++ wuffs_lzw__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (a_key == 1348378624u) { ++ if (a_value > 9u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_pending_literal_width_plus_one = ((uint32_t)(a_value)); ++ return wuffs_base__make_status(NULL); ++ } ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func lzw.decoder.dst_history_retain_length ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_lzw__decoder__dst_history_retain_length( ++ const wuffs_lzw__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ ++ return wuffs_base__utility__make_optional_u63(true, 0u); ++} ++ ++// -------- func lzw.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_lzw__decoder__workbuf_len( ++ const wuffs_lzw__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++} ++ ++// -------- func lzw.decoder.transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_lzw__decoder__transform_io( ++ wuffs_lzw__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_i = 0; ++ ++ uint32_t coro_susp_point = self->private_impl.p_transform_io; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ self->private_impl.f_literal_width = 8u; ++ if (self->private_impl.f_pending_literal_width_plus_one > 0u) { ++ self->private_impl.f_literal_width = (self->private_impl.f_pending_literal_width_plus_one - 1u); ++ } ++ self->private_impl.f_clear_code = (((uint32_t)(1u)) << self->private_impl.f_literal_width); ++ self->private_impl.f_end_code = (self->private_impl.f_clear_code + 1u); ++ self->private_impl.f_save_code = self->private_impl.f_end_code; ++ self->private_impl.f_prev_code = self->private_impl.f_end_code; ++ self->private_impl.f_width = (self->private_impl.f_literal_width + 1u); ++ self->private_impl.f_bits = 0u; ++ self->private_impl.f_n_bits = 0u; ++ self->private_impl.f_output_ri = 0u; ++ self->private_impl.f_output_wi = 0u; ++ v_i = 0u; ++ while (v_i < self->private_impl.f_clear_code) { ++ self->private_data.f_lm1s[v_i] = 0u; ++ self->private_data.f_suffixes[v_i][0u] = ((uint8_t)(v_i)); ++ v_i += 1u; ++ } ++ while (true) { ++ wuffs_lzw__decoder__read_from(self, a_src); ++ if (self->private_impl.f_output_wi > 0u) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_lzw__decoder__write_to(self, a_dst); ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ if (self->private_impl.f_read_from_return_value == 0u) { ++ break; ++ } else if (self->private_impl.f_read_from_return_value == 1u) { ++ continue; ++ } else if (self->private_impl.f_read_from_return_value == 2u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ } else if (self->private_impl.f_read_from_return_value == 3u) { ++ status = wuffs_base__make_status(wuffs_lzw__error__truncated_input); ++ goto exit; ++ } else if (self->private_impl.f_read_from_return_value == 4u) { ++ status = wuffs_base__make_status(wuffs_lzw__error__bad_code); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_lzw__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ } ++ ++ ok: ++ self->private_impl.p_transform_io = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func lzw.decoder.read_from ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_lzw__decoder__read_from( ++ wuffs_lzw__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ uint32_t v_clear_code = 0; ++ uint32_t v_end_code = 0; ++ uint32_t v_save_code = 0; ++ uint32_t v_prev_code = 0; ++ uint32_t v_width = 0; ++ uint32_t v_bits = 0; ++ uint32_t v_n_bits = 0; ++ uint32_t v_output_wi = 0; ++ uint32_t v_code = 0; ++ uint32_t v_c = 0; ++ uint32_t v_o = 0; ++ uint32_t v_steps = 0; ++ uint8_t v_first_byte = 0; ++ uint16_t v_lm1_b = 0; ++ uint16_t v_lm1_a = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } ++ ++ v_clear_code = self->private_impl.f_clear_code; ++ v_end_code = self->private_impl.f_end_code; ++ v_save_code = self->private_impl.f_save_code; ++ v_prev_code = self->private_impl.f_prev_code; ++ v_width = self->private_impl.f_width; ++ v_bits = self->private_impl.f_bits; ++ v_n_bits = self->private_impl.f_n_bits; ++ v_output_wi = self->private_impl.f_output_wi; ++ while (true) { ++ if (v_n_bits < v_width) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= 4u) { ++ v_bits |= ((uint32_t)(wuffs_base__peek_u32le__no_bounds_check(iop_a_src) << v_n_bits)); ++ iop_a_src += ((31u - v_n_bits) >> 3u); ++ v_n_bits |= 24u; ++ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ self->private_impl.f_read_from_return_value = 3u; ++ } else { ++ self->private_impl.f_read_from_return_value = 2u; ++ } ++ break; ++ } else { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ if (v_n_bits >= v_width) { ++ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ if (a_src && a_src->meta.closed) { ++ self->private_impl.f_read_from_return_value = 3u; ++ } else { ++ self->private_impl.f_read_from_return_value = 2u; ++ } ++ break; ++ } else { ++ v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); ++ iop_a_src += 1u; ++ v_n_bits += 8u; ++ if (v_n_bits < v_width) { ++ self->private_impl.f_read_from_return_value = 5u; ++ break; ++ } ++ } ++ } ++ } ++ v_code = ((v_bits) & WUFFS_PRIVATE_IMPL__LOW_BITS_MASK__U32(v_width)); ++ v_bits >>= v_width; ++ v_n_bits -= v_width; ++ if (v_code < v_clear_code) { ++ self->private_data.f_output[v_output_wi] = ((uint8_t)(v_code)); ++ v_output_wi = ((v_output_wi + 1u) & 8191u); ++ if (v_save_code <= 4095u) { ++ v_lm1_a = ((uint16_t)(((uint16_t)(self->private_data.f_lm1s[v_prev_code] + 1u)) & 4095u)); ++ self->private_data.f_lm1s[v_save_code] = v_lm1_a; ++ if (((uint16_t)(v_lm1_a % 8u)) != 0u) { ++ self->private_impl.f_prefixes[v_save_code] = self->private_impl.f_prefixes[v_prev_code]; ++ memcpy(self->private_data.f_suffixes[v_save_code],self->private_data.f_suffixes[v_prev_code], sizeof(self->private_data.f_suffixes[v_save_code])); ++ self->private_data.f_suffixes[v_save_code][((uint16_t)(v_lm1_a % 8u))] = ((uint8_t)(v_code)); ++ } else { ++ self->private_impl.f_prefixes[v_save_code] = ((uint16_t)(v_prev_code)); ++ self->private_data.f_suffixes[v_save_code][0u] = ((uint8_t)(v_code)); ++ } ++ v_save_code += 1u; ++ if (v_width < 12u) { ++ v_width += (1u & (v_save_code >> v_width)); ++ } ++ v_prev_code = v_code; ++ } ++ } else if (v_code <= v_end_code) { ++ if (v_code == v_end_code) { ++ self->private_impl.f_read_from_return_value = 0u; ++ break; ++ } ++ v_save_code = v_end_code; ++ v_prev_code = v_end_code; ++ v_width = (self->private_impl.f_literal_width + 1u); ++ } else if (v_code <= v_save_code) { ++ v_c = v_code; ++ if (v_code == v_save_code) { ++ v_c = v_prev_code; ++ } ++ v_o = ((v_output_wi + (((uint32_t)(self->private_data.f_lm1s[v_c])) & 4294967288u)) & 8191u); ++ v_output_wi = ((v_output_wi + 1u + ((uint32_t)(self->private_data.f_lm1s[v_c]))) & 8191u); ++ v_steps = (((uint32_t)(self->private_data.f_lm1s[v_c])) >> 3u); ++ while (true) { ++ memcpy((self->private_data.f_output)+(v_o), (self->private_data.f_suffixes[v_c]), 8u); ++ if (v_steps <= 0u) { ++ break; ++ } ++ v_steps -= 1u; ++ v_o = (((uint32_t)(v_o - 8u)) & 8191u); ++ v_c = ((uint32_t)(self->private_impl.f_prefixes[v_c])); ++ } ++ v_first_byte = self->private_data.f_suffixes[v_c][0u]; ++ if (v_code == v_save_code) { ++ self->private_data.f_output[v_output_wi] = v_first_byte; ++ v_output_wi = ((v_output_wi + 1u) & 8191u); ++ } ++ if (v_save_code <= 4095u) { ++ v_lm1_b = ((uint16_t)(((uint16_t)(self->private_data.f_lm1s[v_prev_code] + 1u)) & 4095u)); ++ self->private_data.f_lm1s[v_save_code] = v_lm1_b; ++ if (((uint16_t)(v_lm1_b % 8u)) != 0u) { ++ self->private_impl.f_prefixes[v_save_code] = self->private_impl.f_prefixes[v_prev_code]; ++ memcpy(self->private_data.f_suffixes[v_save_code],self->private_data.f_suffixes[v_prev_code], sizeof(self->private_data.f_suffixes[v_save_code])); ++ self->private_data.f_suffixes[v_save_code][((uint16_t)(v_lm1_b % 8u))] = v_first_byte; ++ } else { ++ self->private_impl.f_prefixes[v_save_code] = ((uint16_t)(v_prev_code)); ++ self->private_data.f_suffixes[v_save_code][0u] = ((uint8_t)(v_first_byte)); ++ } ++ v_save_code += 1u; ++ if (v_width < 12u) { ++ v_width += (1u & (v_save_code >> v_width)); ++ } ++ v_prev_code = v_code; ++ } ++ } else { ++ self->private_impl.f_read_from_return_value = 4u; ++ break; ++ } ++ if (v_output_wi > 4095u) { ++ self->private_impl.f_read_from_return_value = 1u; ++ break; ++ } ++ } ++ if (self->private_impl.f_read_from_return_value != 2u) { ++ while (v_n_bits >= 8u) { ++ v_n_bits -= 8u; ++ if (iop_a_src > io1_a_src) { ++ iop_a_src--; ++ } else { ++ self->private_impl.f_read_from_return_value = 5u; ++ break; ++ } ++ } ++ } ++ self->private_impl.f_save_code = v_save_code; ++ self->private_impl.f_prev_code = v_prev_code; ++ self->private_impl.f_width = v_width; ++ self->private_impl.f_bits = v_bits; ++ self->private_impl.f_n_bits = v_n_bits; ++ self->private_impl.f_output_wi = v_output_wi; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func lzw.decoder.write_to ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_lzw__decoder__write_to( ++ wuffs_lzw__decoder* self, ++ wuffs_base__io_buffer* a_dst) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__slice_u8 v_s = {0}; ++ uint64_t v_n = 0; ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ ++ uint32_t coro_susp_point = self->private_impl.p_write_to; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (self->private_impl.f_output_wi > 0u) { ++ if (self->private_impl.f_output_ri > self->private_impl.f_output_wi) { ++ status = wuffs_base__make_status(wuffs_lzw__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ v_s = wuffs_base__make_slice_u8_ij(self->private_data.f_output, ++ self->private_impl.f_output_ri, ++ self->private_impl.f_output_wi); ++ v_n = wuffs_private_impl__io_writer__copy_from_slice(&iop_a_dst, io2_a_dst,v_s); ++ if (v_n == ((uint64_t)(v_s.len))) { ++ self->private_impl.f_output_ri = 0u; ++ self->private_impl.f_output_wi = 0u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ } ++ self->private_impl.f_output_ri = (((uint32_t)(self->private_impl.f_output_ri + ((uint32_t)(v_n)))) & 8191u); ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_write_to = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_write_to = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func lzw.decoder.flush ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8 ++wuffs_lzw__decoder__flush( ++ wuffs_lzw__decoder* self) { ++ if (!self) { ++ return wuffs_base__empty_slice_u8(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__empty_slice_u8(); ++ } ++ ++ uint32_t v_ri = 0; ++ uint32_t v_wi = 0; ++ ++ v_ri = self->private_impl.f_output_ri; ++ v_wi = self->private_impl.f_output_wi; ++ self->private_impl.f_output_ri = 0u; ++ self->private_impl.f_output_wi = 0u; ++ if (v_ri <= v_wi) { ++ return wuffs_base__make_slice_u8_ij(self->private_data.f_output, v_ri, v_wi); ++ } ++ return wuffs_base__make_slice_u8(self->private_data.f_output, 0); ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NETPBM) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_netpbm__error__bad_header[] = "#netpbm: bad header"; ++const char wuffs_netpbm__error__truncated_input[] = "#netpbm: truncated input"; ++const char wuffs_netpbm__error__unsupported_netpbm_file[] = "#netpbm: unsupported Netpbm file"; ++const char wuffs_netpbm__note__internal_note_short_read[] = "@netpbm: internal note: short read"; ++ ++// ---------------- Private Consts ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_netpbm__decoder__do_decode_image_config( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_netpbm__decoder__do_decode_frame_config( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_netpbm__decoder__do_decode_frame( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_netpbm__decoder__swizzle( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++// ---------------- VTables ++ ++const wuffs_base__image_decoder__func_ptrs ++wuffs_netpbm__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_netpbm__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_netpbm__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_netpbm__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_netpbm__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_netpbm__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_netpbm__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_netpbm__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_netpbm__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_netpbm__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_netpbm__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_netpbm__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_netpbm__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_netpbm__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_netpbm__decoder__initialize( ++ wuffs_netpbm__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_netpbm__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_netpbm__decoder* ++wuffs_netpbm__decoder__alloc(void) { ++ wuffs_netpbm__decoder* x = ++ (wuffs_netpbm__decoder*)(calloc(1, sizeof(wuffs_netpbm__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_netpbm__decoder__initialize( ++ x, sizeof(wuffs_netpbm__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_netpbm__decoder(void) { ++ return sizeof(wuffs_netpbm__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func netpbm.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_netpbm__decoder__get_quirk( ++ const wuffs_netpbm__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func netpbm.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_netpbm__decoder__set_quirk( ++ wuffs_netpbm__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func netpbm.decoder.decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_netpbm__decoder__decode_image_config( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_netpbm__decoder__do_decode_image_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func netpbm.decoder.do_decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_netpbm__decoder__do_decode_image_config( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_n = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (v_c8 != 80u) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if ((v_c8 < 49u) || (55u < v_c8)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } else if (v_c8 == 53u) { ++ self->private_impl.f_pixfmt = 536870920u; ++ } else if (v_c8 == 54u) { ++ self->private_impl.f_pixfmt = 2684356744u; ++ } else { ++ status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ if (v_c8 != 10u) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ if ((v_c8 == 32u) || (v_c8 == 9u)) { ++ continue; ++ } else if (v_c8 == 35u) { ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; ++ } ++ if (v_c8 == 10u) { ++ break; ++ } ++ } ++ continue; ++ } else if ((v_c8 < 48u) || (57u < v_c8)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } ++ self->private_impl.f_width = ((uint32_t)(((uint8_t)(v_c8 - 48u)))); ++ break; ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; ++ } ++ if ((v_c8 == 32u) || (v_c8 == 9u)) { ++ break; ++ } else if ((v_c8 < 48u) || (57u < v_c8)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } ++ v_n = ((10u * self->private_impl.f_width) + ((uint32_t)(((uint8_t)(v_c8 - 48u))))); ++ if (v_n > 16777215u) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); ++ goto exit; ++ } ++ self->private_impl.f_width = v_n; ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; ++ } ++ if ((v_c8 == 32u) || (v_c8 == 9u)) { ++ continue; ++ } else if (v_c8 == 35u) { ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_7 = *iop_a_src++; ++ v_c8 = t_7; ++ } ++ if (v_c8 == 10u) { ++ break; ++ } ++ } ++ continue; ++ } else if ((v_c8 < 48u) || (57u < v_c8)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } ++ self->private_impl.f_height = ((uint32_t)(((uint8_t)(v_c8 - 48u)))); ++ break; ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_8 = *iop_a_src++; ++ v_c8 = t_8; ++ } ++ if ((v_c8 == 32u) || (v_c8 == 9u) || (v_c8 == 13u)) { ++ continue; ++ } else if (v_c8 == 10u) { ++ break; ++ } else if ((v_c8 < 48u) || (57u < v_c8)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } ++ v_n = ((10u * self->private_impl.f_height) + ((uint32_t)(((uint8_t)(v_c8 - 48u))))); ++ if (v_n > 16777215u) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); ++ goto exit; ++ } ++ self->private_impl.f_height = v_n; ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_9 = *iop_a_src++; ++ v_c8 = t_9; ++ } ++ if ((v_c8 == 32u) || (v_c8 == 9u)) { ++ continue; ++ } else if (v_c8 == 35u) { ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_10 = *iop_a_src++; ++ v_c8 = t_10; ++ } ++ if (v_c8 == 10u) { ++ break; ++ } ++ } ++ continue; ++ } else if ((v_c8 < 48u) || (57u < v_c8)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } ++ self->private_impl.f_max_value = ((uint32_t)(((uint8_t)(v_c8 - 48u)))); ++ break; ++ } ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_11 = *iop_a_src++; ++ v_c8 = t_11; ++ } ++ if ((v_c8 == 32u) || (v_c8 == 9u) || (v_c8 == 13u)) { ++ continue; ++ } else if (v_c8 == 10u) { ++ break; ++ } else if ((v_c8 < 48u) || (57u < v_c8)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ goto exit; ++ } ++ v_n = ((10u * self->private_impl.f_max_value) + ((uint32_t)(((uint8_t)(v_c8 - 48u))))); ++ if (v_n > 16777215u) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); ++ goto exit; ++ } ++ self->private_impl.f_max_value = v_n; ++ } ++ if (self->private_impl.f_max_value != 255u) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); ++ goto exit; ++ } ++ self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ if (a_dst != NULL) { ++ wuffs_base__image_config__set( ++ a_dst, ++ self->private_impl.f_pixfmt, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ self->private_impl.f_frame_config_io_position, ++ false); ++ } ++ self->private_impl.f_call_sequence = 32u; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_do_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func netpbm.decoder.decode_frame_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_netpbm__decoder__decode_frame_config( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 2)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_netpbm__decoder__do_decode_frame_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func netpbm.decoder.do_decode_frame_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_netpbm__decoder__do_decode_frame_config( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_netpbm__decoder__do_decode_image_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); ++ goto exit; ++ } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ self->private_impl.f_call_sequence = 96u; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height), ++ ((wuffs_base__flicks)(0u)), ++ 0u, ++ self->private_impl.f_frame_config_io_position, ++ 0u, ++ false, ++ false, ++ 0u); ++ } ++ self->private_impl.f_call_sequence = 64u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func netpbm.decoder.decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_netpbm__decoder__decode_frame( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 3)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_netpbm__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_netpbm__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func netpbm.decoder.do_decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_netpbm__decoder__do_decode_frame( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_netpbm__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y = 0u; ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette(a_dst), ++ wuffs_base__utility__make_pixel_format(self->private_impl.f_pixfmt), ++ wuffs_base__utility__empty_slice_u8(), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ while (true) { ++ v_status = wuffs_netpbm__decoder__swizzle(self, a_dst, a_src); ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } else if (v_status.repr != wuffs_netpbm__note__internal_note_short_read) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ } ++ self->private_impl.f_call_sequence = 96u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ return status; ++} ++ ++// -------- func netpbm.decoder.swizzle ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_netpbm__decoder__swizzle( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row = 0; ++ uint32_t v_src_bytes_per_pixel = 0; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint64_t v_i = 0; ++ uint64_t v_j = 0; ++ uint64_t v_n = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } ++ ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ goto exit; ++ } ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ while (true) { ++ if (self->private_impl.f_dst_x == self->private_impl.f_width) { ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y += 1u; ++ if (self->private_impl.f_dst_y >= self->private_impl.f_height) { ++ break; ++ } ++ } ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); ++ } ++ v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); ++ if (v_i >= ((uint64_t)(v_dst.len))) { ++ v_src_bytes_per_pixel = 1u; ++ if (self->private_impl.f_pixfmt == 2684356744u) { ++ v_src_bytes_per_pixel = 3u; ++ } ++ v_n = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(v_src_bytes_per_pixel))); ++ v_n = wuffs_base__u64__min(v_n, ((uint64_t)(((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x))))); ++ v_j = v_n; ++ while (v_j >= 8u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 8u)))) { ++ iop_a_src += (v_src_bytes_per_pixel * 8u); ++ } ++ v_j -= 8u; ++ } ++ while (v_j > 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 1u)))) { ++ iop_a_src += (v_src_bytes_per_pixel * 1u); ++ } ++ v_j -= 1u; ++ } ++ } else { ++ v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( ++ &self->private_impl.f_swizzler, ++ wuffs_base__slice_u8__subslice_i(v_dst, v_i), ++ wuffs_base__pixel_buffer__palette(a_dst), ++ &iop_a_src, ++ io2_a_src); ++ } ++ if (v_n == 0u) { ++ status = wuffs_base__make_status(wuffs_netpbm__note__internal_note_short_read); ++ goto ok; ++ } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); ++ } ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ ++ ok: ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func netpbm.decoder.frame_dirty_rect ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_netpbm__decoder__frame_dirty_rect( ++ const wuffs_netpbm__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ ++ return wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height); ++} ++ ++// -------- func netpbm.decoder.num_animation_loops ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_netpbm__decoder__num_animation_loops( ++ const wuffs_netpbm__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func netpbm.decoder.num_decoded_frame_configs ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_netpbm__decoder__num_decoded_frame_configs( ++ const wuffs_netpbm__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 32u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func netpbm.decoder.num_decoded_frames ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_netpbm__decoder__num_decoded_frames( ++ const wuffs_netpbm__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 64u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func netpbm.decoder.restart_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_netpbm__decoder__restart_frame( ++ wuffs_netpbm__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (self->private_impl.f_call_sequence < 32u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } ++ if ((a_index != 0u) || (a_io_position != self->private_impl.f_frame_config_io_position)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_call_sequence = 40u; ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func netpbm.decoder.set_report_metadata ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_netpbm__decoder__set_report_metadata( ++ wuffs_netpbm__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func netpbm.decoder.tell_me_more ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_netpbm__decoder__tell_me_more( ++ wuffs_netpbm__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); ++ goto exit; ++ ++ goto ok; ++ ok: ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func netpbm.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_netpbm__decoder__workbuf_len( ++ const wuffs_netpbm__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NETPBM) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_nie__error__bad_header[] = "#nie: bad header"; ++const char wuffs_nie__error__truncated_input[] = "#nie: truncated input"; ++const char wuffs_nie__error__unsupported_nie_file[] = "#nie: unsupported NIE file"; ++const char wuffs_nie__note__internal_note_short_read[] = "@nie: internal note: short read"; ++ ++// ---------------- Private Consts ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_nie__decoder__do_decode_image_config( ++ wuffs_nie__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_nie__decoder__do_decode_frame_config( ++ wuffs_nie__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_nie__decoder__do_decode_frame( ++ wuffs_nie__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_nie__decoder__swizzle( ++ wuffs_nie__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++// ---------------- VTables ++ ++const wuffs_base__image_decoder__func_ptrs ++wuffs_nie__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_nie__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_nie__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_nie__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_nie__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_nie__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_nie__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_nie__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_nie__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_nie__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_nie__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_nie__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_nie__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_nie__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_nie__decoder__initialize( ++ wuffs_nie__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_nie__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_nie__decoder* ++wuffs_nie__decoder__alloc(void) { ++ wuffs_nie__decoder* x = ++ (wuffs_nie__decoder*)(calloc(1, sizeof(wuffs_nie__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_nie__decoder__initialize( ++ x, sizeof(wuffs_nie__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_nie__decoder(void) { ++ return sizeof(wuffs_nie__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func nie.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_nie__decoder__get_quirk( ++ const wuffs_nie__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func nie.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__set_quirk( ++ wuffs_nie__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func nie.decoder.decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__decode_image_config( ++ wuffs_nie__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_nie__decoder__do_decode_image_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_nie__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func nie.decoder.do_decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_nie__decoder__do_decode_image_config( ++ wuffs_nie__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_a = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ v_a = t_0; ++ } ++ if (v_a != 1169146734u) { ++ status = wuffs_base__make_status(wuffs_nie__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ v_a = t_1; ++ } ++ if (v_a == 879649535u) { ++ self->private_impl.f_pixfmt = 2164295816u; ++ } else if (v_a == 946758399u) { ++ self->private_impl.f_pixfmt = 2164308923u; ++ } else if (v_a == 879780607u) { ++ status = wuffs_base__make_status(wuffs_nie__error__unsupported_nie_file); ++ goto exit; ++ } else if (v_a == 946889471u) { ++ status = wuffs_base__make_status(wuffs_nie__error__unsupported_nie_file); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_nie__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ if (num_bits_2 == 24) { ++ t_2 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)) << 56; ++ } ++ } ++ v_a = t_2; ++ } ++ if (v_a > 2147483647u) { ++ status = wuffs_base__make_status(wuffs_nie__error__bad_header); ++ goto exit; ++ } else if (v_a > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } ++ self->private_impl.f_width = v_a; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_3 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; ++ if (num_bits_3 == 24) { ++ t_3 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ } ++ } ++ v_a = t_3; ++ } ++ if (v_a > 2147483647u) { ++ status = wuffs_base__make_status(wuffs_nie__error__bad_header); ++ goto exit; ++ } else if (v_a > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } ++ self->private_impl.f_height = v_a; ++ if (a_dst != NULL) { ++ wuffs_base__image_config__set( ++ a_dst, ++ self->private_impl.f_pixfmt, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ 16u, ++ false); ++ } ++ self->private_impl.f_call_sequence = 32u; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_do_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func nie.decoder.decode_frame_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__decode_frame_config( ++ wuffs_nie__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 2)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_nie__decoder__do_decode_frame_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_nie__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func nie.decoder.do_decode_frame_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_nie__decoder__do_decode_frame_config( ++ wuffs_nie__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_nie__decoder__do_decode_image_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (16u != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); ++ goto exit; ++ } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ self->private_impl.f_call_sequence = 96u; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height), ++ ((wuffs_base__flicks)(0u)), ++ 0u, ++ 16u, ++ 0u, ++ false, ++ false, ++ 0u); ++ } ++ self->private_impl.f_call_sequence = 64u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func nie.decoder.decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__decode_frame( ++ wuffs_nie__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 3)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_nie__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_nie__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func nie.decoder.do_decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_nie__decoder__do_decode_frame( ++ wuffs_nie__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_nie__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y = 0u; ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette(a_dst), ++ wuffs_base__utility__make_pixel_format(self->private_impl.f_pixfmt), ++ wuffs_base__utility__empty_slice_u8(), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ while (true) { ++ v_status = wuffs_nie__decoder__swizzle(self, a_dst, a_src); ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } else if (v_status.repr != wuffs_nie__note__internal_note_short_read) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ } ++ self->private_impl.f_call_sequence = 96u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ return status; ++} ++ ++// -------- func nie.decoder.swizzle ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_nie__decoder__swizzle( ++ wuffs_nie__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row = 0; ++ uint32_t v_src_bytes_per_pixel = 0; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint64_t v_i = 0; ++ uint64_t v_j = 0; ++ uint64_t v_n = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } ++ ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ goto exit; ++ } ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ while (true) { ++ if (self->private_impl.f_dst_x == self->private_impl.f_width) { ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y += 1u; ++ if (self->private_impl.f_dst_y >= self->private_impl.f_height) { ++ break; ++ } ++ } ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); ++ } ++ v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); ++ if (v_i >= ((uint64_t)(v_dst.len))) { ++ v_src_bytes_per_pixel = 4u; ++ if (self->private_impl.f_pixfmt == 2164308923u) { ++ v_src_bytes_per_pixel = 8u; ++ } ++ v_n = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(v_src_bytes_per_pixel))); ++ v_n = wuffs_base__u64__min(v_n, ((uint64_t)(((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x))))); ++ v_j = v_n; ++ while (v_j >= 8u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 8u)))) { ++ iop_a_src += (v_src_bytes_per_pixel * 8u); ++ } ++ v_j -= 8u; ++ } ++ while (v_j > 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 1u)))) { ++ iop_a_src += (v_src_bytes_per_pixel * 1u); ++ } ++ v_j -= 1u; ++ } ++ } else { ++ v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( ++ &self->private_impl.f_swizzler, ++ wuffs_base__slice_u8__subslice_i(v_dst, v_i), ++ wuffs_base__pixel_buffer__palette(a_dst), ++ &iop_a_src, ++ io2_a_src); ++ } ++ if (v_n == 0u) { ++ status = wuffs_base__make_status(wuffs_nie__note__internal_note_short_read); ++ goto ok; ++ } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); ++ } ++ status = wuffs_base__make_status(NULL); ++ goto ok; ++ ++ ok: ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func nie.decoder.frame_dirty_rect ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_nie__decoder__frame_dirty_rect( ++ const wuffs_nie__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ ++ return wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height); ++} ++ ++// -------- func nie.decoder.num_animation_loops ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_nie__decoder__num_animation_loops( ++ const wuffs_nie__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func nie.decoder.num_decoded_frame_configs ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_nie__decoder__num_decoded_frame_configs( ++ const wuffs_nie__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 32u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func nie.decoder.num_decoded_frames ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_nie__decoder__num_decoded_frames( ++ const wuffs_nie__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 64u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func nie.decoder.restart_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__restart_frame( ++ wuffs_nie__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (self->private_impl.f_call_sequence < 32u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } ++ if ((a_index != 0u) || (a_io_position != 16u)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_call_sequence = 40u; ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func nie.decoder.set_report_metadata ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_nie__decoder__set_report_metadata( ++ wuffs_nie__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func nie.decoder.tell_me_more ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_nie__decoder__tell_me_more( ++ wuffs_nie__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); ++ goto exit; ++ ++ goto ok; ++ ok: ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func nie.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_nie__decoder__workbuf_len( ++ const wuffs_nie__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_zlib__note__dictionary_required[] = "@zlib: dictionary required"; ++const char wuffs_zlib__error__bad_checksum[] = "#zlib: bad checksum"; ++const char wuffs_zlib__error__bad_compression_method[] = "#zlib: bad compression method"; ++const char wuffs_zlib__error__bad_compression_window_size[] = "#zlib: bad compression window size"; ++const char wuffs_zlib__error__bad_parity_check[] = "#zlib: bad parity check"; ++const char wuffs_zlib__error__incorrect_dictionary[] = "#zlib: incorrect dictionary"; ++const char wuffs_zlib__error__truncated_input[] = "#zlib: truncated input"; ++ ++// ---------------- Private Consts ++ ++#define WUFFS_ZLIB__QUIRKS_BASE 2113790976u ++ ++#define WUFFS_ZLIB__QUIRKS_COUNT 1u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_zlib__decoder__do_transform_io( ++ wuffs_zlib__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++// ---------------- VTables ++ ++const wuffs_base__io_transformer__func_ptrs ++wuffs_zlib__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++ (wuffs_base__optional_u63(*)(const void*))(&wuffs_zlib__decoder__dst_history_retain_length), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_zlib__decoder__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_zlib__decoder__set_quirk), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_zlib__decoder__transform_io), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_zlib__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_zlib__decoder__initialize( ++ wuffs_zlib__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ { ++ wuffs_base__status z = wuffs_adler32__hasher__initialize( ++ &self->private_data.f_checksum, sizeof(self->private_data.f_checksum), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ { ++ wuffs_base__status z = wuffs_adler32__hasher__initialize( ++ &self->private_data.f_dict_id_hasher, sizeof(self->private_data.f_dict_id_hasher), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ { ++ wuffs_base__status z = wuffs_deflate__decoder__initialize( ++ &self->private_data.f_flate, sizeof(self->private_data.f_flate), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = ++ wuffs_base__io_transformer__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = ++ (const void*)(&wuffs_zlib__decoder__func_ptrs_for__wuffs_base__io_transformer); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_zlib__decoder* ++wuffs_zlib__decoder__alloc(void) { ++ wuffs_zlib__decoder* x = ++ (wuffs_zlib__decoder*)(calloc(1, sizeof(wuffs_zlib__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_zlib__decoder__initialize( ++ x, sizeof(wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_zlib__decoder(void) { ++ return sizeof(wuffs_zlib__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func zlib.decoder.dictionary_id ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_zlib__decoder__dictionary_id( ++ const wuffs_zlib__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return self->private_impl.f_dict_id_want; ++} ++ ++// -------- func zlib.decoder.add_dictionary ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_zlib__decoder__add_dictionary( ++ wuffs_zlib__decoder* self, ++ wuffs_base__slice_u8 a_dict) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); ++ } ++ ++ if (self->private_impl.f_header_complete) { ++ self->private_impl.f_bad_call_sequence = true; ++ } else { ++ self->private_impl.f_dict_id_have = wuffs_adler32__hasher__update_u32(&self->private_data.f_dict_id_hasher, a_dict); ++ wuffs_deflate__decoder__add_history(&self->private_data.f_flate, a_dict); ++ } ++ self->private_impl.f_got_dictionary = true; ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func zlib.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_zlib__decoder__get_quirk( ++ const wuffs_zlib__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ uint32_t v_key = 0; ++ ++ if ((a_key == 1u) && self->private_impl.f_ignore_checksum) { ++ return 1u; ++ } else if (a_key >= 2113790976u) { ++ v_key = (a_key - 2113790976u); ++ if (v_key < 1u) { ++ if (self->private_impl.f_quirks[v_key]) { ++ return 1u; ++ } ++ } ++ } ++ return 0u; ++} ++ ++// -------- func zlib.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_zlib__decoder__set_quirk( ++ wuffs_zlib__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (self->private_impl.f_header_complete) { ++ self->private_impl.f_bad_call_sequence = true; ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } else if (a_key == 1u) { ++ self->private_impl.f_ignore_checksum = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } else if (a_key >= 2113790976u) { ++ a_key -= 2113790976u; ++ if (a_key < 1u) { ++ self->private_impl.f_quirks[a_key] = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } ++ } ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func zlib.decoder.dst_history_retain_length ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_zlib__decoder__dst_history_retain_length( ++ const wuffs_zlib__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ ++ return wuffs_base__utility__make_optional_u63(true, 0u); ++} ++ ++// -------- func zlib.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_zlib__decoder__workbuf_len( ++ const wuffs_zlib__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__make_range_ii_u64(1u, 1u); ++} ++ ++// -------- func zlib.decoder.transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_zlib__decoder__transform_io( ++ wuffs_zlib__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_transform_io; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_zlib__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_zlib__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_transform_io = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func zlib.decoder.do_transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_zlib__decoder__do_transform_io( ++ wuffs_zlib__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint16_t v_x = 0; ++ uint32_t v_checksum_have = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint32_t v_checksum_want = 0; ++ uint64_t v_mark = 0; ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_transform_io; ++ if (coro_susp_point) { ++ v_checksum_have = self->private_data.s_do_transform_io.v_checksum_have; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_bad_call_sequence) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } else if (self->private_impl.f_quirks[0u]) { ++ } else if ( ! self->private_impl.f_want_dictionary) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint16_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_0 = wuffs_base__peek_u16be__no_bounds_check(iop_a_src); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); + while (true) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_number_length = wuffs_json__decoder__decode_number(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- v_number_status = (v_number_length >> 8u); +- v_vminor = 10486787u; +- if ((v_number_length & 128u) != 0u) { +- v_vminor = 10486785u; ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- v_number_length = (v_number_length & 127u); +- if (v_number_status == 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_number_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 8) { ++ t_0 = ((uint16_t)(*scratch >> 48)); + break; + } +- while (v_number_length > 0u) { +- v_number_length -= 1u; +- if (iop_a_src > io1_a_src) { +- iop_a_src--; +- } else { +- status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); +- goto exit; ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ } ++ v_x = t_0; ++ } ++ if (((uint16_t)(((uint16_t)(v_x >> 8u)) & 15u)) != 8u) { ++ status = wuffs_base__make_status(wuffs_zlib__error__bad_compression_method); ++ goto exit; ++ } ++ if (((uint16_t)(v_x >> 12u)) > 7u) { ++ status = wuffs_base__make_status(wuffs_zlib__error__bad_compression_window_size); ++ goto exit; ++ } ++ if (((uint16_t)(v_x % 31u)) != 0u) { ++ status = wuffs_base__make_status(wuffs_zlib__error__bad_parity_check); ++ goto exit; ++ } ++ self->private_impl.f_want_dictionary = (((uint16_t)(v_x & 32u)) != 0u); ++ if (self->private_impl.f_want_dictionary) { ++ self->private_impl.f_dict_id_have = 1u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- } +- if (v_number_status == 1u) { +- if (self->private_impl.f_quirks[14u]) { +- 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(16); +- status = wuffs_json__decoder__decode_inf_nan(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; +- } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch >> 32)); + break; + } +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } else if (v_number_status == 2u) { +- status = wuffs_base__make_status(wuffs_json__error__unsupported_number_length); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17); +- while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(18); +- } +- } +- } +- break; +- } else if (v_class == 5u) { +- v_vminor = 2113553u; +- if (v_depth == 0u) { +- } else if (0u != (v_expect_after_value & (((uint32_t)(1u)) << 6u))) { +- v_vminor = 2113601u; +- } else { +- v_vminor = 2113569u; +- } +- if (v_depth >= 1024u) { +- status = wuffs_base__make_status(wuffs_json__error__unsupported_recursion_depth); +- goto exit; +- } +- v_stack_byte = (v_depth / 32u); +- v_stack_bit = (v_depth & 31u); +- self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(1u)) << v_stack_bit); +- v_depth += 1u; +- iop_a_src += 1u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_expect = 4162u; +- v_expect_after_value = 4164u; +- goto label__outer__continue; +- } else if (v_class == 6u) { +- iop_a_src += 1u; +- if (v_depth <= 1u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2101314u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__outer__break; +- } +- v_depth -= 1u; +- v_stack_byte = ((v_depth - 1u) / 32u); +- v_stack_bit = ((v_depth - 1u) & 31u); +- if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2105410u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_expect = 4356u; +- v_expect_after_value = 4356u; +- } else { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2113602u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_expect = 4164u; +- v_expect_after_value = 4164u; +- } +- goto label__outer__continue; +- } else if (v_class == 7u) { +- v_vminor = 2105361u; +- if (v_depth == 0u) { +- } else if (0u != (v_expect_after_value & (((uint32_t)(1u)) << 6u))) { +- v_vminor = 2105409u; +- } else { +- v_vminor = 2105377u; +- } +- if (v_depth >= 1024u) { +- status = wuffs_base__make_status(wuffs_json__error__unsupported_recursion_depth); +- goto exit; +- } +- v_stack_byte = (v_depth / 32u); +- v_stack_bit = (v_depth & 31u); +- self->private_data.f_stack[v_stack_byte] &= (4294967295u ^ (((uint32_t)(1u)) << v_stack_bit)); +- v_depth += 1u; +- iop_a_src += 1u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_expect = 8114u; +- v_expect_after_value = 4356u; +- goto label__outer__continue; +- } else if (v_class == 8u) { +- iop_a_src += 1u; +- if (v_depth <= 1u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2101282u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- goto label__outer__break; +- } +- v_depth -= 1u; +- v_stack_byte = ((v_depth - 1u) / 32u); +- v_stack_bit = ((v_depth - 1u) & 31u); +- if (0u == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1u)) << v_stack_bit))) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2105378u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_expect = 4356u; +- v_expect_after_value = 4356u; +- } else { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2113570u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- v_expect = 4164u; +- v_expect_after_value = 4164u; +- } +- goto label__outer__continue; +- } else if (v_class == 9u) { +- v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src, 111546413966853u); +- if (v_match == 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(8388612u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(5u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (((uint64_t)(io2_a_src - iop_a_src)) < 5u) { +- status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- iop_a_src += 5u; +- break; +- } else if (v_match == 1u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(19); +- goto label__outer__continue; +- } +- } else if (v_class == 10u) { +- v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src, 435762131972u); +- if (v_match == 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(8388616u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { +- status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- iop_a_src += 4u; +- break; +- } else if (v_match == 1u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(20); +- goto label__outer__continue; +- } +- } else if (v_class == 11u) { +- v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src, 465676103172u); +- if (v_match == 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(8388610u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { +- status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- iop_a_src += 4u; +- break; +- } else if (v_match == 1u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(21); +- goto label__outer__continue; +- } +- if (self->private_impl.f_quirks[14u]) { +- 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(22); +- status = wuffs_json__decoder__decode_inf_nan(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; +- } +- break; +- } +- } else if (v_class == 12u) { +- if (self->private_impl.f_quirks[11u] || self->private_impl.f_quirks[12u]) { +- 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(23); +- status = wuffs_json__decoder__decode_comment(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; +- } +- if (self->private_impl.f_comment_type > 0u) { +- goto label__outer__continue; ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)); + } + } ++ self->private_impl.f_dict_id_want = t_1; + } +- status = wuffs_base__make_status(wuffs_json__error__bad_input); ++ status = wuffs_base__make_status(wuffs_zlib__note__dictionary_required); ++ goto ok; ++ } else if (self->private_impl.f_got_dictionary) { ++ status = wuffs_base__make_status(wuffs_zlib__error__incorrect_dictionary); + goto exit; + } +- if (v_depth == 0u) { +- break; ++ } else if (self->private_impl.f_dict_id_have != self->private_impl.f_dict_id_want) { ++ if (self->private_impl.f_got_dictionary) { ++ status = wuffs_base__make_status(wuffs_zlib__error__incorrect_dictionary); ++ goto exit; + } +- v_expect = v_expect_after_value; ++ status = wuffs_base__make_status(wuffs_zlib__note__dictionary_required); ++ goto ok; + } +- label__outer__break:; +- if (self->private_impl.f_quirks[17u] || self->private_impl.f_quirks[18u]) { +- if (a_dst) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ self->private_impl.f_header_complete = true; ++ while (true) { ++ v_mark = ((uint64_t)(iop_a_dst - io0_a_dst)); ++ { ++ 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__status t_2 = wuffs_deflate__decoder__transform_io(&self->private_data.f_flate, a_dst, a_src, a_workbuf); ++ v_status = t_2; ++ 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 (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ if ( ! self->private_impl.f_ignore_checksum && ! self->private_impl.f_quirks[0u]) { ++ v_checksum_have = wuffs_adler32__hasher__update_u32(&self->private_data.f_checksum, wuffs_private_impl__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24); +- status = wuffs_json__decoder__decode_trailer(self, a_dst, a_src); +- if (a_dst) { +- iop_a_dst = a_dst->data.ptr + a_dst->meta.wi; ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; + } +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ } ++ if ( ! self->private_impl.f_quirks[0u]) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); ++ if (num_bits_3 == 24) { ++ t_3 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)); ++ } ++ } ++ v_checksum_want = t_3; + } +- if (status.repr) { +- goto suspend; ++ if ( ! self->private_impl.f_ignore_checksum && (v_checksum_have != v_checksum_want)) { ++ status = wuffs_base__make_status(wuffs_zlib__error__bad_checksum); ++ goto exit; + } + } +- self->private_impl.f_end_of_data = true; + +- ok: +- self->private_impl.p_decode_tokens[0] = 0; +- goto exit; +- } ++ ok: ++ self->private_impl.p_do_transform_io = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_transform_io.v_checksum_have = v_checksum_have; ++ ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_png__error__bad_animation_sequence_number[] = "#png: bad animation sequence number"; ++const char wuffs_png__error__bad_checksum[] = "#png: bad checksum"; ++const char wuffs_png__error__bad_chunk[] = "#png: bad chunk"; ++const char wuffs_png__error__bad_filter[] = "#png: bad filter"; ++const char wuffs_png__error__bad_header[] = "#png: bad header"; ++const char wuffs_png__error__bad_text_chunk_not_latin_1[] = "#png: bad text chunk (not Latin-1)"; ++const char wuffs_png__error__missing_palette[] = "#png: missing palette"; ++const char wuffs_png__error__truncated_input[] = "#png: truncated input"; ++const char wuffs_png__error__unsupported_cgbi_extension[] = "#png: unsupported CgBI extension"; ++const char wuffs_png__error__unsupported_png_compression_method[] = "#png: unsupported PNG compression method"; ++const char wuffs_png__error__unsupported_png_file[] = "#png: unsupported PNG file"; ++const char wuffs_png__error__internal_error_inconsistent_i_o[] = "#png: internal error: inconsistent I/O"; ++const char wuffs_png__error__internal_error_inconsistent_chunk_type[] = "#png: internal error: inconsistent chunk type"; ++const char wuffs_png__error__internal_error_inconsistent_workbuf_length[] = "#png: internal error: inconsistent workbuf length"; ++const char wuffs_png__error__internal_error_zlib_decoder_did_not_exhaust_its_input[] = "#png: internal error: zlib decoder did not exhaust its input"; ++ ++// ---------------- Private Consts ++ ++#define WUFFS_PNG__ANCILLARY_BIT 32u ++ ++static const uint8_t ++WUFFS_PNG__INTERLACING[8][6] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ { ++ 0u, 0u, 0u, 0u, 0u, 0u, ++ }, { ++ 3u, 7u, 0u, 3u, 7u, 0u, ++ }, { ++ 3u, 3u, 4u, 3u, 7u, 0u, ++ }, { ++ 2u, 3u, 0u, 3u, 3u, 4u, ++ }, { ++ 2u, 1u, 2u, 2u, 3u, 0u, ++ }, { ++ 1u, 1u, 0u, 2u, 1u, 2u, ++ }, { ++ 1u, 0u, 1u, 1u, 1u, 0u, ++ }, { ++ 0u, 0u, 0u, 1u, 0u, 1u, ++ }, ++}; ++ ++static const uint8_t ++WUFFS_PNG__LOW_BIT_DEPTH_MULTIPLIERS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 255u, 85u, 0u, 17u, 0u, 0u, 0u, ++}; ++ ++static const uint8_t ++WUFFS_PNG__LOW_BIT_DEPTH_NUM_PACKS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 8u, 4u, 0u, 2u, 0u, 0u, 0u, ++}; ++ ++static const uint8_t ++WUFFS_PNG__NUM_CHANNELS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1u, 0u, 3u, 1u, 2u, 0u, 4u, 0u, ++}; ++ ++static const uint16_t ++WUFFS_PNG__LATIN_1[256] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, ++ 40u, 41u, 42u, 43u, 44u, 45u, 46u, 47u, ++ 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, ++ 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, ++ 64u, 65u, 66u, 67u, 68u, 69u, 70u, 71u, ++ 72u, 73u, 74u, 75u, 76u, 77u, 78u, 79u, ++ 80u, 81u, 82u, 83u, 84u, 85u, 86u, 87u, ++ 88u, 89u, 90u, 91u, 92u, 93u, 94u, 95u, ++ 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, ++ 104u, 105u, 106u, 107u, 108u, 109u, 110u, 111u, ++ 112u, 113u, 114u, 115u, 116u, 117u, 118u, 119u, ++ 120u, 121u, 122u, 123u, 124u, 125u, 126u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 41410u, 41666u, 41922u, 42178u, 42434u, 42690u, 42946u, ++ 43202u, 43458u, 43714u, 43970u, 44226u, 44482u, 44738u, 44994u, ++ 45250u, 45506u, 45762u, 46018u, 46274u, 46530u, 46786u, 47042u, ++ 47298u, 47554u, 47810u, 48066u, 48322u, 48578u, 48834u, 49090u, ++ 32963u, 33219u, 33475u, 33731u, 33987u, 34243u, 34499u, 34755u, ++ 35011u, 35267u, 35523u, 35779u, 36035u, 36291u, 36547u, 36803u, ++ 37059u, 37315u, 37571u, 37827u, 38083u, 38339u, 38595u, 38851u, ++ 39107u, 39363u, 39619u, 39875u, 40131u, 40387u, 40643u, 40899u, ++ 41155u, 41411u, 41667u, 41923u, 42179u, 42435u, 42691u, 42947u, ++ 43203u, 43459u, 43715u, 43971u, 44227u, 44483u, 44739u, 44995u, ++ 45251u, 45507u, 45763u, 46019u, 46275u, 46531u, 46787u, 47043u, ++ 47299u, 47555u, 47811u, 48067u, 48323u, 48579u, 48835u, 49091u, ++}; ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1_distance_4_arm_neon( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3_distance_4_arm_neon( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_3_arm_neon( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_4_arm_neon( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1__choosy_default( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1_distance_3_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1_distance_4_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_2( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + +- goto suspend; +- suspend: +- self->private_impl.p_decode_tokens[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; +- self->private_data.s_decode_tokens[0].v_depth = v_depth; +- self->private_data.s_decode_tokens[0].v_expect = v_expect; +- self->private_data.s_decode_tokens[0].v_expect_after_value = v_expect_after_value; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + +- goto exit; +- exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3__choosy_default( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3_distance_3_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + +-// -------- func json.decoder.decode_number ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3_distance_4_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + + WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_json__decoder__decode_number( +- wuffs_json__decoder* self, +- wuffs_base__io_buffer* a_src) { +- uint8_t v_c = 0; +- uint32_t v_n = 0; +- uint32_t v_floating_point = 0; ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4__choosy_default( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + +- do { +- v_n = 0u; +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if ( ! (a_src && a_src->meta.closed)) { +- v_n |= 768u; +- } +- break; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if (v_c != 45u) { +- } else { +- v_n += 1u; +- iop_a_src += 1u; +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if ( ! (a_src && a_src->meta.closed)) { +- v_n |= 768u; +- } +- v_n |= 256u; +- break; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- } +- if (v_c == 48u) { +- v_n += 1u; +- iop_a_src += 1u; +- } else { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (v_n > 99u) { +- break; +- } +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if ( ! (a_src && a_src->meta.closed)) { +- v_n |= 768u; +- } +- break; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if (v_c != 46u) { +- } else { +- if (v_n >= 99u) { +- v_n |= 512u; +- break; +- } +- v_n += 1u; +- iop_a_src += 1u; +- v_floating_point = 128u; +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (v_n > 99u) { +- break; +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if ( ! (a_src && a_src->meta.closed)) { +- v_n |= 768u; +- } +- break; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- } +- if ((v_c != 69u) && (v_c != 101u)) { +- break; +- } +- if (v_n >= 99u) { +- v_n |= 512u; +- break; +- } +- v_n += 1u; +- iop_a_src += 1u; +- v_floating_point = 128u; +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if ( ! (a_src && a_src->meta.closed)) { +- v_n |= 768u; +- } +- v_n |= 256u; +- break; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if ((v_c != 43u) && (v_c != 45u)) { +- } else { +- if (v_n >= 99u) { +- v_n |= 512u; +- break; +- } +- v_n += 1u; +- iop_a_src += 1u; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } while (0); +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- return (v_n | v_floating_point); +-} ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_3_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + +-// -------- func json.decoder.decode_digits ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_4_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) + WUFFS_BASE__GENERATED_C_CODE +-static uint32_t +-wuffs_json__decoder__decode_digits( +- wuffs_json__decoder* self, ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1_distance_4_x86_sse42( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3_distance_4_x86_sse42( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_3_x86_sse42( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_4_x86_sse42( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev); ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__do_decode_image_config( ++ wuffs_png__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_ihdr( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__assign_filter_distance( ++ wuffs_png__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint64_t ++wuffs_png__decoder__calculate_bytes_per_row( ++ const wuffs_png__decoder* self, ++ uint32_t a_width); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__choose_filter_implementations( ++ wuffs_png__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_other_chunk( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src, +- uint32_t a_n) { +- uint8_t v_c = 0; +- uint32_t v_n = 0; ++ bool a_framy); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_actl( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_chrm( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_exif( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_fctl( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_gama( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_iccp( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_plte( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_srgb( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_trns( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__do_decode_frame_config( ++ wuffs_png__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__skip_frame( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__do_decode_frame( ++ wuffs_png__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__decode_pass( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__do_tell_me_more( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__filter_and_swizzle( ++ wuffs_png__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__filter_and_swizzle__choosy_default( ++ wuffs_png__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__filter_and_swizzle_tricky( ++ wuffs_png__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf); ++ ++// ---------------- VTables ++ ++const wuffs_base__image_decoder__func_ptrs ++wuffs_png__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_png__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_png__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_png__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_png__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_png__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_png__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_png__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_png__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_png__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_png__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_png__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_png__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_png__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_png__decoder__initialize( ++ wuffs_png__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); + } + +- v_n = a_n; +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if ( ! (a_src && a_src->meta.closed)) { +- v_n |= 768u; +- } +- break; ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); + } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if (0u == WUFFS_JSON__LUT_DECIMAL_DIGITS[v_c]) { +- break; ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); + } +- if (v_n >= 99u) { +- v_n |= 512u; +- break; ++ } ++ ++ self->private_impl.choosy_filter_1 = &wuffs_png__decoder__filter_1__choosy_default; ++ self->private_impl.choosy_filter_3 = &wuffs_png__decoder__filter_3__choosy_default; ++ self->private_impl.choosy_filter_4 = &wuffs_png__decoder__filter_4__choosy_default; ++ self->private_impl.choosy_filter_and_swizzle = &wuffs_png__decoder__filter_and_swizzle__choosy_default; ++ ++ { ++ wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize( ++ &self->private_data.f_crc32, sizeof(self->private_data.f_crc32), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; + } +- v_n += 1u; +- iop_a_src += 1u; + } +- if (v_n == a_n) { +- v_n |= 256u; ++ { ++ wuffs_base__status z = wuffs_zlib__decoder__initialize( ++ &self->private_data.f_zlib, sizeof(self->private_data.f_zlib), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } + } +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_png__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_png__decoder* ++wuffs_png__decoder__alloc(void) { ++ wuffs_png__decoder* x = ++ (wuffs_png__decoder*)(calloc(1, sizeof(wuffs_png__decoder))); ++ if (!x) { ++ return NULL; + } +- return v_n; ++ if (wuffs_png__decoder__initialize( ++ x, sizeof(wuffs_png__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_png__decoder(void) { ++ return sizeof(wuffs_png__decoder); + } + +-// -------- func json.decoder.decode_leading ++// ---------------- Function Implementations + +-WUFFS_BASE__GENERATED_C_CODE +-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); ++// ‼ WUFFS MULTI-FILE SECTION +arm_neon ++// -------- func png.decoder.filter_1_distance_4_arm_neon + +- uint8_t v_c = 0; +- uint32_t v_u = 0; ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1_distance_4_arm_neon( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ uint8x8_t v_fa = {0}; ++ uint8x8_t v_fx = {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 && a_dst->data.ptr) { +- 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; ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ v_curr.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, v_fa); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, v_fa); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; + } ++ v_curr.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, v_fa); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ } ++ v_curr.len = 0; + } +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ return wuffs_base__make_empty_struct(); ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++// ‼ WUFFS MULTI-FILE SECTION -arm_neon + +- uint32_t coro_susp_point = self->private_impl.p_decode_leading[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++// ‼ WUFFS MULTI-FILE SECTION +arm_neon ++// -------- func png.decoder.filter_3_distance_4_arm_neon + +- self->private_impl.f_allow_leading_ars = self->private_impl.f_quirks[15u]; +- self->private_impl.f_allow_leading_ubom = self->private_impl.f_quirks[16u]; +- while (self->private_impl.f_allow_leading_ars || self->private_impl.f_allow_leading_ubom) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- continue; ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3_distance_4_arm_neon( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ uint8x8_t v_fa = {0}; ++ uint8x8_t v_fb = {0}; ++ uint8x8_t v_fx = {0}; ++ ++ if (((uint64_t)(a_prev.len)) == 0u) { ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ v_curr.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; + } +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_src && a_src->meta.closed) { +- break; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- continue; ++ v_curr.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; + } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if ((v_c == 30u) && self->private_impl.f_allow_leading_ars) { +- self->private_impl.f_allow_leading_ars = false; +- iop_a_src += 1u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- continue; +- } else if ((v_c == 239u) && self->private_impl.f_allow_leading_ubom) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 3u) { +- if (a_src && a_src->meta.closed) { +- break; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- continue; +- } +- v_u = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); +- if (v_u == 12565487u) { +- self->private_impl.f_allow_leading_ubom = false; +- iop_a_src += 3u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(3u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- continue; +- } ++ v_curr.len = 0; ++ } ++ } else { ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; + } +- break; ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ } ++ v_curr.len = 0; ++ v_prev.len = 0; + } +- +- 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->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- +- return status; ++ return wuffs_base__make_empty_struct(); + } ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++// ‼ WUFFS MULTI-FILE SECTION -arm_neon + +-// -------- func json.decoder.decode_comment ++// ‼ WUFFS MULTI-FILE SECTION +arm_neon ++// -------- func png.decoder.filter_4_distance_3_arm_neon + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_json__decoder__decode_comment( +- 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; +- uint16_t v_c2 = 0; +- uint32_t v_length = 0; ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_3_arm_neon( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ uint8x8_t v_fa = {0}; ++ uint8x8_t v_fb = {0}; ++ uint8x8_t v_fc = {0}; ++ uint8x8_t v_fx = {0}; ++ uint16x8_t v_fafb = {0}; ++ uint16x8_t v_fcfc = {0}; ++ uint16x8_t v_pa = {0}; ++ uint16x8_t v_pb = {0}; ++ uint16x8_t v_pc = {0}; ++ uint16x8_t v_cmpab = {0}; ++ uint16x8_t v_cmpac = {0}; ++ uint8x8_t v_picka = {0}; ++ uint8x8_t v_pickb = {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 && a_dst->data.ptr) { +- 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; ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, wuffs_private_impl__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 7, 6)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fafb = vaddl_u8(v_fa, v_fb); ++ v_fcfc = vaddl_u8(v_fc, v_fc); ++ v_pa = vabdl_u8(v_fb, v_fc); ++ v_pb = vabdl_u8(v_fa, v_fc); ++ v_pc = vabdq_u16(v_fafb, v_fcfc); ++ v_cmpab = vcleq_u16(v_pa, v_pb); ++ v_cmpac = vcleq_u16(v_pa, v_pc); ++ v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); ++ v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); ++ v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); ++ wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fc = v_fb; ++ v_fa = v_fx; ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fafb = vaddl_u8(v_fa, v_fb); ++ v_fcfc = vaddl_u8(v_fc, v_fc); ++ v_pa = vabdl_u8(v_fb, v_fc); ++ v_pb = vabdl_u8(v_fa, v_fc); ++ v_pc = vabdq_u16(v_fafb, v_fcfc); ++ v_cmpab = vcleq_u16(v_pa, v_pb); ++ v_cmpac = vcleq_u16(v_pa, v_pc); ++ v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); ++ v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); ++ v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); ++ wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fc = v_fb; ++ v_fa = v_fx; ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; + } ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, wuffs_private_impl__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 4, 3)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fafb = vaddl_u8(v_fa, v_fb); ++ v_fcfc = vaddl_u8(v_fc, v_fc); ++ v_pa = vabdl_u8(v_fb, v_fc); ++ v_pb = vabdl_u8(v_fa, v_fc); ++ v_pc = vabdq_u16(v_fafb, v_fcfc); ++ v_cmpab = vcleq_u16(v_pa, v_pb); ++ v_cmpac = vcleq_u16(v_pa, v_pc); ++ v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); ++ v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); ++ v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); ++ wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fc = v_fb; ++ v_fa = v_fx; ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; ++ } ++ v_curr.len = 3; ++ v_prev.len = 3; ++ const uint8_t* i_end2_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3)); ++ while (v_curr.ptr < i_end2_curr) { ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u24le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u24le__no_bounds_check(v_curr.ptr))); ++ v_fafb = vaddl_u8(v_fa, v_fb); ++ v_fcfc = vaddl_u8(v_fc, v_fc); ++ v_pa = vabdl_u8(v_fb, v_fc); ++ v_pb = vabdl_u8(v_fa, v_fc); ++ v_pc = vabdq_u16(v_fafb, v_fcfc); ++ v_cmpab = vcleq_u16(v_pa, v_pb); ++ v_cmpac = vcleq_u16(v_pa, v_pc); ++ v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); ++ v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); ++ v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); ++ wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; ++ } ++ v_curr.len = 0; ++ v_prev.len = 0; + } +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ return wuffs_base__make_empty_struct(); ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++// ‼ WUFFS MULTI-FILE SECTION -arm_neon + +- uint32_t coro_susp_point = self->private_impl.p_decode_comment[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++// ‼ WUFFS MULTI-FILE SECTION +arm_neon ++// -------- func png.decoder.filter_4_distance_4_arm_neon + +- self->private_impl.f_comment_type = 0u; +- while ((((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) || (((uint64_t)(io2_a_src - iop_a_src)) <= 1u)) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- continue; +- } +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- } +- v_c2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); +- if ((v_c2 == 10799u) && self->private_impl.f_quirks[11u]) { +- iop_a_src += 2u; +- v_length = 2u; +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 1u) { +- if (v_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); +- } +- v_length = 0u; +- continue; +- } +- v_c2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); +- if (v_c2 == 12074u) { +- iop_a_src += 2u; +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)((v_length + 2u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- self->private_impl.f_comment_type = 1u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- iop_a_src += 1u; +- if (v_length >= 65533u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(2u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)((v_length + 1u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); +- } +- v_length = 0u; +- continue; +- } +- v_length += 1u; +- } +- } else if ((v_c2 == 12079u) && self->private_impl.f_quirks[12u]) { +- iop_a_src += 2u; +- v_length = 2u; +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_src && a_src->meta.closed) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- self->private_impl.f_comment_type = 2u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } else if (v_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); +- while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); +- } +- v_length = 0u; +- continue; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if (v_c == 10u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- self->private_impl.f_comment_type = 2u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- iop_a_src += 1u; +- if (v_length >= 65533u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(1u)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) | +- (((uint64_t)((v_length + 1u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); +- } +- v_length = 0u; +- continue; +- } +- v_length += 1u; +- } ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_4_arm_neon( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ uint8x8_t v_fa = {0}; ++ uint8x8_t v_fb = {0}; ++ uint8x8_t v_fc = {0}; ++ uint8x8_t v_fx = {0}; ++ uint16x8_t v_fafb = {0}; ++ uint16x8_t v_fcfc = {0}; ++ uint16x8_t v_pa = {0}; ++ uint16x8_t v_pb = {0}; ++ uint16x8_t v_pc = {0}; ++ uint16x8_t v_cmpab = {0}; ++ uint16x8_t v_cmpac = {0}; ++ uint8x8_t v_picka = {0}; ++ uint8x8_t v_pickb = {0}; ++ ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fafb = vaddl_u8(v_fa, v_fb); ++ v_fcfc = vaddl_u8(v_fc, v_fc); ++ v_pa = vabdl_u8(v_fb, v_fc); ++ v_pb = vabdl_u8(v_fa, v_fc); ++ v_pc = vabdq_u16(v_fafb, v_fcfc); ++ v_cmpab = vcleq_u16(v_pa, v_pb); ++ v_cmpac = vcleq_u16(v_pa, v_pc); ++ v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); ++ v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); ++ v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fc = v_fb; ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fafb = vaddl_u8(v_fa, v_fb); ++ v_fcfc = vaddl_u8(v_fc, v_fc); ++ v_pa = vabdl_u8(v_fb, v_fc); ++ v_pb = vabdl_u8(v_fa, v_fc); ++ v_pc = vabdq_u16(v_fafb, v_fcfc); ++ v_cmpab = vcleq_u16(v_pa, v_pb); ++ v_cmpac = vcleq_u16(v_pa, v_pc); ++ v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); ++ v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); ++ v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fc = v_fb; ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; + } +- +- ok: +- self->private_impl.p_decode_comment[0] = 0; +- goto exit; ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_fafb = vaddl_u8(v_fa, v_fb); ++ v_fcfc = vaddl_u8(v_fc, v_fc); ++ v_pa = vabdl_u8(v_fb, v_fc); ++ v_pb = vabdl_u8(v_fa, v_fc); ++ v_pc = vabdq_u16(v_fafb, v_fcfc); ++ v_cmpab = vcleq_u16(v_pa, v_pb); ++ v_cmpac = vcleq_u16(v_pa, v_pc); ++ v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); ++ v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); ++ v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); ++ v_fc = v_fb; ++ v_fa = v_fx; ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ } ++ v_curr.len = 0; ++ v_prev.len = 0; + } ++ return wuffs_base__make_empty_struct(); ++} ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++// ‼ WUFFS MULTI-FILE SECTION -arm_neon + +- goto suspend; +- suspend: +- self->private_impl.p_decode_comment[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++// -------- func png.decoder.filter_1 + +- goto exit; +- exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr) { ++ return (*self->private_impl.choosy_filter_1)(self, a_curr); ++} + +- return status; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1__choosy_default( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr) { ++ uint64_t v_filter_distance = 0; ++ uint8_t v_fa = 0; ++ uint64_t v_i_start = 0; ++ uint64_t v_i = 0; ++ ++ v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance)); ++ v_i_start = 0u; ++ while (v_i_start < v_filter_distance) { ++ v_fa = 0u; ++ v_i = v_i_start; ++ while (v_i < ((uint64_t)(a_curr.len))) { ++ a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + v_fa)); ++ v_fa = a_curr.ptr[v_i]; ++ v_i += v_filter_distance; ++ } ++ v_i_start += 1u; ++ } ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func json.decoder.decode_inf_nan ++// -------- func png.decoder.filter_1_distance_3_fallback + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_json__decoder__decode_inf_nan( +- 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); +- +- uint32_t v_c4 = 0; +- uint32_t v_neg = 0; ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1_distance_3_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ uint8_t v_fa0 = 0; ++ uint8_t v_fa1 = 0; ++ uint8_t v_fa2 = 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 && a_dst->data.ptr) { +- 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; ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ v_curr.len = 3; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; ++ v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; + } ++ v_curr.len = 3; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; ++ } ++ v_curr.len = 0; + } +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ return wuffs_base__make_empty_struct(); ++} + +- uint32_t coro_susp_point = self->private_impl.p_decode_inf_nan[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++// -------- func png.decoder.filter_1_distance_4_fallback + +- while (true) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- continue; +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 2u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- continue; +- } +- v_c4 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); +- if ((v_c4 | 2105376u) == 6712937u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) > 7u) { +- if ((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) | 2314885530818453536u) == 8751735898823356009u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(10485792u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(8u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 8u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- } else if ( ! (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- continue; +- } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(10485792u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(3u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 3u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } else if ((v_c4 | 2105376u) == 7233902u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(10485888u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(3u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 3u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } else if ((v_c4 & 255u) == 43u) { +- v_neg = 0u; +- } else if ((v_c4 & 255u) == 45u) { +- v_neg = 1u; +- } else { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 3u) { +- if (a_src && a_src->meta.closed) { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); +- continue; +- } +- v_c4 = (wuffs_base__peek_u32le__no_bounds_check(iop_a_src) >> 8u); +- if ((v_c4 | 2105376u) == 6712937u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) > 8u) { +- if ((wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 1u) | 2314885530818453536u) == 8751735898823356009u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((10485760u | (((uint32_t)(32u)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(9u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 9u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- } else if ( ! (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); +- continue; +- } +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((10485760u | (((uint32_t)(32u)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 4u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } else if ((v_c4 | 2105376u) == 7233902u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)((10485760u | (((uint32_t)(128u)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(4u)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- iop_a_src += 4u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto exit; +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1_distance_4_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ uint8_t v_fa0 = 0; ++ uint8_t v_fa1 = 0; ++ uint8_t v_fa2 = 0; ++ uint8_t v_fa3 = 0; + +- ok: +- self->private_impl.p_decode_inf_nan[0] = 0; +- goto exit; ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ v_curr.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_fa3 = ((uint8_t)(v_fa3 + v_curr.ptr[3u])); ++ v_curr.ptr[3u] = v_fa3; ++ v_curr.ptr += 4; ++ } ++ v_curr.len = 0; + } ++ return wuffs_base__make_empty_struct(); ++} + +- goto suspend; +- suspend: +- self->private_impl.p_decode_inf_nan[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++// -------- func png.decoder.filter_2 + +- goto exit; +- exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_2( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ uint64_t v_n = 0; ++ uint64_t v_i = 0; + +- return status; ++ v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len))); ++ v_i = 0u; ++ while (v_i < v_n) { ++ a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + a_prev.ptr[v_i])); ++ v_i += 1u; ++ } ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func json.decoder.decode_trailer ++// -------- func png.decoder.filter_3 + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_json__decoder__decode_trailer( +- 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); ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ return (*self->private_impl.choosy_filter_3)(self, a_curr, a_prev); ++} + +- uint8_t v_c = 0; +- uint32_t v_whitespace_length = 0; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3__choosy_default( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ uint64_t v_filter_distance = 0; ++ uint64_t v_n = 0; ++ uint64_t v_i = 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 && a_dst->data.ptr) { +- 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; ++ v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance)); ++ if (((uint64_t)(a_prev.len)) == 0u) { ++ v_i = v_filter_distance; ++ while (v_i < ((uint64_t)(a_curr.len))) { ++ a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)(a_curr.ptr[(v_i - v_filter_distance)] / 2u)))); ++ v_i += 1u; ++ } ++ } else { ++ v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len))); ++ v_i = 0u; ++ while ((v_i < v_n) && (v_i < v_filter_distance)) { ++ a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)(a_prev.ptr[v_i] / 2u)))); ++ v_i += 1u; ++ } ++ v_i = v_filter_distance; ++ while (v_i < v_n) { ++ a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)(((((uint32_t)(a_curr.ptr[(v_i - v_filter_distance)])) + ((uint32_t)(a_prev.ptr[v_i]))) / 2u))))); ++ v_i += 1u; + } + } +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ return wuffs_base__make_empty_struct(); ++} + +- uint32_t coro_susp_point = self->private_impl.p_decode_trailer[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++// -------- func png.decoder.filter_3_distance_3_fallback + +- if (self->private_impl.f_quirks[18u]) { +- self->private_impl.f_trailer_stop = 10u; +- } else { +- self->private_impl.f_trailer_stop = 0u; +- } +- label__outer__continue:; +- while (true) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- continue; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_3_distance_3_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ uint8_t v_fa0 = 0; ++ uint8_t v_fa1 = 0; ++ uint8_t v_fa2 = 0; ++ ++ if (((uint64_t)(a_prev.len)) == 0u) { ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ v_curr.len = 3; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fa0 = ((uint8_t)(((uint8_t)(v_fa0 / 2u)) + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(((uint8_t)(v_fa1 / 2u)) + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(((uint8_t)(v_fa2 / 2u)) + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; ++ v_fa0 = ((uint8_t)(((uint8_t)(v_fa0 / 2u)) + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(((uint8_t)(v_fa1 / 2u)) + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(((uint8_t)(v_fa2 / 2u)) + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; + } +- v_whitespace_length = 0u; +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (v_whitespace_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } +- if (a_src && a_src->meta.closed) { +- goto label__outer__break; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- goto label__outer__continue; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if (WUFFS_JSON__LUT_CLASSES[v_c] != 0u) { +- if (v_whitespace_length > 0u) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- } +- if (self->private_impl.f_trailer_stop > 0u) { +- status = wuffs_base__make_status(wuffs_json__error__bad_input); +- goto 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)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_json__decoder__decode_comment(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; +- } +- if (self->private_impl.f_comment_type > 0u) { +- goto label__outer__continue; +- } +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- iop_a_src += 1u; +- if ((v_whitespace_length >= 65534u) || (v_c == self->private_impl.f_trailer_stop)) { +- *iop_a_dst++ = wuffs_base__make_token( +- (((uint64_t)(0u)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | +- (((uint64_t)((v_whitespace_length + 1u))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT)); +- if (v_c == self->private_impl.f_trailer_stop) { +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- goto label__outer__continue; +- } +- v_whitespace_length += 1u; ++ v_curr.len = 3; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_fa0 = ((uint8_t)(((uint8_t)(v_fa0 / 2u)) + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(((uint8_t)(v_fa1 / 2u)) + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(((uint8_t)(v_fa2 / 2u)) + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; + } ++ v_curr.len = 0; ++ } ++ } else { ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 3; ++ v_prev.len = 3; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0u]))) / 2u))) + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1u]))) / 2u))) + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2u]))) / 2u))) + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; ++ v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0u]))) / 2u))) + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1u]))) / 2u))) + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2u]))) / 2u))) + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; ++ } ++ v_curr.len = 3; ++ v_prev.len = 3; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0u]))) / 2u))) + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1u]))) / 2u))) + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2u]))) / 2u))) + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; ++ } ++ v_curr.len = 0; ++ v_prev.len = 0; + } +- label__outer__break:; +- +- ok: +- self->private_impl.p_decode_trailer[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_trailer[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- +- return status; ++ return wuffs_base__make_empty_struct(); + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) +- +-// ---------------- Status Codes Implementations +- +-const char wuffs_lzw__error__bad_code[] = "#lzw: bad code"; +-const char wuffs_lzw__error__truncated_input[] = "#lzw: truncated input"; +-const char wuffs_lzw__error__internal_error_inconsistent_i_o[] = "#lzw: internal error: inconsistent I/O"; +- +-// ---------------- Private Consts +- +-#define WUFFS_LZW__QUIRKS_BASE 1348378624 +- +-// ---------------- Private Initializer Prototypes +- +-// ---------------- Private Function Prototypes ++// -------- func png.decoder.filter_3_distance_4_fallback + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_lzw__decoder__read_from( +- wuffs_lzw__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_lzw__decoder__write_to( +- wuffs_lzw__decoder* self, +- wuffs_base__io_buffer* a_dst); +- +-// ---------------- VTables +- +-const wuffs_base__io_transformer__func_ptrs +-wuffs_lzw__decoder__func_ptrs_for__wuffs_base__io_transformer = { +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_lzw__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_lzw__decoder__history_retain_length), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_lzw__decoder__set_quirk), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__slice_u8))(&wuffs_lzw__decoder__transform_io), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_lzw__decoder__workbuf_len), +-}; +- +-// ---------------- Initializer Implementations +- +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_lzw__decoder__initialize( +- wuffs_lzw__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); +- } ++wuffs_png__decoder__filter_3_distance_4_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ uint8_t v_fa0 = 0; ++ uint8_t v_fa1 = 0; ++ uint8_t v_fa2 = 0; ++ uint8_t v_fa3 = 0; + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ if (((uint64_t)(a_prev.len)) == 0u) { ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ v_curr.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fa0 = ((uint8_t)(((uint8_t)(v_fa0 / 2u)) + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(((uint8_t)(v_fa1 / 2u)) + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(((uint8_t)(v_fa2 / 2u)) + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_fa3 = ((uint8_t)(((uint8_t)(v_fa3 / 2u)) + v_curr.ptr[3u])); ++ v_curr.ptr[3u] = v_fa3; ++ v_curr.ptr += 4; ++ } ++ v_curr.len = 0; + } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif + } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0u]))) / 2u))) + v_curr.ptr[0u])); ++ v_curr.ptr[0u] = v_fa0; ++ v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1u]))) / 2u))) + v_curr.ptr[1u])); ++ v_curr.ptr[1u] = v_fa1; ++ v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2u]))) / 2u))) + v_curr.ptr[2u])); ++ v_curr.ptr[2u] = v_fa2; ++ v_fa3 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa3)) + ((uint32_t)(v_prev.ptr[3u]))) / 2u))) + v_curr.ptr[3u])); ++ v_curr.ptr[3u] = v_fa3; ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ } ++ v_curr.len = 0; ++ v_prev.len = 0; + } + } +- +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = +- wuffs_base__io_transformer__vtable_name; +- self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = +- (const void*)(&wuffs_lzw__decoder__func_ptrs_for__wuffs_base__io_transformer); +- return wuffs_base__make_status(NULL); ++ return wuffs_base__make_empty_struct(); + } + +-wuffs_lzw__decoder* +-wuffs_lzw__decoder__alloc(void) { +- wuffs_lzw__decoder* x = +- (wuffs_lzw__decoder*)(calloc(sizeof(wuffs_lzw__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_lzw__decoder__initialize( +- x, sizeof(wuffs_lzw__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; +- } +- return x; +-} ++// -------- func png.decoder.filter_4 + +-size_t +-sizeof__wuffs_lzw__decoder(void) { +- return sizeof(wuffs_lzw__decoder); ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ return (*self->private_impl.choosy_filter_4)(self, a_curr, a_prev); + } + +-// ---------------- Function Implementations +- +-// -------- func lzw.decoder.get_quirk +- + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_lzw__decoder__get_quirk( +- const wuffs_lzw__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4__choosy_default( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ uint64_t v_filter_distance = 0; ++ uint64_t v_n = 0; ++ uint64_t v_i = 0; ++ uint32_t v_fa = 0; ++ uint32_t v_fb = 0; ++ uint32_t v_fc = 0; ++ uint32_t v_pp = 0; ++ uint32_t v_pa = 0; ++ uint32_t v_pb = 0; ++ uint32_t v_pc = 0; + +- if (a_key == 1348378624u) { +- return ((uint64_t)(self->private_impl.f_pending_literal_width_plus_one)); ++ v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance)); ++ v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len))); ++ v_i = 0u; ++ while ((v_i < v_n) && (v_i < v_filter_distance)) { ++ a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + a_prev.ptr[v_i])); ++ v_i += 1u; + } +- return 0u; ++ v_i = v_filter_distance; ++ while (v_i < v_n) { ++ v_fa = ((uint32_t)(a_curr.ptr[(v_i - v_filter_distance)])); ++ v_fb = ((uint32_t)(a_prev.ptr[v_i])); ++ v_fc = ((uint32_t)(a_prev.ptr[(v_i - v_filter_distance)])); ++ v_pp = ((uint32_t)(((uint32_t)(v_fa + v_fb)) - v_fc)); ++ v_pa = ((uint32_t)(v_pp - v_fa)); ++ if (v_pa >= 2147483648u) { ++ v_pa = ((uint32_t)(0u - v_pa)); ++ } ++ v_pb = ((uint32_t)(v_pp - v_fb)); ++ if (v_pb >= 2147483648u) { ++ v_pb = ((uint32_t)(0u - v_pb)); ++ } ++ v_pc = ((uint32_t)(v_pp - v_fc)); ++ if (v_pc >= 2147483648u) { ++ v_pc = ((uint32_t)(0u - v_pc)); ++ } ++ if ((v_pa <= v_pb) && (v_pa <= v_pc)) { ++ } else if (v_pb <= v_pc) { ++ v_fa = v_fb; ++ } else { ++ v_fa = v_fc; ++ } ++ a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)(v_fa)))); ++ v_i += 1u; ++ } ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func lzw.decoder.set_quirk ++// -------- func png.decoder.filter_4_distance_3_fallback + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_lzw__decoder__set_quirk( +- wuffs_lzw__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_3_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ uint32_t v_fa0 = 0; ++ uint32_t v_fa1 = 0; ++ uint32_t v_fa2 = 0; ++ uint32_t v_fb0 = 0; ++ uint32_t v_fb1 = 0; ++ uint32_t v_fb2 = 0; ++ uint32_t v_fc0 = 0; ++ uint32_t v_fc1 = 0; ++ uint32_t v_fc2 = 0; ++ uint32_t v_pp0 = 0; ++ uint32_t v_pp1 = 0; ++ uint32_t v_pp2 = 0; ++ uint32_t v_pa0 = 0; ++ uint32_t v_pa1 = 0; ++ uint32_t v_pa2 = 0; ++ uint32_t v_pb0 = 0; ++ uint32_t v_pb1 = 0; ++ uint32_t v_pb2 = 0; ++ uint32_t v_pc0 = 0; ++ uint32_t v_pc1 = 0; ++ uint32_t v_pc2 = 0; + +- if (a_key == 1348378624u) { +- if (a_value > 9u) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 3; ++ v_prev.len = 3; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fb0 = ((uint32_t)(v_prev.ptr[0u])); ++ v_pp0 = ((uint32_t)(((uint32_t)(v_fa0 + v_fb0)) - v_fc0)); ++ v_pa0 = ((uint32_t)(v_pp0 - v_fa0)); ++ if (v_pa0 >= 2147483648u) { ++ v_pa0 = ((uint32_t)(0u - v_pa0)); ++ } ++ v_pb0 = ((uint32_t)(v_pp0 - v_fb0)); ++ if (v_pb0 >= 2147483648u) { ++ v_pb0 = ((uint32_t)(0u - v_pb0)); ++ } ++ v_pc0 = ((uint32_t)(v_pp0 - v_fc0)); ++ if (v_pc0 >= 2147483648u) { ++ v_pc0 = ((uint32_t)(0u - v_pc0)); ++ } ++ if ((v_pa0 <= v_pb0) && (v_pa0 <= v_pc0)) { ++ } else if (v_pb0 <= v_pc0) { ++ v_fa0 = v_fb0; ++ } else { ++ v_fa0 = v_fc0; ++ } ++ v_curr.ptr[0u] = ((uint8_t)(v_curr.ptr[0u] + ((uint8_t)(v_fa0)))); ++ v_fa0 = ((uint32_t)(v_curr.ptr[0u])); ++ v_fc0 = v_fb0; ++ v_fb1 = ((uint32_t)(v_prev.ptr[1u])); ++ v_pp1 = ((uint32_t)(((uint32_t)(v_fa1 + v_fb1)) - v_fc1)); ++ v_pa1 = ((uint32_t)(v_pp1 - v_fa1)); ++ if (v_pa1 >= 2147483648u) { ++ v_pa1 = ((uint32_t)(0u - v_pa1)); ++ } ++ v_pb1 = ((uint32_t)(v_pp1 - v_fb1)); ++ if (v_pb1 >= 2147483648u) { ++ v_pb1 = ((uint32_t)(0u - v_pb1)); ++ } ++ v_pc1 = ((uint32_t)(v_pp1 - v_fc1)); ++ if (v_pc1 >= 2147483648u) { ++ v_pc1 = ((uint32_t)(0u - v_pc1)); ++ } ++ if ((v_pa1 <= v_pb1) && (v_pa1 <= v_pc1)) { ++ } else if (v_pb1 <= v_pc1) { ++ v_fa1 = v_fb1; ++ } else { ++ v_fa1 = v_fc1; ++ } ++ v_curr.ptr[1u] = ((uint8_t)(v_curr.ptr[1u] + ((uint8_t)(v_fa1)))); ++ v_fa1 = ((uint32_t)(v_curr.ptr[1u])); ++ v_fc1 = v_fb1; ++ v_fb2 = ((uint32_t)(v_prev.ptr[2u])); ++ v_pp2 = ((uint32_t)(((uint32_t)(v_fa2 + v_fb2)) - v_fc2)); ++ v_pa2 = ((uint32_t)(v_pp2 - v_fa2)); ++ if (v_pa2 >= 2147483648u) { ++ v_pa2 = ((uint32_t)(0u - v_pa2)); ++ } ++ v_pb2 = ((uint32_t)(v_pp2 - v_fb2)); ++ if (v_pb2 >= 2147483648u) { ++ v_pb2 = ((uint32_t)(0u - v_pb2)); ++ } ++ v_pc2 = ((uint32_t)(v_pp2 - v_fc2)); ++ if (v_pc2 >= 2147483648u) { ++ v_pc2 = ((uint32_t)(0u - v_pc2)); ++ } ++ if ((v_pa2 <= v_pb2) && (v_pa2 <= v_pc2)) { ++ } else if (v_pb2 <= v_pc2) { ++ v_fa2 = v_fb2; ++ } else { ++ v_fa2 = v_fc2; ++ } ++ v_curr.ptr[2u] = ((uint8_t)(v_curr.ptr[2u] + ((uint8_t)(v_fa2)))); ++ v_fa2 = ((uint32_t)(v_curr.ptr[2u])); ++ v_fc2 = v_fb2; ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; + } +- self->private_impl.f_pending_literal_width_plus_one = ((uint32_t)(a_value)); +- return wuffs_base__make_status(NULL); ++ v_curr.len = 0; ++ v_prev.len = 0; + } +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func lzw.decoder.history_retain_length ++// -------- func png.decoder.filter_4_distance_4_fallback + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_lzw__decoder__history_retain_length( +- const wuffs_lzw__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func lzw.decoder.workbuf_len ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_4_fallback( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ uint32_t v_fa0 = 0; ++ uint32_t v_fa1 = 0; ++ uint32_t v_fa2 = 0; ++ uint32_t v_fa3 = 0; ++ uint32_t v_fb0 = 0; ++ uint32_t v_fb1 = 0; ++ uint32_t v_fb2 = 0; ++ uint32_t v_fb3 = 0; ++ uint32_t v_fc0 = 0; ++ uint32_t v_fc1 = 0; ++ uint32_t v_fc2 = 0; ++ uint32_t v_fc3 = 0; ++ uint32_t v_pp0 = 0; ++ uint32_t v_pp1 = 0; ++ uint32_t v_pp2 = 0; ++ uint32_t v_pp3 = 0; ++ uint32_t v_pa0 = 0; ++ uint32_t v_pa1 = 0; ++ uint32_t v_pa2 = 0; ++ uint32_t v_pa3 = 0; ++ uint32_t v_pb0 = 0; ++ uint32_t v_pb1 = 0; ++ uint32_t v_pb2 = 0; ++ uint32_t v_pb3 = 0; ++ uint32_t v_pc0 = 0; ++ uint32_t v_pc1 = 0; ++ uint32_t v_pc2 = 0; ++ uint32_t v_pc3 = 0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_lzw__decoder__workbuf_len( +- const wuffs_lzw__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_fb0 = ((uint32_t)(v_prev.ptr[0u])); ++ v_pp0 = ((uint32_t)(((uint32_t)(v_fa0 + v_fb0)) - v_fc0)); ++ v_pa0 = ((uint32_t)(v_pp0 - v_fa0)); ++ if (v_pa0 >= 2147483648u) { ++ v_pa0 = ((uint32_t)(0u - v_pa0)); ++ } ++ v_pb0 = ((uint32_t)(v_pp0 - v_fb0)); ++ if (v_pb0 >= 2147483648u) { ++ v_pb0 = ((uint32_t)(0u - v_pb0)); ++ } ++ v_pc0 = ((uint32_t)(v_pp0 - v_fc0)); ++ if (v_pc0 >= 2147483648u) { ++ v_pc0 = ((uint32_t)(0u - v_pc0)); ++ } ++ if ((v_pa0 <= v_pb0) && (v_pa0 <= v_pc0)) { ++ } else if (v_pb0 <= v_pc0) { ++ v_fa0 = v_fb0; ++ } else { ++ v_fa0 = v_fc0; ++ } ++ v_curr.ptr[0u] = ((uint8_t)(v_curr.ptr[0u] + ((uint8_t)(v_fa0)))); ++ v_fa0 = ((uint32_t)(v_curr.ptr[0u])); ++ v_fc0 = v_fb0; ++ v_fb1 = ((uint32_t)(v_prev.ptr[1u])); ++ v_pp1 = ((uint32_t)(((uint32_t)(v_fa1 + v_fb1)) - v_fc1)); ++ v_pa1 = ((uint32_t)(v_pp1 - v_fa1)); ++ if (v_pa1 >= 2147483648u) { ++ v_pa1 = ((uint32_t)(0u - v_pa1)); ++ } ++ v_pb1 = ((uint32_t)(v_pp1 - v_fb1)); ++ if (v_pb1 >= 2147483648u) { ++ v_pb1 = ((uint32_t)(0u - v_pb1)); ++ } ++ v_pc1 = ((uint32_t)(v_pp1 - v_fc1)); ++ if (v_pc1 >= 2147483648u) { ++ v_pc1 = ((uint32_t)(0u - v_pc1)); ++ } ++ if ((v_pa1 <= v_pb1) && (v_pa1 <= v_pc1)) { ++ } else if (v_pb1 <= v_pc1) { ++ v_fa1 = v_fb1; ++ } else { ++ v_fa1 = v_fc1; ++ } ++ v_curr.ptr[1u] = ((uint8_t)(v_curr.ptr[1u] + ((uint8_t)(v_fa1)))); ++ v_fa1 = ((uint32_t)(v_curr.ptr[1u])); ++ v_fc1 = v_fb1; ++ v_fb2 = ((uint32_t)(v_prev.ptr[2u])); ++ v_pp2 = ((uint32_t)(((uint32_t)(v_fa2 + v_fb2)) - v_fc2)); ++ v_pa2 = ((uint32_t)(v_pp2 - v_fa2)); ++ if (v_pa2 >= 2147483648u) { ++ v_pa2 = ((uint32_t)(0u - v_pa2)); ++ } ++ v_pb2 = ((uint32_t)(v_pp2 - v_fb2)); ++ if (v_pb2 >= 2147483648u) { ++ v_pb2 = ((uint32_t)(0u - v_pb2)); ++ } ++ v_pc2 = ((uint32_t)(v_pp2 - v_fc2)); ++ if (v_pc2 >= 2147483648u) { ++ v_pc2 = ((uint32_t)(0u - v_pc2)); ++ } ++ if ((v_pa2 <= v_pb2) && (v_pa2 <= v_pc2)) { ++ } else if (v_pb2 <= v_pc2) { ++ v_fa2 = v_fb2; ++ } else { ++ v_fa2 = v_fc2; ++ } ++ v_curr.ptr[2u] = ((uint8_t)(v_curr.ptr[2u] + ((uint8_t)(v_fa2)))); ++ v_fa2 = ((uint32_t)(v_curr.ptr[2u])); ++ v_fc2 = v_fb2; ++ v_fb3 = ((uint32_t)(v_prev.ptr[3u])); ++ v_pp3 = ((uint32_t)(((uint32_t)(v_fa3 + v_fb3)) - v_fc3)); ++ v_pa3 = ((uint32_t)(v_pp3 - v_fa3)); ++ if (v_pa3 >= 2147483648u) { ++ v_pa3 = ((uint32_t)(0u - v_pa3)); ++ } ++ v_pb3 = ((uint32_t)(v_pp3 - v_fb3)); ++ if (v_pb3 >= 2147483648u) { ++ v_pb3 = ((uint32_t)(0u - v_pb3)); ++ } ++ v_pc3 = ((uint32_t)(v_pp3 - v_fc3)); ++ if (v_pc3 >= 2147483648u) { ++ v_pc3 = ((uint32_t)(0u - v_pc3)); ++ } ++ if ((v_pa3 <= v_pb3) && (v_pa3 <= v_pc3)) { ++ } else if (v_pb3 <= v_pc3) { ++ v_fa3 = v_fb3; ++ } else { ++ v_fa3 = v_fc3; ++ } ++ v_curr.ptr[3u] = ((uint8_t)(v_curr.ptr[3u] + ((uint8_t)(v_fa3)))); ++ v_fa3 = ((uint32_t)(v_curr.ptr[3u])); ++ v_fc3 = v_fb3; ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ } ++ v_curr.len = 0; ++ v_prev.len = 0; + } +- +- return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func lzw.decoder.transform_io ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++// -------- func png.decoder.filter_1_distance_4_x86_sse42 + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_lzw__decoder__transform_io( +- wuffs_lzw__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_i = 0; +- +- uint32_t coro_susp_point = self->private_impl.p_transform_io[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_1_distance_4_x86_sse42( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ __m128i v_x128 = {0}; ++ __m128i v_a128 = {0}; + +- self->private_impl.f_literal_width = 8u; +- if (self->private_impl.f_pending_literal_width_plus_one > 0u) { +- self->private_impl.f_literal_width = (self->private_impl.f_pending_literal_width_plus_one - 1u); +- } +- self->private_impl.f_clear_code = (((uint32_t)(1u)) << self->private_impl.f_literal_width); +- self->private_impl.f_end_code = (self->private_impl.f_clear_code + 1u); +- self->private_impl.f_save_code = self->private_impl.f_end_code; +- self->private_impl.f_prev_code = self->private_impl.f_end_code; +- self->private_impl.f_width = (self->private_impl.f_literal_width + 1u); +- self->private_impl.f_bits = 0u; +- self->private_impl.f_n_bits = 0u; +- self->private_impl.f_output_ri = 0u; +- self->private_impl.f_output_wi = 0u; +- v_i = 0u; +- while (v_i < self->private_impl.f_clear_code) { +- self->private_data.f_lm1s[v_i] = 0u; +- self->private_data.f_suffixes[v_i][0u] = ((uint8_t)(v_i)); +- v_i += 1u; ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ v_curr.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_a128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_a128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; + } +- while (true) { +- wuffs_lzw__decoder__read_from(self, a_src); +- if (self->private_impl.f_output_wi > 0u) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_lzw__decoder__write_to(self, a_dst); +- if (status.repr) { +- goto suspend; +- } +- } +- if (self->private_impl.f_read_from_return_value == 0u) { +- break; +- } else if (self->private_impl.f_read_from_return_value == 1u) { +- continue; +- } else if (self->private_impl.f_read_from_return_value == 2u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- } else if (self->private_impl.f_read_from_return_value == 3u) { +- status = wuffs_base__make_status(wuffs_lzw__error__truncated_input); +- goto exit; +- } else if (self->private_impl.f_read_from_return_value == 4u) { +- status = wuffs_base__make_status(wuffs_lzw__error__bad_code); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_lzw__error__internal_error_inconsistent_i_o); +- goto exit; +- } ++ v_curr.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_a128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; + } +- +- ok: +- self->private_impl.p_transform_io[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; +- +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ v_curr.len = 0; + } +- return status; ++ return wuffs_base__make_empty_struct(); + } ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-// -------- func lzw.decoder.read_from ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++// -------- func png.decoder.filter_3_distance_4_x86_sse42 + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_lzw__decoder__read_from( +- wuffs_lzw__decoder* self, +- wuffs_base__io_buffer* a_src) { +- uint32_t v_clear_code = 0; +- uint32_t v_end_code = 0; +- uint32_t v_save_code = 0; +- uint32_t v_prev_code = 0; +- uint32_t v_width = 0; +- uint32_t v_bits = 0; +- uint32_t v_n_bits = 0; +- uint32_t v_output_wi = 0; +- uint32_t v_code = 0; +- uint32_t v_c = 0; +- uint32_t v_o = 0; +- uint32_t v_steps = 0; +- uint8_t v_first_byte = 0; +- uint16_t v_lm1_b = 0; +- uint16_t v_lm1_a = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++wuffs_png__decoder__filter_3_distance_4_x86_sse42( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ __m128i v_x128 = {0}; ++ __m128i v_a128 = {0}; ++ __m128i v_b128 = {0}; ++ __m128i v_p128 = {0}; ++ __m128i v_k128 = {0}; + +- v_clear_code = self->private_impl.f_clear_code; +- v_end_code = self->private_impl.f_end_code; +- v_save_code = self->private_impl.f_save_code; +- v_prev_code = self->private_impl.f_prev_code; +- v_width = self->private_impl.f_width; +- v_bits = self->private_impl.f_bits; +- v_n_bits = self->private_impl.f_n_bits; +- v_output_wi = self->private_impl.f_output_wi; +- while (true) { +- if (v_n_bits < v_width) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= 4u) { +- v_bits |= ((uint32_t)(wuffs_base__peek_u32le__no_bounds_check(iop_a_src) << v_n_bits)); +- iop_a_src += ((31u - v_n_bits) >> 3u); +- v_n_bits |= 24u; +- } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_src && a_src->meta.closed) { +- self->private_impl.f_read_from_return_value = 3u; +- } else { +- self->private_impl.f_read_from_return_value = 2u; +- } +- break; +- } else { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- if (v_n_bits >= v_width) { +- } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- if (a_src && a_src->meta.closed) { +- self->private_impl.f_read_from_return_value = 3u; +- } else { +- self->private_impl.f_read_from_return_value = 2u; +- } +- break; +- } else { +- v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits); +- iop_a_src += 1u; +- v_n_bits += 8u; +- if (v_n_bits < v_width) { +- self->private_impl.f_read_from_return_value = 5u; +- break; +- } +- } +- } +- } +- v_code = ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_width)); +- v_bits >>= v_width; +- v_n_bits -= v_width; +- if (v_code < v_clear_code) { +- self->private_data.f_output[v_output_wi] = ((uint8_t)(v_code)); +- v_output_wi = ((v_output_wi + 1u) & 8191u); +- if (v_save_code <= 4095u) { +- v_lm1_a = (((uint16_t)(self->private_data.f_lm1s[v_prev_code] + 1u)) & 4095u); +- self->private_data.f_lm1s[v_save_code] = v_lm1_a; +- if ((v_lm1_a % 8u) != 0u) { +- self->private_impl.f_prefixes[v_save_code] = self->private_impl.f_prefixes[v_prev_code]; +- memcpy(self->private_data.f_suffixes[v_save_code],self->private_data.f_suffixes[v_prev_code], sizeof(self->private_data.f_suffixes[v_save_code])); +- self->private_data.f_suffixes[v_save_code][(v_lm1_a % 8u)] = ((uint8_t)(v_code)); +- } else { +- self->private_impl.f_prefixes[v_save_code] = ((uint16_t)(v_prev_code)); +- self->private_data.f_suffixes[v_save_code][0u] = ((uint8_t)(v_code)); +- } +- v_save_code += 1u; +- if (v_width < 12u) { +- v_width += (1u & (v_save_code >> v_width)); +- } +- v_prev_code = v_code; +- } +- } else if (v_code <= v_end_code) { +- if (v_code == v_end_code) { +- self->private_impl.f_read_from_return_value = 0u; +- break; +- } +- v_save_code = v_end_code; +- v_prev_code = v_end_code; +- v_width = (self->private_impl.f_literal_width + 1u); +- } else if (v_code <= v_save_code) { +- v_c = v_code; +- if (v_code == v_save_code) { +- v_c = v_prev_code; +- } +- v_o = ((v_output_wi + (((uint32_t)(self->private_data.f_lm1s[v_c])) & 4294967288u)) & 8191u); +- v_output_wi = ((v_output_wi + 1u + ((uint32_t)(self->private_data.f_lm1s[v_c]))) & 8191u); +- v_steps = (((uint32_t)(self->private_data.f_lm1s[v_c])) >> 3u); +- while (true) { +- memcpy((self->private_data.f_output)+(v_o), (self->private_data.f_suffixes[v_c]), 8u); +- if (v_steps <= 0u) { +- break; +- } +- v_steps -= 1u; +- v_o = (((uint32_t)(v_o - 8u)) & 8191u); +- v_c = ((uint32_t)(self->private_impl.f_prefixes[v_c])); +- } +- v_first_byte = self->private_data.f_suffixes[v_c][0u]; +- if (v_code == v_save_code) { +- self->private_data.f_output[v_output_wi] = v_first_byte; +- v_output_wi = ((v_output_wi + 1u) & 8191u); ++ if (((uint64_t)(a_prev.len)) == 0u) { ++ v_k128 = _mm_set1_epi8((int8_t)(254u)); ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ v_curr.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; ++ v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; + } +- if (v_save_code <= 4095u) { +- v_lm1_b = (((uint16_t)(self->private_data.f_lm1s[v_prev_code] + 1u)) & 4095u); +- self->private_data.f_lm1s[v_save_code] = v_lm1_b; +- if ((v_lm1_b % 8u) != 0u) { +- self->private_impl.f_prefixes[v_save_code] = self->private_impl.f_prefixes[v_prev_code]; +- memcpy(self->private_data.f_suffixes[v_save_code],self->private_data.f_suffixes[v_prev_code], sizeof(self->private_data.f_suffixes[v_save_code])); +- self->private_data.f_suffixes[v_save_code][(v_lm1_b % 8u)] = v_first_byte; +- } else { +- self->private_impl.f_prefixes[v_save_code] = ((uint16_t)(v_prev_code)); +- self->private_data.f_suffixes[v_save_code][0u] = ((uint8_t)(v_first_byte)); +- } +- v_save_code += 1u; +- if (v_width < 12u) { +- v_width += (1u & (v_save_code >> v_width)); +- } +- v_prev_code = v_code; ++ v_curr.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; + } +- } else { +- self->private_impl.f_read_from_return_value = 4u; +- break; +- } +- if (v_output_wi > 4095u) { +- self->private_impl.f_read_from_return_value = 1u; +- break; ++ v_curr.len = 0; + } +- } +- if (self->private_impl.f_read_from_return_value != 2u) { +- while (v_n_bits >= 8u) { +- v_n_bits -= 8u; +- if (iop_a_src > io1_a_src) { +- iop_a_src--; +- } else { +- self->private_impl.f_read_from_return_value = 5u; +- break; ++ } else { ++ v_k128 = _mm_set1_epi8((int8_t)(1u)); ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_p128 = _mm_avg_epu8(v_a128, v_b128); ++ v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128))); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_p128 = _mm_avg_epu8(v_a128, v_b128); ++ v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128))); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ } ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_p128 = _mm_avg_epu8(v_a128, v_b128); ++ v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128))); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; + } ++ v_curr.len = 0; ++ v_prev.len = 0; + } + } +- self->private_impl.f_save_code = v_save_code; +- self->private_impl.f_prev_code = v_prev_code; +- self->private_impl.f_width = v_width; +- self->private_impl.f_bits = v_bits; +- self->private_impl.f_n_bits = v_n_bits; +- self->private_impl.f_output_wi = v_output_wi; +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- + return wuffs_base__make_empty_struct(); + } ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-// -------- func lzw.decoder.write_to ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++// -------- func png.decoder.filter_4_distance_3_x86_sse42 + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_lzw__decoder__write_to( +- wuffs_lzw__decoder* self, +- wuffs_base__io_buffer* a_dst) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__slice_u8 v_s = {0}; +- uint64_t v_n = 0; ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_3_x86_sse42( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ __m128i v_x128 = {0}; ++ __m128i v_a128 = {0}; ++ __m128i v_b128 = {0}; ++ __m128i v_c128 = {0}; ++ __m128i v_p128 = {0}; ++ __m128i v_pa128 = {0}; ++ __m128i v_pb128 = {0}; ++ __m128i v_pc128 = {0}; ++ __m128i v_smallest128 = {0}; ++ __m128i v_z128 = {0}; + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, wuffs_private_impl__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 7, 6)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); ++ v_pa128 = _mm_sub_epi16(v_b128, v_c128); ++ v_pb128 = _mm_sub_epi16(v_a128, v_c128); ++ v_pc128 = _mm_add_epi16(v_pa128, v_pb128); ++ v_pa128 = _mm_abs_epi16(v_pa128); ++ v_pb128 = _mm_abs_epi16(v_pb128); ++ v_pc128 = _mm_abs_epi16(v_pc128); ++ v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); ++ v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ v_c128 = v_b128; ++ v_x128 = _mm_packus_epi16(v_x128, v_x128); ++ wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); ++ v_pa128 = _mm_sub_epi16(v_b128, v_c128); ++ v_pb128 = _mm_sub_epi16(v_a128, v_c128); ++ v_pc128 = _mm_add_epi16(v_pa128, v_pb128); ++ v_pa128 = _mm_abs_epi16(v_pa128); ++ v_pb128 = _mm_abs_epi16(v_pb128); ++ v_pc128 = _mm_abs_epi16(v_pc128); ++ v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); ++ v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ v_c128 = v_b128; ++ v_x128 = _mm_packus_epi16(v_x128, v_x128); ++ wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; + } +- } +- +- uint32_t coro_susp_point = self->private_impl.p_write_to[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (self->private_impl.f_output_wi > 0u) { +- if (self->private_impl.f_output_ri > self->private_impl.f_output_wi) { +- status = wuffs_base__make_status(wuffs_lzw__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- v_s = wuffs_base__make_slice_u8_ij(self->private_data.f_output, +- self->private_impl.f_output_ri, +- self->private_impl.f_output_wi); +- v_n = wuffs_base__io_writer__copy_from_slice(&iop_a_dst, io2_a_dst,v_s); +- if (v_n == ((uint64_t)(v_s.len))) { +- self->private_impl.f_output_ri = 0u; +- self->private_impl.f_output_wi = 0u; +- status = wuffs_base__make_status(NULL); +- goto ok; +- } +- self->private_impl.f_output_ri = (((uint32_t)(self->private_impl.f_output_ri + ((uint32_t)(v_n)))) & 8191u); +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, wuffs_private_impl__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 4, 3)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); ++ v_pa128 = _mm_sub_epi16(v_b128, v_c128); ++ v_pb128 = _mm_sub_epi16(v_a128, v_c128); ++ v_pc128 = _mm_add_epi16(v_pa128, v_pb128); ++ v_pa128 = _mm_abs_epi16(v_pa128); ++ v_pb128 = _mm_abs_epi16(v_pb128); ++ v_pc128 = _mm_abs_epi16(v_pc128); ++ v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); ++ v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ v_c128 = v_b128; ++ v_x128 = _mm_packus_epi16(v_x128, v_x128); ++ wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; + } +- +- ok: +- self->private_impl.p_write_to[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_write_to[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func lzw.decoder.flush +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8 +-wuffs_lzw__decoder__flush( +- wuffs_lzw__decoder* self) { +- if (!self) { +- return wuffs_base__make_slice_u8(NULL, 0); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_slice_u8(NULL, 0); +- } +- +- uint32_t v_ri = 0; +- uint32_t v_wi = 0; +- +- v_ri = self->private_impl.f_output_ri; +- v_wi = self->private_impl.f_output_wi; +- self->private_impl.f_output_ri = 0u; +- self->private_impl.f_output_wi = 0u; +- if (v_ri <= v_wi) { +- return wuffs_base__make_slice_u8_ij(self->private_data.f_output, v_ri, v_wi); ++ v_curr.len = 3; ++ v_prev.len = 3; ++ const uint8_t* i_end2_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3)); ++ while (v_curr.ptr < i_end2_curr) { ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u24le__no_bounds_check(v_prev.ptr))); ++ v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); ++ v_pa128 = _mm_sub_epi16(v_b128, v_c128); ++ v_pb128 = _mm_sub_epi16(v_a128, v_c128); ++ v_pc128 = _mm_add_epi16(v_pa128, v_pb128); ++ v_pa128 = _mm_abs_epi16(v_pa128); ++ v_pb128 = _mm_abs_epi16(v_pb128); ++ v_pc128 = _mm_abs_epi16(v_pc128); ++ v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); ++ v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u24le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_x128 = _mm_packus_epi16(v_x128, v_x128); ++ wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 3; ++ v_prev.ptr += 3; ++ } ++ v_curr.len = 0; ++ v_prev.len = 0; + } +- return wuffs_base__make_slice_u8(self->private_data.f_output, 0); ++ return wuffs_base__make_empty_struct(); + } ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NETPBM) +- +-// ---------------- Status Codes Implementations +- +-const char wuffs_netpbm__error__bad_header[] = "#netpbm: bad header"; +-const char wuffs_netpbm__error__truncated_input[] = "#netpbm: truncated input"; +-const char wuffs_netpbm__error__unsupported_netpbm_file[] = "#netpbm: unsupported Netpbm file"; +-const char wuffs_netpbm__note__internal_note_short_read[] = "@netpbm: internal note: short read"; +- +-// ---------------- Private Consts +- +-// ---------------- Private Initializer Prototypes +- +-// ---------------- Private Function Prototypes +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_netpbm__decoder__do_decode_image_config( +- wuffs_netpbm__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_netpbm__decoder__do_decode_frame_config( +- wuffs_netpbm__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_netpbm__decoder__do_decode_frame( +- wuffs_netpbm__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); ++// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 ++// -------- func png.decoder.filter_4_distance_4_x86_sse42 + ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_netpbm__decoder__swizzle( +- wuffs_netpbm__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src); +- +-// ---------------- VTables +- +-const wuffs_base__image_decoder__func_ptrs +-wuffs_netpbm__decoder__func_ptrs_for__wuffs_base__image_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__pixel_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__pixel_blend, +- wuffs_base__slice_u8, +- wuffs_base__decode_frame_options*))(&wuffs_netpbm__decoder__decode_frame), +- (wuffs_base__status(*)(void*, +- wuffs_base__frame_config*, +- wuffs_base__io_buffer*))(&wuffs_netpbm__decoder__decode_frame_config), +- (wuffs_base__status(*)(void*, +- wuffs_base__image_config*, +- wuffs_base__io_buffer*))(&wuffs_netpbm__decoder__decode_image_config), +- (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_netpbm__decoder__frame_dirty_rect), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_netpbm__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_netpbm__decoder__history_retain_length), +- (uint32_t(*)(const void*))(&wuffs_netpbm__decoder__num_animation_loops), +- (uint64_t(*)(const void*))(&wuffs_netpbm__decoder__num_decoded_frame_configs), +- (uint64_t(*)(const void*))(&wuffs_netpbm__decoder__num_decoded_frames), +- (wuffs_base__status(*)(void*, +- uint64_t, +- uint64_t))(&wuffs_netpbm__decoder__restart_frame), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_netpbm__decoder__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- uint32_t, +- bool))(&wuffs_netpbm__decoder__set_report_metadata), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__more_information*, +- wuffs_base__io_buffer*))(&wuffs_netpbm__decoder__tell_me_more), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_netpbm__decoder__workbuf_len), +-}; +- +-// ---------------- Initializer Implementations +- +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_netpbm__decoder__initialize( +- wuffs_netpbm__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); +- } ++static wuffs_base__empty_struct ++wuffs_png__decoder__filter_4_distance_4_x86_sse42( ++ wuffs_png__decoder* self, ++ wuffs_base__slice_u8 a_curr, ++ wuffs_base__slice_u8 a_prev) { ++ wuffs_base__slice_u8 v_curr = {0}; ++ wuffs_base__slice_u8 v_prev = {0}; ++ __m128i v_x128 = {0}; ++ __m128i v_a128 = {0}; ++ __m128i v_b128 = {0}; ++ __m128i v_c128 = {0}; ++ __m128i v_p128 = {0}; ++ __m128i v_pa128 = {0}; ++ __m128i v_pb128 = {0}; ++ __m128i v_pc128 = {0}; ++ __m128i v_smallest128 = {0}; ++ __m128i v_z128 = {0}; + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ { ++ wuffs_base__slice_u8 i_slice_curr = a_curr; ++ v_curr.ptr = i_slice_curr.ptr; ++ wuffs_base__slice_u8 i_slice_prev = a_prev; ++ v_prev.ptr = i_slice_prev.ptr; ++ i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end0_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8)); ++ while (v_curr.ptr < i_end0_curr) { ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); ++ v_pa128 = _mm_sub_epi16(v_b128, v_c128); ++ v_pb128 = _mm_sub_epi16(v_a128, v_c128); ++ v_pc128 = _mm_add_epi16(v_pa128, v_pb128); ++ v_pa128 = _mm_abs_epi16(v_pa128); ++ v_pb128 = _mm_abs_epi16(v_pb128); ++ v_pc128 = _mm_abs_epi16(v_pc128); ++ v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); ++ v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ v_c128 = v_b128; ++ v_x128 = _mm_packus_epi16(v_x128, v_x128); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); ++ v_pa128 = _mm_sub_epi16(v_b128, v_c128); ++ v_pb128 = _mm_sub_epi16(v_a128, v_c128); ++ v_pc128 = _mm_add_epi16(v_pa128, v_pb128); ++ v_pa128 = _mm_abs_epi16(v_pa128); ++ v_pb128 = _mm_abs_epi16(v_pb128); ++ v_pc128 = _mm_abs_epi16(v_pc128); ++ v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); ++ v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ v_c128 = v_b128; ++ v_x128 = _mm_packus_epi16(v_x128, v_x128); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; + } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ v_curr.len = 4; ++ v_prev.len = 4; ++ const uint8_t* i_end1_curr = wuffs_private_impl__ptr_u8_plus_len(v_curr.ptr, (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4)); ++ while (v_curr.ptr < i_end1_curr) { ++ v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); ++ v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); ++ v_pa128 = _mm_sub_epi16(v_b128, v_c128); ++ v_pb128 = _mm_sub_epi16(v_a128, v_c128); ++ v_pc128 = _mm_add_epi16(v_pa128, v_pb128); ++ v_pa128 = _mm_abs_epi16(v_pa128); ++ v_pb128 = _mm_abs_epi16(v_pb128); ++ v_pc128 = _mm_abs_epi16(v_pc128); ++ v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); ++ v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); ++ v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); ++ v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); ++ v_x128 = _mm_add_epi8(v_x128, v_p128); ++ v_a128 = v_x128; ++ v_c128 = v_b128; ++ v_x128 = _mm_packus_epi16(v_x128, v_x128); ++ wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); ++ v_curr.ptr += 4; ++ v_prev.ptr += 4; + } ++ v_curr.len = 0; ++ v_prev.len = 0; + } +- +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = +- wuffs_base__image_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = +- (const void*)(&wuffs_netpbm__decoder__func_ptrs_for__wuffs_base__image_decoder); +- return wuffs_base__make_status(NULL); +-} +- +-wuffs_netpbm__decoder* +-wuffs_netpbm__decoder__alloc(void) { +- wuffs_netpbm__decoder* x = +- (wuffs_netpbm__decoder*)(calloc(sizeof(wuffs_netpbm__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_netpbm__decoder__initialize( +- x, sizeof(wuffs_netpbm__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; +- } +- return x; +-} +- +-size_t +-sizeof__wuffs_netpbm__decoder(void) { +- return sizeof(wuffs_netpbm__decoder); ++ return wuffs_base__make_empty_struct(); + } ++#endif // defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-// ---------------- Function Implementations +- +-// -------- func netpbm.decoder.get_quirk ++// -------- func png.decoder.get_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_netpbm__decoder__get_quirk( +- const wuffs_netpbm__decoder* self, ++wuffs_png__decoder__get_quirk( ++ const wuffs_png__decoder* self, + uint32_t a_key) { + if (!self) { + return 0; +@@ -49804,15 +62628,18 @@ wuffs_netpbm__decoder__get_quirk( + return 0; + } + ++ if ((a_key == 1u) && self->private_impl.f_ignore_checksum) { ++ return 1u; ++ } + return 0u; + } + +-// -------- func netpbm.decoder.set_quirk ++// -------- func png.decoder.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__set_quirk( +- wuffs_netpbm__decoder* self, ++wuffs_png__decoder__set_quirk( ++ wuffs_png__decoder* self, + uint32_t a_key, + uint64_t a_value) { + if (!self) { +@@ -49825,15 +62652,20 @@ wuffs_netpbm__decoder__set_quirk( + : wuffs_base__error__initialize_not_called); + } + ++ if (a_key == 1u) { ++ self->private_impl.f_ignore_checksum = (a_value > 0u); ++ wuffs_zlib__decoder__set_quirk(&self->private_data.f_zlib, a_key, a_value); ++ return wuffs_base__make_status(NULL); ++ } + return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func netpbm.decoder.decode_image_config ++// -------- func png.decoder.decode_image_config + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__decode_image_config( +- wuffs_netpbm__decoder* self, ++wuffs_png__decoder__decode_image_config( ++ wuffs_png__decoder* self, + wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { + if (!self) { +@@ -49859,53 +62691,364 @@ wuffs_netpbm__decoder__decode_image_config( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_png__decoder__do_decode_image_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_png__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func png.decoder.do_decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__do_decode_image_config( ++ wuffs_png__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint64_t v_magic = 0; ++ uint64_t v_mark = 0; ++ uint32_t v_checksum_have = 0; ++ uint32_t v_checksum_want = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_image_config; ++ if (coro_susp_point) { ++ v_checksum_have = self->private_data.s_do_decode_image_config.v_checksum_have; ++ } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + ++ if (self->private_impl.f_call_sequence != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } else if ( ! self->private_impl.f_seen_ihdr) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint64_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_0 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 56) { ++ t_0 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ v_magic = t_0; ++ } ++ if (v_magic != 727905341920923785u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint64_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_1 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 56) { ++ t_1 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ v_magic = t_1; ++ } ++ if (v_magic != 5927942488114331648u) { ++ if (v_magic == 5278895250759221248u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_cgbi_extension); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); ++ goto exit; ++ } ++ self->private_impl.f_chunk_type_array[0u] = 73u; ++ self->private_impl.f_chunk_type_array[1u] = 72u; ++ self->private_impl.f_chunk_type_array[2u] = 68u; ++ self->private_impl.f_chunk_type_array[3u] = 82u; ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4)); ++ while (true) { ++ v_mark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_2 = wuffs_png__decoder__decode_ihdr(self, a_src); ++ v_status = t_2; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ if ( ! self->private_impl.f_ignore_checksum) { ++ v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_private_impl__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); ++ if (num_bits_3 == 24) { ++ t_3 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)); ++ } ++ } ++ v_checksum_want = t_3; ++ } ++ if ( ! self->private_impl.f_ignore_checksum && (v_checksum_have != v_checksum_want)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_checksum); ++ goto exit; ++ } ++ self->private_impl.f_seen_ihdr = true; ++ } else if (self->private_impl.f_metadata_fourcc != 0u) { ++ self->private_impl.f_call_sequence = 16u; ++ status = wuffs_base__make_status(wuffs_base__note__metadata_reported); ++ goto ok; ++ } + while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 8u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); ++ continue; ++ } ++ self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32u))); ++ if (self->private_impl.f_chunk_type == 1413563465u) { ++ if ( ! self->private_impl.f_seen_actl || self->private_impl.f_seen_fctl) { ++ break; ++ } ++ self->private_impl.f_seen_idat = true; ++ } else if (self->private_impl.f_chunk_type == 1413571686u) { ++ if (self->private_impl.f_seen_idat && self->private_impl.f_seen_fctl) { ++ break; ++ } ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ iop_a_src += 8u; ++ if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32u) == 0u)) { ++ self->private_impl.f_chunk_type_array[0u] = ((uint8_t)((self->private_impl.f_chunk_type >> 0u))); ++ self->private_impl.f_chunk_type_array[1u] = ((uint8_t)((self->private_impl.f_chunk_type >> 8u))); ++ self->private_impl.f_chunk_type_array[2u] = ((uint8_t)((self->private_impl.f_chunk_type >> 16u))); ++ self->private_impl.f_chunk_type_array[3u] = ((uint8_t)((self->private_impl.f_chunk_type >> 24u))); ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4)); ++ } ++ while (true) { ++ v_mark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_4 = wuffs_png__decoder__decode_other_chunk(self, a_src, false); ++ v_status = t_4; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32u) == 0u)) { ++ v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_private_impl__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); ++ } ++ if (self->private_impl.f_metadata_fourcc != 0u) { ++ self->private_impl.f_call_sequence = 16u; ++ status = wuffs_base__make_status(wuffs_base__note__metadata_reported); ++ goto ok; ++ } + { +- wuffs_base__status t_0 = wuffs_netpbm__decoder__do_decode_image_config(self, a_dst, a_src); +- v_status = t_0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ uint32_t t_5; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_5 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); ++ if (num_bits_5 == 24) { ++ t_5 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_5 += 8u; ++ *scratch |= ((uint64_t)(num_bits_5)); ++ } ++ } ++ v_checksum_want = t_5; + } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__truncated_input); ++ if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32u) == 0u) && (v_checksum_have != v_checksum_want)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_checksum); + goto exit; + } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } ++ if ((self->private_impl.f_color_type == 3u) && ! self->private_impl.f_seen_plte) { ++ status = wuffs_base__make_status(wuffs_png__error__missing_palette); ++ goto exit; ++ } ++ self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ self->private_impl.f_first_config_io_position = self->private_impl.f_frame_config_io_position; ++ if (a_dst != NULL) { ++ wuffs_base__image_config__set( ++ a_dst, ++ self->private_impl.f_dst_pixfmt, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ self->private_impl.f_first_config_io_position, ++ ((self->private_impl.f_color_type <= 3u) && ! self->private_impl.f_seen_trns)); ++ } ++ if ( ! self->private_impl.f_seen_actl) { ++ self->private_impl.f_num_animation_frames_value = 1u; ++ self->private_impl.f_first_rect_x0 = 0u; ++ self->private_impl.f_first_rect_y0 = 0u; ++ self->private_impl.f_first_rect_x1 = self->private_impl.f_width; ++ self->private_impl.f_first_rect_y1 = self->private_impl.f_height; ++ self->private_impl.f_first_duration = 0u; ++ self->private_impl.f_first_disposal = 0u; ++ self->private_impl.f_first_overwrite_instead_of_blend = false; ++ } ++ self->private_impl.f_call_sequence = 32u; + + ok: +- self->private_impl.p_decode_image_config[0] = 0; ++ self->private_impl.p_do_decode_image_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_image_config.v_checksum_have = v_checksum_have; + + goto exit; + exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } ++ + return status; + } + +-// -------- func netpbm.decoder.do_decode_image_config ++// -------- func png.decoder.decode_ihdr + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_netpbm__decoder__do_decode_image_config( +- wuffs_netpbm__decoder* self, +- wuffs_base__image_config* a_dst, ++wuffs_png__decoder__decode_ihdr( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint32_t v_n = 0; ++ uint32_t v_a32 = 0; ++ uint8_t v_a8 = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -49918,348 +63061,343 @@ wuffs_netpbm__decoder__do_decode_image_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_ihdr; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_ihdr.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_ihdr.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ } ++ v_a32 = t_0; ++ } ++ if ((v_a32 == 0u) || (v_a32 > 2147483647u)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); ++ goto exit; ++ } else if (v_a32 > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); + goto exit; + } ++ self->private_impl.f_width = v_a32; + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_ihdr.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_ihdr.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)); ++ } ++ } ++ v_a32 = t_1; ++ } ++ if ((v_a32 == 0u) || (v_a32 > 2147483647u)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); ++ goto exit; ++ } else if (v_a32 > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } ++ self->private_impl.f_height = v_a32; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; ++ uint8_t t_2 = *iop_a_src++; ++ v_a8 = t_2; + } +- if (v_c != 80u) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ if (v_a8 > 16u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); + goto exit; + } ++ self->private_impl.f_depth = v_a8; + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; ++ uint8_t t_3 = *iop_a_src++; ++ v_a8 = t_3; + } +- if ((v_c < 49u) || (55u < v_c)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); +- goto exit; +- } else if (v_c == 53u) { +- self->private_impl.f_pixfmt = 536870920u; +- } else if (v_c == 54u) { +- self->private_impl.f_pixfmt = 2684356744u; +- } else { +- status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); ++ if ((v_a8 == 1u) || (v_a8 == 5u) || (v_a8 > 6u)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); + goto exit; + } ++ self->private_impl.f_color_type = v_a8; + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint8_t t_2 = *iop_a_src++; +- v_c = t_2; ++ uint8_t t_4 = *iop_a_src++; ++ v_a8 = t_4; + } +- if (v_c != 10u) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); ++ if (v_a8 != 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method); + goto exit; + } +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_3 = *iop_a_src++; +- v_c = t_3; +- } +- if ((v_c == 32u) || (v_c == 9u)) { +- continue; +- } else if (v_c == 35u) { +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_4 = *iop_a_src++; +- v_c = t_4; +- } +- if (v_c == 10u) { +- break; +- } +- } +- continue; +- } else if ((v_c < 48u) || (57u < v_c)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); +- goto exit; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- self->private_impl.f_width = ((uint32_t)((v_c - 48u))); +- break; ++ uint8_t t_5 = *iop_a_src++; ++ v_a8 = t_5; + } +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_5 = *iop_a_src++; +- v_c = t_5; +- } +- if ((v_c == 32u) || (v_c == 9u)) { +- break; +- } else if ((v_c < 48u) || (57u < v_c)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); +- goto exit; +- } +- v_n = ((10u * self->private_impl.f_width) + ((uint32_t)((v_c - 48u)))); +- if (v_n > 16777215u) { +- status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); +- goto exit; +- } +- self->private_impl.f_width = v_n; ++ if (v_a8 != 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); ++ goto exit; + } +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_6 = *iop_a_src++; +- v_c = t_6; +- } +- if ((v_c == 32u) || (v_c == 9u)) { +- continue; +- } else if (v_c == 35u) { +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_7 = *iop_a_src++; +- v_c = t_7; +- } +- if (v_c == 10u) { +- break; +- } +- } +- continue; +- } else if ((v_c < 48u) || (57u < v_c)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); +- goto exit; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- self->private_impl.f_height = ((uint32_t)((v_c - 48u))); +- break; ++ uint8_t t_6 = *iop_a_src++; ++ v_a8 = t_6; + } +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_8 = *iop_a_src++; +- v_c = t_8; +- } +- if ((v_c == 32u) || (v_c == 9u) || (v_c == 13u)) { +- continue; +- } else if (v_c == 10u) { +- break; +- } else if ((v_c < 48u) || (57u < v_c)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); +- goto exit; +- } +- v_n = ((10u * self->private_impl.f_height) + ((uint32_t)((v_c - 48u)))); +- if (v_n > 16777215u) { +- status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); +- goto exit; +- } +- self->private_impl.f_height = v_n; ++ if (v_a8 == 0u) { ++ self->private_impl.f_interlace_pass = 0u; ++ } else if (v_a8 == 1u) { ++ self->private_impl.f_interlace_pass = 1u; ++ self->private_impl.choosy_filter_and_swizzle = ( ++ &wuffs_png__decoder__filter_and_swizzle_tricky); ++ } else { ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); ++ goto exit; + } +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_9 = *iop_a_src++; +- v_c = t_9; +- } +- if ((v_c == 32u) || (v_c == 9u)) { +- continue; +- } else if (v_c == 35u) { +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_10 = *iop_a_src++; +- v_c = t_10; +- } +- if (v_c == 10u) { +- break; +- } +- } +- continue; +- } else if ((v_c < 48u) || (57u < v_c)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); +- goto exit; +- } +- self->private_impl.f_max_value = ((uint32_t)((v_c - 48u))); +- break; ++ self->private_impl.f_filter_distance = 0u; ++ wuffs_png__decoder__assign_filter_distance(self); ++ if (self->private_impl.f_filter_distance == 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_header); ++ goto exit; + } +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_11 = *iop_a_src++; +- v_c = t_11; +- } +- if ((v_c == 32u) || (v_c == 9u) || (v_c == 13u)) { +- continue; +- } else if (v_c == 10u) { +- break; +- } else if ((v_c < 48u) || (57u < v_c)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__bad_header); +- goto exit; +- } +- v_n = ((10u * self->private_impl.f_max_value) + ((uint32_t)((v_c - 48u)))); +- if (v_n > 16777215u) { +- status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); +- goto exit; ++ self->private_impl.f_overall_workbuf_length = (((uint64_t)(self->private_impl.f_height)) * (1u + wuffs_png__decoder__calculate_bytes_per_row(self, self->private_impl.f_width))); ++ wuffs_png__decoder__choose_filter_implementations(self); ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_ihdr = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_ihdr = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func png.decoder.assign_filter_distance ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__assign_filter_distance( ++ wuffs_png__decoder* self) { ++ if (self->private_impl.f_depth < 8u) { ++ if ((self->private_impl.f_depth != 1u) && (self->private_impl.f_depth != 2u) && (self->private_impl.f_depth != 4u)) { ++ return wuffs_base__make_empty_struct(); ++ } else if (self->private_impl.f_color_type == 0u) { ++ self->private_impl.f_dst_pixfmt = 536870920u; ++ self->private_impl.f_src_pixfmt = 536870920u; ++ } else if (self->private_impl.f_color_type == 3u) { ++ self->private_impl.f_dst_pixfmt = 2198077448u; ++ self->private_impl.f_src_pixfmt = 2198077448u; ++ } else { ++ return wuffs_base__make_empty_struct(); ++ } ++ self->private_impl.f_filter_distance = 1u; ++ self->private_impl.choosy_filter_and_swizzle = ( ++ &wuffs_png__decoder__filter_and_swizzle_tricky); ++ } else if (self->private_impl.f_color_type == 0u) { ++ if (self->private_impl.f_depth == 8u) { ++ self->private_impl.f_dst_pixfmt = 536870920u; ++ self->private_impl.f_src_pixfmt = 536870920u; ++ self->private_impl.f_filter_distance = 1u; ++ } else if (self->private_impl.f_depth == 16u) { ++ if (self->private_impl.f_interlace_pass == 0u) { ++ self->private_impl.f_dst_pixfmt = 536870923u; ++ self->private_impl.f_src_pixfmt = 537919499u; ++ } else { ++ self->private_impl.f_dst_pixfmt = 2164308923u; ++ self->private_impl.f_src_pixfmt = 2164308923u; + } +- self->private_impl.f_max_value = v_n; ++ self->private_impl.f_filter_distance = 2u; + } +- if (self->private_impl.f_max_value != 255u) { +- status = wuffs_base__make_status(wuffs_netpbm__error__unsupported_netpbm_file); +- goto exit; ++ } else if (self->private_impl.f_color_type == 2u) { ++ if (self->private_impl.f_depth == 8u) { ++ self->private_impl.f_dst_pixfmt = 2147485832u; ++ self->private_impl.f_src_pixfmt = 2684356744u; ++ self->private_impl.f_filter_distance = 3u; ++ } else if (self->private_impl.f_depth == 16u) { ++ self->private_impl.f_dst_pixfmt = 2164308923u; ++ self->private_impl.f_src_pixfmt = 2164308923u; ++ self->private_impl.f_filter_distance = 6u; ++ self->private_impl.choosy_filter_and_swizzle = ( ++ &wuffs_png__decoder__filter_and_swizzle_tricky); + } +- self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- if (a_dst != NULL) { +- wuffs_base__image_config__set( +- a_dst, +- self->private_impl.f_pixfmt, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height, +- self->private_impl.f_frame_config_io_position, +- false); ++ } else if (self->private_impl.f_color_type == 3u) { ++ if (self->private_impl.f_depth == 8u) { ++ self->private_impl.f_dst_pixfmt = 2198077448u; ++ self->private_impl.f_src_pixfmt = 2198077448u; ++ self->private_impl.f_filter_distance = 1u; ++ } ++ } else if (self->private_impl.f_color_type == 4u) { ++ if (self->private_impl.f_depth == 8u) { ++ self->private_impl.f_dst_pixfmt = 553648264u; ++ self->private_impl.f_src_pixfmt = 553648264u; ++ self->private_impl.f_filter_distance = 2u; ++ } else if (self->private_impl.f_depth == 16u) { ++ self->private_impl.f_dst_pixfmt = 2164308923u; ++ self->private_impl.f_src_pixfmt = 2164308923u; ++ self->private_impl.f_filter_distance = 4u; ++ self->private_impl.choosy_filter_and_swizzle = ( ++ &wuffs_png__decoder__filter_and_swizzle_tricky); ++ } ++ } else if (self->private_impl.f_color_type == 6u) { ++ if (self->private_impl.f_depth == 8u) { ++ self->private_impl.f_dst_pixfmt = 2164295816u; ++ self->private_impl.f_src_pixfmt = 2701166728u; ++ self->private_impl.f_filter_distance = 4u; ++ } else if (self->private_impl.f_depth == 16u) { ++ self->private_impl.f_dst_pixfmt = 2164308923u; ++ self->private_impl.f_src_pixfmt = 2164308923u; ++ self->private_impl.f_filter_distance = 8u; ++ self->private_impl.choosy_filter_and_swizzle = ( ++ &wuffs_png__decoder__filter_and_swizzle_tricky); + } +- self->private_impl.f_call_sequence = 32u; +- +- goto ok; +- ok: +- self->private_impl.p_do_decode_image_config[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- +- return status; ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func netpbm.decoder.decode_frame_config ++// -------- func png.decoder.calculate_bytes_per_row + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__decode_frame_config( +- wuffs_netpbm__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 2)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_netpbm__decoder__do_decode_frame_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++static uint64_t ++wuffs_png__decoder__calculate_bytes_per_row( ++ const wuffs_png__decoder* self, ++ uint32_t a_width) { ++ uint64_t v_bytes_per_channel = 0; + +- ok: +- self->private_impl.p_decode_frame_config[0] = 0; +- goto exit; ++ if (self->private_impl.f_depth == 1u) { ++ return ((uint64_t)(((a_width + 7u) / 8u))); ++ } else if (self->private_impl.f_depth == 2u) { ++ return ((uint64_t)(((a_width + 3u) / 4u))); ++ } else if (self->private_impl.f_depth == 4u) { ++ return ((uint64_t)(((a_width + 1u) / 2u))); + } ++ v_bytes_per_channel = ((uint64_t)(((uint8_t)(self->private_impl.f_depth >> 3u)))); ++ return (((uint64_t)(a_width)) * v_bytes_per_channel * ((uint64_t)(WUFFS_PNG__NUM_CHANNELS[self->private_impl.f_color_type]))); ++} + +- goto suspend; +- suspend: +- self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++// -------- func png.decoder.choose_filter_implementations + +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_png__decoder__choose_filter_implementations( ++ wuffs_png__decoder* self) { ++ if (self->private_impl.f_filter_distance == 3u) { ++ self->private_impl.choosy_filter_1 = ( ++ &wuffs_png__decoder__filter_1_distance_3_fallback); ++ self->private_impl.choosy_filter_3 = ( ++ &wuffs_png__decoder__filter_3_distance_3_fallback); ++ self->private_impl.choosy_filter_4 = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_4_distance_3_arm_neon : ++#endif ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_4_distance_3_x86_sse42 : ++#endif ++ &wuffs_png__decoder__filter_4_distance_3_fallback); ++ } else if (self->private_impl.f_filter_distance == 4u) { ++ self->private_impl.choosy_filter_1 = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_1_distance_4_arm_neon : ++#endif ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_1_distance_4_x86_sse42 : ++#endif ++ &wuffs_png__decoder__filter_1_distance_4_fallback); ++ self->private_impl.choosy_filter_3 = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_3_distance_4_arm_neon : ++#endif ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_3_distance_4_x86_sse42 : ++#endif ++ &wuffs_png__decoder__filter_3_distance_4_fallback); ++ self->private_impl.choosy_filter_4 = ( ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__ARM_NEON) ++ wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_4_distance_4_arm_neon : ++#endif ++#if defined(WUFFS_PRIVATE_IMPL__CPU_ARCH__X86_64_V2) ++ wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_4_distance_4_x86_sse42 : ++#endif ++ &wuffs_png__decoder__filter_4_distance_4_fallback); + } +- return status; ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func netpbm.decoder.do_decode_frame_config ++// -------- func png.decoder.decode_other_chunk + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_netpbm__decoder__do_decode_frame_config( +- wuffs_netpbm__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { ++wuffs_png__decoder__decode_other_chunk( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ bool a_framy) { + wuffs_base__status status = wuffs_base__make_status(NULL); + + const uint8_t* iop_a_src = NULL; +@@ -50273,62 +63411,218 @@ wuffs_netpbm__decoder__do_decode_frame_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_other_chunk; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence == 32u) { +- } else if (self->private_impl.f_call_sequence < 32u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ if ((self->private_impl.f_chunk_type == 1163152464u) && ! a_framy) { ++ if (self->private_impl.f_seen_plte) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } else if (self->private_impl.f_color_type == 3u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_png__decoder__decode_plte(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if ((self->private_impl.f_color_type == 2u) || (self->private_impl.f_color_type == 6u)) { ++ } else { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_netpbm__decoder__do_decode_image_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ self->private_impl.f_seen_plte = true; ++ } else if ((self->private_impl.f_chunk_type & 32u) == 0u) { ++ if (self->private_impl.f_chunk_type != 1413563465u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; + } +- if (status.repr) { +- goto suspend; ++ } ++ if (self->private_impl.f_chunk_type == 1716082789u) { ++ if (self->private_impl.f_report_metadata_exif) { ++ if (self->private_impl.f_seen_exif) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_png__decoder__decode_exif(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_seen_exif = true; + } +- } else if (self->private_impl.f_call_sequence == 40u) { +- if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_restart); +- goto exit; ++ } else if ((self->private_impl.f_chunk_type == 1951945833u) || (self->private_impl.f_chunk_type == 1951942004u) || (self->private_impl.f_chunk_type == 1951945850u)) { ++ if (self->private_impl.f_report_metadata_kvp) { ++ self->private_impl.f_metadata_flavor = 4u; ++ self->private_impl.f_metadata_fourcc = 1263947851u; ++ self->private_impl.f_metadata_x = 0u; ++ self->private_impl.f_metadata_y = 0u; ++ self->private_impl.f_metadata_z = 0u; ++ } ++ } else if ( ! a_framy) { ++ if (self->private_impl.f_chunk_type == 1280598881u) { ++ if (self->private_impl.f_seen_actl) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_png__decoder__decode_actl(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_seen_actl = true; ++ } else if (self->private_impl.f_chunk_type == 1297238115u) { ++ if (self->private_impl.f_report_metadata_chrm) { ++ if (self->private_impl.f_seen_chrm) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_png__decoder__decode_chrm(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_seen_chrm = true; ++ } ++ } else if (self->private_impl.f_chunk_type == 1280598886u) { ++ if (self->private_impl.f_seen_fctl) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ status = wuffs_png__decoder__decode_fctl(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_seen_fctl = true; ++ } else if (self->private_impl.f_chunk_type == 1095582055u) { ++ if (self->private_impl.f_report_metadata_gama) { ++ if (self->private_impl.f_seen_gama) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ status = wuffs_png__decoder__decode_gama(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_seen_gama = true; ++ } ++ } else if (self->private_impl.f_chunk_type == 1346585449u) { ++ if (self->private_impl.f_report_metadata_iccp) { ++ if (self->private_impl.f_seen_iccp) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ status = wuffs_png__decoder__decode_iccp(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_seen_iccp = true; ++ } ++ } else if (self->private_impl.f_chunk_type == 1111970419u) { ++ if (self->private_impl.f_report_metadata_srgb) { ++ if (self->private_impl.f_seen_srgb) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ status = wuffs_png__decoder__decode_srgb(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_seen_srgb = true; ++ } ++ } else if (self->private_impl.f_chunk_type == 1397641844u) { ++ if (self->private_impl.f_seen_trns || ((self->private_impl.f_color_type == 3u) && ! self->private_impl.f_seen_plte)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } else if (self->private_impl.f_color_type > 3u) { ++ } else { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ status = wuffs_png__decoder__decode_trns(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ self->private_impl.f_seen_trns = true; + } +- } else if (self->private_impl.f_call_sequence == 64u) { +- self->private_impl.f_call_sequence = 96u; +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; + } +- if (a_dst != NULL) { +- wuffs_base__frame_config__set( +- a_dst, +- wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height), +- ((wuffs_base__flicks)(0u)), +- 0u, +- self->private_impl.f_frame_config_io_position, +- 0u, +- false, +- false, +- 0u); ++ if (self->private_impl.f_metadata_fourcc == 0u) { ++ self->private_data.s_decode_other_chunk.scratch = self->private_impl.f_chunk_length; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ if (self->private_data.s_decode_other_chunk.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_decode_other_chunk.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_decode_other_chunk.scratch; + } +- self->private_impl.f_call_sequence = 64u; + ++ goto ok; + ok: +- self->private_impl.p_do_decode_frame_config[0] = 0; ++ self->private_impl.p_decode_other_chunk = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_other_chunk = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +@@ -50339,181 +63633,130 @@ wuffs_netpbm__decoder__do_decode_frame_config( + return status; + } + +-// -------- func netpbm.decoder.decode_frame +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__decode_frame( +- wuffs_netpbm__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 3)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_netpbm__decoder__do_decode_frame(self, +- a_dst, +- a_src, +- a_blend, +- a_workbuf, +- a_opts); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_netpbm__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } +- +- ok: +- self->private_impl.p_decode_frame[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; +- +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} +- +-// -------- func netpbm.decoder.do_decode_frame ++// -------- func png.decoder.decode_actl + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_netpbm__decoder__do_decode_frame( +- wuffs_netpbm__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { ++wuffs_png__decoder__decode_actl( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_actl; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence == 64u) { +- } else if (self->private_impl.f_call_sequence < 64u) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_netpbm__decoder__do_decode_frame_config(self, NULL, a_src); +- if (status.repr) { +- goto suspend; +- } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; ++ if (self->private_impl.f_chunk_length != 8u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } else if (self->private_impl.f_interlace_pass > 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); ++ goto exit; + } +- self->private_impl.f_dst_x = 0u; +- self->private_impl.f_dst_y = 0u; +- v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, +- wuffs_base__pixel_buffer__pixel_format(a_dst), +- wuffs_base__pixel_buffer__palette(a_dst), +- wuffs_base__utility__make_pixel_format(self->private_impl.f_pixfmt), +- wuffs_base__utility__empty_slice_u8(), +- a_blend); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; ++ self->private_impl.f_chunk_length = 0u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_actl.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_actl.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } + } +- goto ok; ++ self->private_impl.f_num_animation_frames_value = t_0; + } +- while (true) { +- v_status = wuffs_netpbm__decoder__swizzle(self, a_dst, a_src); +- if (wuffs_base__status__is_ok(&v_status)) { +- break; +- } else if (v_status.repr != wuffs_netpbm__note__internal_note_short_read) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; ++ if (self->private_impl.f_num_animation_frames_value == 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_actl.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_actl.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)); + } +- goto ok; + } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ self->private_impl.f_num_animation_loops_value = t_1; + } +- self->private_impl.f_call_sequence = 96u; + ++ goto ok; + ok: +- self->private_impl.p_do_decode_frame[0] = 0; ++ self->private_impl.p_decode_actl = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_actl = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ + return status; + } + +-// -------- func netpbm.decoder.swizzle ++// -------- func png.decoder.decode_chrm + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_netpbm__decoder__swizzle( +- wuffs_netpbm__decoder* self, +- wuffs_base__pixel_buffer* a_dst, ++wuffs_png__decoder__decode_chrm( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint32_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_bytes_per_row = 0; +- uint32_t v_src_bytes_per_pixel = 0; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint64_t v_i = 0; +- uint64_t v_j = 0; +- uint64_t v_n = 0; ++ uint64_t v_u = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -50526,543 +63769,337 @@ wuffs_netpbm__decoder__swizzle( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_option); +- goto exit; +- } +- v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); +- v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- while (true) { +- if (self->private_impl.f_dst_x == self->private_impl.f_width) { +- self->private_impl.f_dst_x = 0u; +- self->private_impl.f_dst_y += 1u; +- if (self->private_impl.f_dst_y >= self->private_impl.f_height) { +- break; +- } +- } +- v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); ++ uint32_t coro_susp_point = self->private_impl.p_decode_chrm; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_chunk_length != 32u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; + } +- v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); +- if (v_i >= ((uint64_t)(v_dst.len))) { +- v_src_bytes_per_pixel = 1u; +- if (self->private_impl.f_pixfmt == 2684356744u) { +- v_src_bytes_per_pixel = 3u; +- } +- v_n = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(v_src_bytes_per_pixel))); +- v_n = wuffs_base__u64__min(v_n, ((uint64_t)(((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x))))); +- v_j = v_n; +- while (v_j >= 8u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 8u)))) { +- iop_a_src += (v_src_bytes_per_pixel * 8u); ++ self->private_impl.f_chunk_length = 0u; ++ self->private_impl.f_metadata_flavor = 5u; ++ self->private_impl.f_metadata_fourcc = 1128813133u; ++ self->private_impl.f_metadata_x = 0u; ++ self->private_impl.f_metadata_y = 0u; ++ self->private_impl.f_metadata_z = 0u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint64_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_chrm.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_chrm.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 24) { ++ t_0 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); + } +- v_j -= 8u; + } +- while (v_j > 0u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 1u)))) { +- iop_a_src += (v_src_bytes_per_pixel * 1u); ++ v_u = t_0; ++ } ++ self->private_impl.f_metadata_x |= ((16777215u & v_u) << 0u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint64_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_chrm.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_chrm.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); ++ if (num_bits_1 == 24) { ++ t_1 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)); + } +- v_j -= 1u; + } +- } else { +- v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( +- &self->private_impl.f_swizzler, +- wuffs_base__slice_u8__subslice_i(v_dst, v_i), +- wuffs_base__pixel_buffer__palette(a_dst), +- &iop_a_src, +- io2_a_src); +- } +- if (v_n == 0u) { +- status = wuffs_base__make_status(wuffs_netpbm__note__internal_note_short_read); +- goto ok; ++ v_u = t_1; + } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); +- } +- status = wuffs_base__make_status(NULL); +- goto ok; +- +- ok: +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func netpbm.decoder.frame_dirty_rect +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_netpbm__decoder__frame_dirty_rect( +- const wuffs_netpbm__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- +- return wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height); +-} +- +-// -------- func netpbm.decoder.num_animation_loops +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_netpbm__decoder__num_animation_loops( +- const wuffs_netpbm__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func netpbm.decoder.num_decoded_frame_configs +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_netpbm__decoder__num_decoded_frame_configs( +- const wuffs_netpbm__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- if (self->private_impl.f_call_sequence > 32u) { +- return 1u; +- } +- return 0u; +-} +- +-// -------- func netpbm.decoder.num_decoded_frames +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_netpbm__decoder__num_decoded_frames( +- const wuffs_netpbm__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- if (self->private_impl.f_call_sequence > 64u) { +- return 1u; +- } +- return 0u; +-} +- +-// -------- func netpbm.decoder.restart_frame +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__restart_frame( +- wuffs_netpbm__decoder* self, +- uint64_t a_index, +- uint64_t a_io_position) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- +- if (self->private_impl.f_call_sequence < 32u) { +- return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- } +- if ((a_index != 0u) || (a_io_position != self->private_impl.f_frame_config_io_position)) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- self->private_impl.f_call_sequence = 40u; +- return wuffs_base__make_status(NULL); +-} +- +-// -------- func netpbm.decoder.set_report_metadata +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_netpbm__decoder__set_report_metadata( +- wuffs_netpbm__decoder* self, +- uint32_t a_fourcc, +- bool a_report) { +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func netpbm.decoder.tell_me_more +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_netpbm__decoder__tell_me_more( +- wuffs_netpbm__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 4)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- status = wuffs_base__make_status(wuffs_base__error__no_more_information); +- goto exit; +- +- goto ok; +- ok: +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} +- +-// -------- func netpbm.decoder.history_retain_length +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_netpbm__decoder__history_retain_length( +- const wuffs_netpbm__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func netpbm.decoder.workbuf_len +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_netpbm__decoder__workbuf_len( +- const wuffs_netpbm__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- +- return wuffs_base__utility__make_range_ii_u64(0u, 0u); +-} +- +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NETPBM) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) +- +-// ---------------- Status Codes Implementations +- +-const char wuffs_nie__error__bad_header[] = "#nie: bad header"; +-const char wuffs_nie__error__truncated_input[] = "#nie: truncated input"; +-const char wuffs_nie__error__unsupported_nie_file[] = "#nie: unsupported NIE file"; +-const char wuffs_nie__note__internal_note_short_read[] = "@nie: internal note: short read"; +- +-// ---------------- Private Consts +- +-// ---------------- Private Initializer Prototypes +- +-// ---------------- Private Function Prototypes +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_nie__decoder__do_decode_image_config( +- wuffs_nie__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_nie__decoder__do_decode_frame_config( +- wuffs_nie__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_nie__decoder__do_decode_frame( +- wuffs_nie__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_nie__decoder__swizzle( +- wuffs_nie__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src); +- +-// ---------------- VTables +- +-const wuffs_base__image_decoder__func_ptrs +-wuffs_nie__decoder__func_ptrs_for__wuffs_base__image_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__pixel_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__pixel_blend, +- wuffs_base__slice_u8, +- wuffs_base__decode_frame_options*))(&wuffs_nie__decoder__decode_frame), +- (wuffs_base__status(*)(void*, +- wuffs_base__frame_config*, +- wuffs_base__io_buffer*))(&wuffs_nie__decoder__decode_frame_config), +- (wuffs_base__status(*)(void*, +- wuffs_base__image_config*, +- wuffs_base__io_buffer*))(&wuffs_nie__decoder__decode_image_config), +- (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_nie__decoder__frame_dirty_rect), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_nie__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_nie__decoder__history_retain_length), +- (uint32_t(*)(const void*))(&wuffs_nie__decoder__num_animation_loops), +- (uint64_t(*)(const void*))(&wuffs_nie__decoder__num_decoded_frame_configs), +- (uint64_t(*)(const void*))(&wuffs_nie__decoder__num_decoded_frames), +- (wuffs_base__status(*)(void*, +- uint64_t, +- uint64_t))(&wuffs_nie__decoder__restart_frame), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_nie__decoder__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- uint32_t, +- bool))(&wuffs_nie__decoder__set_report_metadata), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__more_information*, +- wuffs_base__io_buffer*))(&wuffs_nie__decoder__tell_me_more), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_nie__decoder__workbuf_len), +-}; +- +-// ---------------- Initializer Implementations +- +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_nie__decoder__initialize( +- wuffs_nie__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); +- } +- +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ self->private_impl.f_metadata_x |= ((16777215u & v_u) << 24u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint64_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_2 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_chrm.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_chrm.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); ++ if (num_bits_2 == 24) { ++ t_2 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)); ++ } ++ } ++ v_u = t_2; + } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ self->private_impl.f_metadata_x |= ((uint64_t)((16777215u & v_u) << 48u)); ++ self->private_impl.f_metadata_y |= ((16777215u & v_u) >> 16u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ uint64_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_3 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_chrm.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_chrm.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); ++ if (num_bits_3 == 24) { ++ t_3 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)); ++ } ++ } ++ v_u = t_3; + } +- } +- +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = +- wuffs_base__image_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = +- (const void*)(&wuffs_nie__decoder__func_ptrs_for__wuffs_base__image_decoder); +- return wuffs_base__make_status(NULL); +-} +- +-wuffs_nie__decoder* +-wuffs_nie__decoder__alloc(void) { +- wuffs_nie__decoder* x = +- (wuffs_nie__decoder*)(calloc(sizeof(wuffs_nie__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_nie__decoder__initialize( +- x, sizeof(wuffs_nie__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; +- } +- return x; +-} +- +-size_t +-sizeof__wuffs_nie__decoder(void) { +- return sizeof(wuffs_nie__decoder); +-} +- +-// ---------------- Function Implementations +- +-// -------- func nie.decoder.get_quirk ++ self->private_impl.f_metadata_y |= ((16777215u & v_u) << 8u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ uint64_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_4 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_chrm.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_chrm.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); ++ if (num_bits_4 == 24) { ++ t_4 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)); ++ } ++ } ++ v_u = t_4; ++ } ++ self->private_impl.f_metadata_y |= ((16777215u & v_u) << 32u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ uint64_t t_5; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_5 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_chrm.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_chrm.scratch; ++ uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); ++ if (num_bits_5 == 24) { ++ t_5 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_5 += 8u; ++ *scratch |= ((uint64_t)(num_bits_5)); ++ } ++ } ++ v_u = t_5; ++ } ++ self->private_impl.f_metadata_y |= ((uint64_t)((16777215u & v_u) << 56u)); ++ self->private_impl.f_metadata_z |= ((16777215u & v_u) >> 8u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ uint64_t t_6; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_6 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_chrm.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_chrm.scratch; ++ uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6); ++ if (num_bits_6 == 24) { ++ t_6 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_6 += 8u; ++ *scratch |= ((uint64_t)(num_bits_6)); ++ } ++ } ++ v_u = t_6; ++ } ++ self->private_impl.f_metadata_z |= ((16777215u & v_u) << 16u); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ uint64_t t_7; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_7 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_chrm.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_chrm.scratch; ++ uint32_t num_bits_7 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_7); ++ if (num_bits_7 == 24) { ++ t_7 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_7 += 8u; ++ *scratch |= ((uint64_t)(num_bits_7)); ++ } ++ } ++ v_u = t_7; ++ } ++ self->private_impl.f_metadata_z |= ((16777215u & v_u) << 40u); + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_nie__decoder__get_quirk( +- const wuffs_nie__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ goto ok; ++ ok: ++ self->private_impl.p_decode_chrm = 0; ++ goto exit; + } + +- return 0u; +-} +- +-// -------- func nie.decoder.set_quirk ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_chrm = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__set_quirk( +- wuffs_nie__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ return status; + } + +-// -------- func nie.decoder.decode_image_config ++// -------- func png.decoder.decode_exif + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__decode_image_config( +- wuffs_nie__decoder* self, +- wuffs_base__image_config* a_dst, ++static wuffs_base__status ++wuffs_png__decoder__decode_exif( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_nie__decoder__do_decode_image_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_nie__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } + +- ok: +- self->private_impl.p_decode_image_config[0] = 0; ++ if (self->private_impl.f_chunk_length < 4u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); + goto exit; + } ++ self->private_impl.f_metadata_flavor = 3u; ++ self->private_impl.f_metadata_fourcc = 1163413830u; ++ self->private_impl.f_metadata_x = 0u; ++ self->private_impl.f_metadata_y = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ self->private_impl.f_metadata_z = wuffs_base__u64__sat_add(self->private_impl.f_metadata_y, ((uint64_t)(self->private_impl.f_chunk_length))); ++ self->private_impl.f_chunk_length = 0u; + +- goto suspend; +- suspend: +- self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; +- ++ goto ok; ++ ok: + goto exit; + exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } ++ + return status; + } + +-// -------- func nie.decoder.do_decode_image_config ++// -------- func png.decoder.decode_fctl + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_nie__decoder__do_decode_image_config( +- wuffs_nie__decoder* self, +- wuffs_base__image_config* a_dst, ++wuffs_png__decoder__decode_fctl( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_a = 0; ++ uint32_t v_x0 = 0; ++ uint32_t v_y0 = 0; ++ uint32_t v_x1 = 0; ++ uint32_t v_y1 = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -51075,185 +64112,309 @@ wuffs_nie__decoder__do_decode_image_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_fctl; ++ if (coro_susp_point) { ++ v_x0 = self->private_data.s_decode_fctl.v_x0; ++ v_x1 = self->private_data.s_decode_fctl.v_x1; ++ v_y1 = self->private_data.s_decode_fctl.v_y1; ++ } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ if (self->private_impl.f_chunk_length != 26u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); + goto exit; + } ++ self->private_impl.f_chunk_length = 0u; + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); + uint32_t t_0; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); + iop_a_src += 4; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; ++ self->private_data.s_decode_fctl.scratch = 0; + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; ++ uint64_t* scratch = &self->private_data.s_decode_fctl.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); + *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); + if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch)); ++ t_0 = ((uint32_t)(*scratch >> 32)); + break; + } + num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ *scratch |= ((uint64_t)(num_bits_0)); + } + } +- v_a = t_0; ++ v_x0 = t_0; + } +- if (v_a != 1169146734u) { +- status = wuffs_base__make_status(wuffs_nie__error__bad_header); ++ if (v_x0 != self->private_impl.f_next_animation_seq_num) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number); ++ goto exit; ++ } else if (self->private_impl.f_next_animation_seq_num >= 4294967295u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); + goto exit; + } ++ self->private_impl.f_next_animation_seq_num += 1u; + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); + uint32_t t_1; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); + iop_a_src += 4; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; ++ self->private_data.s_decode_fctl.scratch = 0; + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; ++ uint64_t* scratch = &self->private_data.s_decode_fctl.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); + *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); + if (num_bits_1 == 24) { +- t_1 = ((uint32_t)(*scratch)); ++ t_1 = ((uint32_t)(*scratch >> 32)); + break; + } + num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ *scratch |= ((uint64_t)(num_bits_1)); + } + } +- v_a = t_1; +- } +- if (v_a == 879649535u) { +- self->private_impl.f_pixfmt = 2164295816u; +- } else if (v_a == 946758399u) { +- self->private_impl.f_pixfmt = 2164308923u; +- } else if (v_a == 879780607u) { +- status = wuffs_base__make_status(wuffs_nie__error__unsupported_nie_file); +- goto exit; +- } else if (v_a == 946889471u) { +- status = wuffs_base__make_status(wuffs_nie__error__unsupported_nie_file); +- goto exit; +- } else { +- status = wuffs_base__make_status(wuffs_nie__error__bad_header); +- goto exit; ++ v_x1 = t_1; + } + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); + uint32_t t_2; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); + iop_a_src += 4; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; ++ self->private_data.s_decode_fctl.scratch = 0; + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; ++ uint64_t* scratch = &self->private_data.s_decode_fctl.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); + *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); + if (num_bits_2 == 24) { +- t_2 = ((uint32_t)(*scratch)); ++ t_2 = ((uint32_t)(*scratch >> 32)); + break; + } + num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)) << 56; ++ *scratch |= ((uint64_t)(num_bits_2)); + } + } +- v_a = t_2; +- } +- if (v_a > 2147483647u) { +- status = wuffs_base__make_status(wuffs_nie__error__bad_header); +- goto exit; +- } else if (v_a > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; ++ v_y1 = t_2; + } +- self->private_impl.f_width = v_a; + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); + uint32_t t_3; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_3 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); + iop_a_src += 4; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; ++ self->private_data.s_decode_fctl.scratch = 0; + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); ++ uint64_t* scratch = &self->private_data.s_decode_fctl.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); ++ if (num_bits_3 == 24) { ++ t_3 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)); ++ } ++ } ++ v_x0 = t_3; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ uint32_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_4 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_fctl.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_fctl.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); ++ if (num_bits_4 == 24) { ++ t_4 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)); ++ } ++ } ++ v_y0 = t_4; ++ } ++ v_x1 += v_x0; ++ v_y1 += v_y0; ++ if ((v_x0 >= v_x1) || ++ (v_x0 > self->private_impl.f_width) || ++ (v_x1 > self->private_impl.f_width) || ++ (v_y0 >= v_y1) || ++ (v_y0 > self->private_impl.f_height) || ++ (v_y1 > self->private_impl.f_height)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_frame_rect_x0 = v_x0; ++ self->private_impl.f_frame_rect_y0 = v_y0; ++ self->private_impl.f_frame_rect_x1 = v_x1; ++ self->private_impl.f_frame_rect_y1 = v_y1; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ uint32_t t_5; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_5 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_fctl.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_fctl.scratch; ++ uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; + *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); ++ if (num_bits_5 == 8) { ++ t_5 = ((uint32_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_5 += 8u; ++ *scratch |= ((uint64_t)(num_bits_5)); ++ } ++ } ++ v_x0 = t_5; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ uint32_t t_6; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_6 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_fctl.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_fctl.scratch; ++ uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFFu)); + *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; +- if (num_bits_3 == 24) { +- t_3 = ((uint32_t)(*scratch)); ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6); ++ if (num_bits_6 == 8) { ++ t_6 = ((uint32_t)(*scratch >> 48)); + break; + } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ num_bits_6 += 8u; ++ *scratch |= ((uint64_t)(num_bits_6)); + } + } +- v_a = t_3; ++ v_x1 = t_6; + } +- if (v_a > 2147483647u) { +- status = wuffs_base__make_status(wuffs_nie__error__bad_header); ++ if (v_x1 <= 0u) { ++ self->private_impl.f_frame_duration = (((uint64_t)(v_x0)) * 7056000u); ++ } else { ++ self->private_impl.f_frame_duration = ((((uint64_t)(v_x0)) * 705600000u) / ((uint64_t)(v_x1))); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_7 = *iop_a_src++; ++ v_x0 = t_7; ++ } ++ if (v_x0 == 0u) { ++ self->private_impl.f_frame_disposal = 0u; ++ } else if (v_x0 == 1u) { ++ self->private_impl.f_frame_disposal = 1u; ++ } else if (v_x0 == 2u) { ++ self->private_impl.f_frame_disposal = 2u; ++ } else { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); + goto exit; +- } else if (v_a > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_8 = *iop_a_src++; ++ v_x0 = t_8; ++ } ++ if (v_x0 == 0u) { ++ self->private_impl.f_frame_overwrite_instead_of_blend = true; ++ } else if (v_x0 == 1u) { ++ self->private_impl.f_frame_overwrite_instead_of_blend = false; ++ } else { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); + goto exit; + } +- self->private_impl.f_height = v_a; +- if (a_dst != NULL) { +- wuffs_base__image_config__set( +- a_dst, +- self->private_impl.f_pixfmt, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height, +- 16u, +- false); ++ if (self->private_impl.f_num_decoded_frame_configs_value == 0u) { ++ self->private_impl.f_first_rect_x0 = self->private_impl.f_frame_rect_x0; ++ self->private_impl.f_first_rect_y0 = self->private_impl.f_frame_rect_y0; ++ self->private_impl.f_first_rect_x1 = self->private_impl.f_frame_rect_x1; ++ self->private_impl.f_first_rect_y1 = self->private_impl.f_frame_rect_y1; ++ self->private_impl.f_first_duration = self->private_impl.f_frame_duration; ++ self->private_impl.f_first_disposal = self->private_impl.f_frame_disposal; ++ self->private_impl.f_first_overwrite_instead_of_blend = self->private_impl.f_frame_overwrite_instead_of_blend; + } +- self->private_impl.f_call_sequence = 32u; + + goto ok; + ok: +- self->private_impl.p_do_decode_image_config[0] = 0; ++ self->private_impl.p_decode_fctl = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_fctl = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_fctl.v_x0 = v_x0; ++ self->private_data.s_decode_fctl.v_x1 = v_x1; ++ self->private_data.s_decode_fctl.v_y1 = v_y1; + + goto exit; + exit: +@@ -51264,82 +64425,99 @@ wuffs_nie__decoder__do_decode_image_config( + return status; + } + +-// -------- func nie.decoder.decode_frame_config ++// -------- func png.decoder.decode_gama + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__decode_frame_config( +- wuffs_nie__decoder* self, +- wuffs_base__frame_config* a_dst, ++static wuffs_base__status ++wuffs_png__decoder__decode_gama( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 2)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_frame_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_gama; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_nie__decoder__do_decode_frame_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_nie__error__truncated_input); +- goto exit; ++ if (self->private_impl.f_chunk_length != 4u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length = 0u; ++ self->private_impl.f_metadata_flavor = 5u; ++ self->private_impl.f_metadata_fourcc = 1195461953u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint64_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_gama.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_gama.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 24) { ++ t_0 = ((uint64_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } + } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ self->private_impl.f_metadata_x = t_0; + } ++ self->private_impl.f_metadata_y = 0u; ++ self->private_impl.f_metadata_z = 0u; + ++ goto ok; + ok: +- self->private_impl.p_decode_frame_config[0] = 0; ++ self->private_impl.p_decode_gama = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ self->private_impl.p_decode_gama = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } ++ + return status; + } + +-// -------- func nie.decoder.do_decode_frame_config ++// -------- func png.decoder.decode_iccp + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_nie__decoder__do_decode_frame_config( +- wuffs_nie__decoder* self, +- wuffs_base__frame_config* a_dst, ++wuffs_png__decoder__decode_iccp( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + ++ uint8_t v_c8 = 0; ++ + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -51351,62 +64529,63 @@ wuffs_nie__decoder__do_decode_frame_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_iccp; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence == 32u) { +- } else if (self->private_impl.f_call_sequence < 32u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ while (true) { ++ if (self->private_impl.f_chunk_length <= 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_nie__decoder__do_decode_image_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ self->private_impl.f_chunk_length -= 1u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; + } +- if (status.repr) { +- goto suspend; ++ if (v_c8 == 0u) { ++ break; + } +- } else if (self->private_impl.f_call_sequence == 40u) { +- if (16u != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_restart); +- goto exit; ++ } ++ if (self->private_impl.f_chunk_length <= 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length -= 1u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- } else if (self->private_impl.f_call_sequence == 64u) { +- self->private_impl.f_call_sequence = 96u; +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; + } +- if (a_dst != NULL) { +- wuffs_base__frame_config__set( +- a_dst, +- wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height), +- ((wuffs_base__flicks)(0u)), +- 0u, +- 16u, +- 0u, +- false, +- false, +- 0u); ++ if (v_c8 != 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method); ++ goto exit; + } +- self->private_impl.f_call_sequence = 64u; ++ self->private_impl.f_metadata_is_zlib_compressed = true; ++ self->private_impl.f_metadata_flavor = 4u; ++ self->private_impl.f_metadata_fourcc = 1229144912u; ++ self->private_impl.f_metadata_x = 0u; ++ self->private_impl.f_metadata_y = 0u; ++ self->private_impl.f_metadata_z = 0u; + ++ goto ok; + ok: +- self->private_impl.p_do_decode_frame_config[0] = 0; ++ self->private_impl.p_decode_iccp = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_iccp = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +@@ -51417,182 +64596,119 @@ wuffs_nie__decoder__do_decode_frame_config( + return status; + } + +-// -------- func nie.decoder.decode_frame ++// -------- func png.decoder.decode_plte + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__decode_frame( +- wuffs_nie__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 3)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; ++static wuffs_base__status ++wuffs_png__decoder__decode_plte( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_nie__decoder__do_decode_frame(self, +- a_dst, +- a_src, +- a_blend, +- a_workbuf, +- a_opts); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_nie__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++ uint32_t v_num_entries = 0; ++ uint32_t v_i = 0; ++ uint32_t v_argb = 0; + +- ok: +- self->private_impl.p_decode_frame[0] = 0; +- goto exit; ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } + +- goto suspend; +- suspend: +- self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; +- +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ uint32_t coro_susp_point = self->private_impl.p_decode_plte; ++ if (coro_susp_point) { ++ v_num_entries = self->private_data.s_decode_plte.v_num_entries; ++ v_i = self->private_data.s_decode_plte.v_i; + } +- return status; +-} +- +-// -------- func nie.decoder.do_decode_frame +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_nie__decoder__do_decode_frame( +- wuffs_nie__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame[0]; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence == 64u) { +- } else if (self->private_impl.f_call_sequence < 64u) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_nie__decoder__do_decode_frame_config(self, NULL, a_src); +- if (status.repr) { +- goto suspend; +- } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- self->private_impl.f_dst_x = 0u; +- self->private_impl.f_dst_y = 0u; +- v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, +- wuffs_base__pixel_buffer__pixel_format(a_dst), +- wuffs_base__pixel_buffer__palette(a_dst), +- wuffs_base__utility__make_pixel_format(self->private_impl.f_pixfmt), +- wuffs_base__utility__empty_slice_u8(), +- a_blend); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; ++ if ((self->private_impl.f_chunk_length > 768u) || ((self->private_impl.f_chunk_length % 3u) != 0u)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; + } +- while (true) { +- v_status = wuffs_nie__decoder__swizzle(self, a_dst, a_src); +- if (wuffs_base__status__is_ok(&v_status)) { +- break; +- } else if (v_status.repr != wuffs_nie__note__internal_note_short_read) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; ++ v_num_entries = (((uint32_t)(self->private_impl.f_chunk_length)) / 3u); ++ self->private_impl.f_chunk_length = 0u; ++ while (v_i < v_num_entries) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { ++ t_0 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src))); ++ iop_a_src += 3; ++ } else { ++ self->private_data.s_decode_plte.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_plte.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 16) { ++ t_0 = ((uint32_t)(*scratch >> 40)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } + } +- goto ok; ++ v_argb = t_0; + } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ v_argb |= 4278190080u; ++ self->private_data.f_src_palette[((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); ++ self->private_data.f_src_palette[((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); ++ self->private_data.f_src_palette[((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); ++ self->private_data.f_src_palette[((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); ++ v_i += 1u; ++ } ++ while (v_i < 256u) { ++ self->private_data.f_src_palette[((4u * v_i) + 0u)] = 0u; ++ self->private_data.f_src_palette[((4u * v_i) + 1u)] = 0u; ++ self->private_data.f_src_palette[((4u * v_i) + 2u)] = 0u; ++ self->private_data.f_src_palette[((4u * v_i) + 3u)] = 255u; ++ v_i += 1u; + } +- self->private_impl.f_call_sequence = 96u; + ++ goto ok; + ok: +- self->private_impl.p_do_decode_frame[0] = 0; ++ self->private_impl.p_decode_plte = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_plte = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_plte.v_num_entries = v_num_entries; ++ self->private_data.s_decode_plte.v_i = v_i; + + goto exit; + exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ + return status; + } + +-// -------- func nie.decoder.swizzle ++// -------- func png.decoder.decode_srgb + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_nie__decoder__swizzle( +- wuffs_nie__decoder* self, +- wuffs_base__pixel_buffer* a_dst, ++wuffs_png__decoder__decode_srgb( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint32_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_bytes_per_row = 0; +- uint32_t v_src_bytes_per_pixel = 0; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint64_t v_i = 0; +- uint64_t v_j = 0; +- uint64_t v_n = 0; +- + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -51604,66 +64720,39 @@ wuffs_nie__decoder__swizzle( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_option); +- goto exit; +- } +- v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); +- v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- while (true) { +- if (self->private_impl.f_dst_x == self->private_impl.f_width) { +- self->private_impl.f_dst_x = 0u; +- self->private_impl.f_dst_y += 1u; +- if (self->private_impl.f_dst_y >= self->private_impl.f_height) { +- break; +- } +- } +- v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); +- if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); +- } +- v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); +- if (v_i >= ((uint64_t)(v_dst.len))) { +- v_src_bytes_per_pixel = 4u; +- if (self->private_impl.f_pixfmt == 2164308923u) { +- v_src_bytes_per_pixel = 8u; +- } +- v_n = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(v_src_bytes_per_pixel))); +- v_n = wuffs_base__u64__min(v_n, ((uint64_t)(((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x))))); +- v_j = v_n; +- while (v_j >= 8u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 8u)))) { +- iop_a_src += (v_src_bytes_per_pixel * 8u); +- } +- v_j -= 8u; +- } +- while (v_j > 0u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) >= ((uint64_t)((v_src_bytes_per_pixel * 1u)))) { +- iop_a_src += (v_src_bytes_per_pixel * 1u); +- } +- v_j -= 1u; +- } +- } else { +- v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader( +- &self->private_impl.f_swizzler, +- wuffs_base__slice_u8__subslice_i(v_dst, v_i), +- wuffs_base__pixel_buffer__palette(a_dst), +- &iop_a_src, +- io2_a_src); ++ uint32_t coro_susp_point = self->private_impl.p_decode_srgb; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_chunk_length != 1u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; + } +- if (v_n == 0u) { +- status = wuffs_base__make_status(wuffs_nie__note__internal_note_short_read); +- goto ok; ++ self->private_impl.f_chunk_length = 0u; ++ self->private_impl.f_metadata_flavor = 5u; ++ self->private_impl.f_metadata_fourcc = 1397901122u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t t_0 = *iop_a_src++; ++ self->private_impl.f_metadata_x = t_0; + } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(v_n))); ++ self->private_impl.f_metadata_y = 0u; ++ self->private_impl.f_metadata_z = 0u; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_srgb = 0; ++ goto exit; + } +- status = wuffs_base__make_status(NULL); +- goto ok; + +- ok: ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_srgb = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ + goto exit; + exit: + if (a_src && a_src->data.ptr) { +@@ -51673,131 +64762,199 @@ wuffs_nie__decoder__swizzle( + return status; + } + +-// -------- func nie.decoder.frame_dirty_rect +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_nie__decoder__frame_dirty_rect( +- const wuffs_nie__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- +- return wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height); +-} +- +-// -------- func nie.decoder.num_animation_loops ++// -------- func png.decoder.decode_trns + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_nie__decoder__num_animation_loops( +- const wuffs_nie__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} ++static wuffs_base__status ++wuffs_png__decoder__decode_trns( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-// -------- func nie.decoder.num_decoded_frame_configs ++ uint32_t v_i = 0; ++ uint32_t v_n = 0; ++ uint64_t v_u = 0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_nie__decoder__num_decoded_frame_configs( +- const wuffs_nie__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } + +- if (self->private_impl.f_call_sequence > 32u) { +- return 1u; ++ uint32_t coro_susp_point = self->private_impl.p_decode_trns; ++ if (coro_susp_point) { ++ v_i = self->private_data.s_decode_trns.v_i; ++ v_n = self->private_data.s_decode_trns.v_n; + } +- return 0u; +-} +- +-// -------- func nie.decoder.num_decoded_frames ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_nie__decoder__num_decoded_frames( +- const wuffs_nie__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ if (self->private_impl.f_color_type == 0u) { ++ self->private_impl.choosy_filter_and_swizzle = ( ++ &wuffs_png__decoder__filter_and_swizzle_tricky); ++ if (self->private_impl.f_depth <= 8u) { ++ self->private_impl.f_dst_pixfmt = 2164295816u; ++ self->private_impl.f_src_pixfmt = 2164295816u; ++ } else { ++ self->private_impl.f_dst_pixfmt = 2164308923u; ++ self->private_impl.f_src_pixfmt = 2164308923u; ++ } ++ if (self->private_impl.f_chunk_length != 2u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length = 0u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint64_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_0 = ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_decode_trns.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_trns.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 8) { ++ t_0 = ((uint64_t)(*scratch >> 48)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ } ++ v_u = t_0; ++ } ++ if (self->private_impl.f_depth <= 1u) { ++ self->private_impl.f_remap_transparency = (((v_u & 1u) * 16777215u) | 4278190080u); ++ } else if (self->private_impl.f_depth <= 2u) { ++ self->private_impl.f_remap_transparency = (((v_u & 3u) * 5592405u) | 4278190080u); ++ } else if (self->private_impl.f_depth <= 4u) { ++ self->private_impl.f_remap_transparency = (((v_u & 15u) * 1118481u) | 4278190080u); ++ } else if (self->private_impl.f_depth <= 8u) { ++ self->private_impl.f_remap_transparency = (((v_u & 255u) * 65793u) | 4278190080u); ++ } else { ++ self->private_impl.f_remap_transparency = ((v_u * 4295032833u) | 18446462598732840960u); ++ } ++ } else if (self->private_impl.f_color_type == 2u) { ++ self->private_impl.choosy_filter_and_swizzle = ( ++ &wuffs_png__decoder__filter_and_swizzle_tricky); ++ if (self->private_impl.f_depth <= 8u) { ++ self->private_impl.f_dst_pixfmt = 2164295816u; ++ self->private_impl.f_src_pixfmt = 2164295816u; ++ } else { ++ self->private_impl.f_dst_pixfmt = 2164308923u; ++ self->private_impl.f_src_pixfmt = 2164308923u; ++ } ++ if (self->private_impl.f_chunk_length != 6u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length = 0u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint64_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 6)) { ++ t_1 = ((uint64_t)(wuffs_base__peek_u48be__no_bounds_check(iop_a_src))); ++ iop_a_src += 6; ++ } else { ++ self->private_data.s_decode_trns.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_trns.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); ++ if (num_bits_1 == 40) { ++ t_1 = ((uint64_t)(*scratch >> 16)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)); ++ } ++ } ++ v_u = t_1; ++ } ++ if (self->private_impl.f_depth <= 8u) { ++ self->private_impl.f_remap_transparency = ((255u & (v_u >> 0u)) | ++ (65280u & (v_u >> 8u)) | ++ (16711680u & (v_u >> 16u)) | ++ 4278190080u); ++ } else { ++ self->private_impl.f_remap_transparency = (v_u | 18446462598732840960u); ++ } ++ } else if (self->private_impl.f_color_type == 3u) { ++ self->private_impl.f_dst_pixfmt = 2164523016u; ++ self->private_impl.f_src_pixfmt = 2164523016u; ++ if (self->private_impl.f_chunk_length > 256u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ v_n = ((uint32_t)(self->private_impl.f_chunk_length)); ++ self->private_impl.f_chunk_length = 0u; ++ while (v_i < v_n) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ self->private_data.f_src_palette[((4u * v_i) + 3u)] = t_2; ++ } ++ v_i += 1u; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } + +- if (self->private_impl.f_call_sequence > 64u) { +- return 1u; ++ goto ok; ++ ok: ++ self->private_impl.p_decode_trns = 0; ++ goto exit; + } +- return 0u; +-} +- +-// -------- func nie.decoder.restart_frame + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__restart_frame( +- wuffs_nie__decoder* self, +- uint64_t a_index, +- uint64_t a_io_position) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_trns = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_trns.v_i = v_i; ++ self->private_data.s_decode_trns.v_n = v_n; + +- if (self->private_impl.f_call_sequence < 32u) { +- return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- } +- if ((a_index != 0u) || (a_io_position != 16u)) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- self->private_impl.f_call_sequence = 40u; +- return wuffs_base__make_status(NULL); +-} + +-// -------- func nie.decoder.set_report_metadata +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_nie__decoder__set_report_metadata( +- wuffs_nie__decoder* self, +- uint32_t a_fourcc, +- bool a_report) { +- return wuffs_base__make_empty_struct(); ++ return status; + } + +-// -------- func nie.decoder.tell_me_more ++// -------- func png.decoder.decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_nie__decoder__tell_me_more( +- wuffs_nie__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, ++wuffs_png__decoder__decode_frame_config( ++ wuffs_png__decoder* self, ++ wuffs_base__frame_config* a_dst, + wuffs_base__io_buffer* a_src) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); +@@ -51808,354 +64965,485 @@ wuffs_nie__decoder__tell_me_more( + ? wuffs_base__error__disabled_by_previous_error + : wuffs_base__error__initialize_not_called); + } +- if (!a_dst || !a_src) { ++ if (!a_src) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 4)) { ++ (self->private_impl.active_coroutine != 2)) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } + self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- status = wuffs_base__make_status(wuffs_base__error__no_more_information); +- goto exit; +- +- goto ok; +- ok: +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} +- +-// -------- func nie.decoder.history_retain_length +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_nie__decoder__history_retain_length( +- const wuffs_nie__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func nie.decoder.workbuf_len +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_nie__decoder__workbuf_len( +- const wuffs_nie__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); +- } +- +- return wuffs_base__utility__make_range_ii_u64(0u, 0u); +-} +- +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB) +- +-// ---------------- Status Codes Implementations +- +-const char wuffs_zlib__note__dictionary_required[] = "@zlib: dictionary required"; +-const char wuffs_zlib__error__bad_checksum[] = "#zlib: bad checksum"; +-const char wuffs_zlib__error__bad_compression_method[] = "#zlib: bad compression method"; +-const char wuffs_zlib__error__bad_compression_window_size[] = "#zlib: bad compression window size"; +-const char wuffs_zlib__error__bad_parity_check[] = "#zlib: bad parity check"; +-const char wuffs_zlib__error__incorrect_dictionary[] = "#zlib: incorrect dictionary"; +-const char wuffs_zlib__error__truncated_input[] = "#zlib: truncated input"; +- +-// ---------------- Private Consts +- +-#define WUFFS_ZLIB__QUIRKS_BASE 2113790976 +- +-#define WUFFS_ZLIB__QUIRKS_COUNT 1 +- +-// ---------------- Private Initializer Prototypes +- +-// ---------------- Private Function Prototypes +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_zlib__decoder__do_transform_io( +- wuffs_zlib__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf); +- +-// ---------------- VTables +- +-const wuffs_base__io_transformer__func_ptrs +-wuffs_zlib__decoder__func_ptrs_for__wuffs_base__io_transformer = { +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_zlib__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_zlib__decoder__history_retain_length), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_zlib__decoder__set_quirk), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__slice_u8))(&wuffs_zlib__decoder__transform_io), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_zlib__decoder__workbuf_len), +-}; +- +-// ---------------- Initializer Implementations +- +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_zlib__decoder__initialize( +- wuffs_zlib__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); +- } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); +- } ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); +- } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); +- } +- } ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- { +- wuffs_base__status z = wuffs_adler32__hasher__initialize( +- &self->private_data.f_checksum, sizeof(self->private_data.f_checksum), WUFFS_VERSION, options); +- if (z.repr) { +- return z; +- } +- } +- { +- wuffs_base__status z = wuffs_adler32__hasher__initialize( +- &self->private_data.f_dict_id_hasher, sizeof(self->private_data.f_dict_id_hasher), WUFFS_VERSION, options); +- if (z.repr) { +- return z; +- } +- } +- { +- wuffs_base__status z = wuffs_deflate__decoder__initialize( +- &self->private_data.f_flate, sizeof(self->private_data.f_flate), WUFFS_VERSION, options); +- if (z.repr) { +- return z; ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_png__decoder__do_decode_frame_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_png__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } +- } +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = +- wuffs_base__io_transformer__vtable_name; +- self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = +- (const void*)(&wuffs_zlib__decoder__func_ptrs_for__wuffs_base__io_transformer); +- return wuffs_base__make_status(NULL); +-} +- +-wuffs_zlib__decoder* +-wuffs_zlib__decoder__alloc(void) { +- wuffs_zlib__decoder* x = +- (wuffs_zlib__decoder*)(calloc(sizeof(wuffs_zlib__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_zlib__decoder__initialize( +- x, sizeof(wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; +- } +- return x; +-} +- +-size_t +-sizeof__wuffs_zlib__decoder(void) { +- return sizeof(wuffs_zlib__decoder); +-} +- +-// ---------------- Function Implementations +- +-// -------- func zlib.decoder.dictionary_id +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_zlib__decoder__dictionary_id( +- const wuffs_zlib__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return self->private_impl.f_dict_id_want; +-} + +-// -------- func zlib.decoder.add_dictionary +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_zlib__decoder__add_dictionary( +- wuffs_zlib__decoder* self, +- wuffs_base__slice_u8 a_dict) { +- if (!self) { +- return wuffs_base__make_empty_struct(); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); ++ ok: ++ self->private_impl.p_decode_frame_config = 0; ++ goto exit; + } + +- if (self->private_impl.f_header_complete) { +- self->private_impl.f_bad_call_sequence = true; +- } else { +- self->private_impl.f_dict_id_got = wuffs_adler32__hasher__update_u32(&self->private_data.f_dict_id_hasher, a_dict); +- wuffs_deflate__decoder__add_history(&self->private_data.f_flate, a_dict); ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; + } +- self->private_impl.f_got_dictionary = true; +- return wuffs_base__make_empty_struct(); ++ return status; + } + +-// -------- func zlib.decoder.get_quirk ++// -------- func png.decoder.do_decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_zlib__decoder__get_quirk( +- const wuffs_zlib__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++static wuffs_base__status ++wuffs_png__decoder__do_decode_frame_config( ++ wuffs_png__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_checksum_have = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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 v_key = 0; ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((a_key == 1u) && self->private_impl.f_ignore_checksum) { +- return 1u; +- } else if (a_key >= 2113790976u) { +- v_key = (a_key - 2113790976u); +- if (v_key < 1u) { +- if (self->private_impl.f_quirks[v_key]) { +- return 1u; ++ if (((uint8_t)(self->private_impl.f_call_sequence & 16u)) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } else if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_png__decoder__do_decode_image_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); ++ goto exit; ++ } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_png__decoder__skip_frame(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ if (self->private_impl.f_metadata_fourcc != 0u) { ++ self->private_impl.f_call_sequence = 48u; ++ status = wuffs_base__make_status(wuffs_base__note__metadata_reported); ++ goto ok; ++ } ++ if (self->private_impl.f_num_decoded_frame_configs_value == 0u) { ++ self->private_impl.f_frame_rect_x0 = self->private_impl.f_first_rect_x0; ++ self->private_impl.f_frame_rect_y0 = self->private_impl.f_first_rect_y0; ++ self->private_impl.f_frame_rect_x1 = self->private_impl.f_first_rect_x1; ++ self->private_impl.f_frame_rect_y1 = self->private_impl.f_first_rect_y1; ++ self->private_impl.f_frame_config_io_position = self->private_impl.f_first_config_io_position; ++ self->private_impl.f_frame_duration = self->private_impl.f_first_duration; ++ self->private_impl.f_frame_disposal = self->private_impl.f_first_disposal; ++ self->private_impl.f_frame_overwrite_instead_of_blend = self->private_impl.f_first_overwrite_instead_of_blend; ++ } else { ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_frame_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_frame_config.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ } ++ self->private_impl.f_chunk_length = t_0; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_frame_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_frame_config.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ self->private_impl.f_chunk_type = t_1; ++ } ++ if (self->private_impl.f_chunk_type == 1145980233u) { ++ if (self->private_impl.f_chunk_length != 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_frame_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_frame_config.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ if (num_bits_2 == 24) { ++ t_2 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)) << 56; ++ } ++ } ++ v_checksum_have = t_2; ++ } ++ if ( ! self->private_impl.f_ignore_checksum && (v_checksum_have != 2187346606u)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_checksum); ++ goto exit; ++ } ++ self->private_impl.f_call_sequence = 96u; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } else if (self->private_impl.f_chunk_type == 1413571686u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } else if (self->private_impl.f_chunk_type == 1280598886u) { ++ self->private_impl.f_frame_config_io_position = ((uint64_t)(wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) - 8u)); ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ status = wuffs_png__decoder__decode_fctl(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_data.s_do_decode_frame_config.scratch = 4u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ if (self->private_data.s_do_decode_frame_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_frame_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_frame_config.scratch; ++ break; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ status = wuffs_png__decoder__decode_other_chunk(self, a_src, true); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (self->private_impl.f_metadata_fourcc != 0u) { ++ self->private_impl.f_call_sequence = 48u; ++ status = wuffs_base__make_status(wuffs_base__note__metadata_reported); ++ goto ok; ++ } ++ self->private_data.s_do_decode_frame_config.scratch = 4u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ if (self->private_data.s_do_decode_frame_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_frame_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_frame_config.scratch; ++ self->private_impl.f_chunk_length = 0u; + } + } ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ self->private_impl.f_frame_rect_x0, ++ self->private_impl.f_frame_rect_y0, ++ self->private_impl.f_frame_rect_x1, ++ self->private_impl.f_frame_rect_y1), ++ ((wuffs_base__flicks)(self->private_impl.f_frame_duration)), ++ ((uint64_t)(self->private_impl.f_num_decoded_frame_configs_value)), ++ self->private_impl.f_frame_config_io_position, ++ self->private_impl.f_frame_disposal, ++ ((self->private_impl.f_color_type <= 3u) && ! self->private_impl.f_seen_trns), ++ self->private_impl.f_frame_overwrite_instead_of_blend, ++ 0u); ++ } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frame_configs_value, 1u); ++ self->private_impl.f_call_sequence = 64u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame_config = 0; ++ goto exit; + } +- return 0u; +-} + +-// -------- func zlib.decoder.set_quirk ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_zlib__decoder__set_quirk( +- wuffs_zlib__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- if (self->private_impl.f_header_complete) { +- self->private_impl.f_bad_call_sequence = true; +- return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- } else if (a_key == 1u) { +- self->private_impl.f_ignore_checksum = (a_value > 0u); +- return wuffs_base__make_status(NULL); +- } else if (a_key >= 2113790976u) { +- a_key -= 2113790976u; +- if (a_key < 1u) { +- self->private_impl.f_quirks[a_key] = (a_value > 0u); +- return wuffs_base__make_status(NULL); +- } +- } +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ return status; + } + +-// -------- func zlib.decoder.history_retain_length ++// -------- func png.decoder.skip_frame + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_zlib__decoder__history_retain_length( +- const wuffs_zlib__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++static wuffs_base__status ++wuffs_png__decoder__skip_frame( ++ wuffs_png__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_seq_num = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } + +- return 0u; +-} ++ uint32_t coro_susp_point = self->private_impl.p_skip_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-// -------- func zlib.decoder.workbuf_len ++ self->private_impl.f_chunk_type_array[0u] = 0u; ++ self->private_impl.f_chunk_type_array[1u] = 0u; ++ self->private_impl.f_chunk_type_array[2u] = 0u; ++ self->private_impl.f_chunk_type_array[3u] = 0u; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 8u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ continue; ++ } ++ self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32u))); ++ if (self->private_impl.f_chunk_type == 1413563465u) { ++ if (self->private_impl.f_chunk_type_array[0u] == 102u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_type_array[0u] = 73u; ++ self->private_impl.f_chunk_type_array[1u] = 68u; ++ self->private_impl.f_chunk_type_array[2u] = 65u; ++ self->private_impl.f_chunk_type_array[3u] = 84u; ++ } else if (self->private_impl.f_chunk_type == 1413571686u) { ++ if (self->private_impl.f_chunk_type_array[0u] == 73u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_type_array[0u] = 102u; ++ self->private_impl.f_chunk_type_array[1u] = 100u; ++ self->private_impl.f_chunk_type_array[2u] = 65u; ++ self->private_impl.f_chunk_type_array[3u] = 84u; ++ if (self->private_impl.f_chunk_length < 4u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length -= 4u; ++ iop_a_src += 8u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_skip_frame.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_skip_frame.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ } ++ v_seq_num = t_0; ++ } ++ if (v_seq_num != self->private_impl.f_next_animation_seq_num) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number); ++ goto exit; ++ } else if (self->private_impl.f_next_animation_seq_num >= 4294967295u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); ++ goto exit; ++ } ++ self->private_impl.f_next_animation_seq_num += 1u; ++ self->private_data.s_skip_frame.scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 4u); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (self->private_data.s_skip_frame.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_skip_frame.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_skip_frame.scratch; ++ self->private_impl.f_chunk_length = 0u; ++ continue; ++ } else if (self->private_impl.f_chunk_type_array[0u] != 0u) { ++ break; ++ } else if (self->private_impl.f_chunk_type == 1280598886u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_data.s_skip_frame.scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 12u); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (self->private_data.s_skip_frame.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_skip_frame.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_skip_frame.scratch; ++ self->private_impl.f_chunk_length = 0u; ++ } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); ++ self->private_impl.f_call_sequence = 32u; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_zlib__decoder__workbuf_len( +- const wuffs_zlib__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ ok: ++ self->private_impl.p_skip_frame = 0; ++ goto exit; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_skip_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- return wuffs_base__utility__make_range_ii_u64(1u, 1u); ++ return status; + } + +-// -------- func zlib.decoder.transform_io ++// -------- func png.decoder.decode_frame + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_zlib__decoder__transform_io( +- wuffs_zlib__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_png__decoder__decode_frame( ++ wuffs_png__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, + wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +@@ -52170,7 +65458,7 @@ wuffs_zlib__decoder__transform_io( + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { ++ (self->private_impl.active_coroutine != 3)) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } +@@ -52179,71 +65467,312 @@ wuffs_zlib__decoder__transform_io( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_transform_io[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_png__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_png__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func png.decoder.do_decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_png__decoder__do_decode_frame( ++ wuffs_png__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_seq_num = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint32_t v_pass_width = 0; ++ uint32_t v_pass_height = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + ++ if (((uint8_t)(self->private_impl.f_call_sequence & 16u)) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } else if (self->private_impl.f_call_sequence >= 96u) { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } else if (self->private_impl.f_call_sequence != 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_png__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } + while (true) { +- { +- wuffs_base__status t_0 = wuffs_zlib__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); +- v_status = t_0; ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 8u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ continue; + } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_zlib__error__truncated_input); ++ self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32u))); ++ if (self->private_impl.f_chunk_type == 1413563465u) { ++ self->private_impl.f_chunk_type_array[0u] = 73u; ++ self->private_impl.f_chunk_type_array[1u] = 68u; ++ self->private_impl.f_chunk_type_array[2u] = 65u; ++ self->private_impl.f_chunk_type_array[3u] = 84u; ++ iop_a_src += 8u; ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4)); ++ } ++ break; ++ } else if (self->private_impl.f_chunk_type == 1413571686u) { ++ self->private_impl.f_chunk_type_array[0u] = 102u; ++ self->private_impl.f_chunk_type_array[1u] = 100u; ++ self->private_impl.f_chunk_type_array[2u] = 65u; ++ self->private_impl.f_chunk_type_array[3u] = 84u; ++ if (self->private_impl.f_chunk_length < 4u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length -= 4u; ++ iop_a_src += 8u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_frame.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_frame.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ } ++ v_seq_num = t_0; ++ } ++ if (v_seq_num != self->private_impl.f_next_animation_seq_num) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number); ++ goto exit; ++ } else if (self->private_impl.f_next_animation_seq_num >= 4294967295u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); ++ goto exit; ++ } ++ self->private_impl.f_next_animation_seq_num += 1u; ++ break; ++ } else if (self->private_impl.f_chunk_type == 1280598886u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); + goto exit; + } ++ self->private_data.s_do_decode_frame.scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 12u); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (self->private_data.s_do_decode_frame.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_frame.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_frame.scratch; ++ self->private_impl.f_chunk_length = 0u; ++ } ++ if (self->private_impl.f_zlib_is_dirty) { ++ wuffs_private_impl__ignore_status(wuffs_zlib__decoder__initialize(&self->private_data.f_zlib, ++ sizeof (wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ if (self->private_impl.f_ignore_checksum) { ++ wuffs_zlib__decoder__set_quirk(&self->private_data.f_zlib, 1u, 1u); ++ } ++ } ++ self->private_impl.f_zlib_is_dirty = true; ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), ++ wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt), ++ wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { + status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ self->private_impl.f_workbuf_hist_pos_base = 0u; ++ while (true) { ++ if (self->private_impl.f_chunk_type_array[0u] == 73u) { ++ v_pass_width = (16777215u & ((((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][1u])) + self->private_impl.f_width) >> WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0u])); ++ v_pass_height = (16777215u & ((((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][4u])) + self->private_impl.f_height) >> WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][3u])); ++ } else { ++ v_pass_width = (16777215u & ((uint32_t)(self->private_impl.f_frame_rect_x1 - self->private_impl.f_frame_rect_x0))); ++ v_pass_height = (16777215u & ((uint32_t)(self->private_impl.f_frame_rect_y1 - self->private_impl.f_frame_rect_y0))); ++ } ++ if ((v_pass_width > 0u) && (v_pass_height > 0u)) { ++ self->private_impl.f_pass_bytes_per_row = wuffs_png__decoder__calculate_bytes_per_row(self, v_pass_width); ++ self->private_impl.f_pass_workbuf_length = (((uint64_t)(v_pass_height)) * (1u + self->private_impl.f_pass_bytes_per_row)); ++ while (true) { ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_1 = wuffs_png__decoder__decode_pass(self, a_src, a_workbuf); ++ v_status = t_1; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } else if (wuffs_base__status__is_error(&v_status) || ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed))) { ++ if (self->private_impl.f_workbuf_wi <= ((uint64_t)(a_workbuf.len))) { ++ wuffs_png__decoder__filter_and_swizzle(self, a_dst, wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_workbuf_wi)); ++ } ++ if (v_status.repr == wuffs_base__suspension__short_read) { ++ status = wuffs_base__make_status(wuffs_png__error__truncated_input); ++ goto exit; ++ } ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); ++ } ++ v_status = wuffs_png__decoder__filter_and_swizzle(self, a_dst, a_workbuf); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ self->private_impl.f_workbuf_hist_pos_base += self->private_impl.f_pass_workbuf_length; ++ } ++ if ((self->private_impl.f_interlace_pass == 0u) || (self->private_impl.f_interlace_pass >= 7u)) { ++ break; ++ } ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_interlace_pass += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif + } ++ wuffs_private_impl__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); ++ self->private_impl.f_call_sequence = 32u; + + ok: +- self->private_impl.p_transform_io[0] = 0; ++ self->private_impl.p_do_decode_frame = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } ++ + return status; + } + +-// -------- func zlib.decoder.do_transform_io ++// -------- func png.decoder.decode_pass + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_zlib__decoder__do_transform_io( +- wuffs_zlib__decoder* self, +- wuffs_base__io_buffer* a_dst, ++wuffs_png__decoder__decode_pass( ++ wuffs_png__decoder* self, + wuffs_base__io_buffer* a_src, + wuffs_base__slice_u8 a_workbuf) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint16_t v_x = 0; +- uint32_t v_checksum_got = 0; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_w = &u_w; ++ uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint64_t v_w_mark = 0; ++ uint64_t v_r_mark = 0; ++ wuffs_base__status v_zlib_status = wuffs_base__make_status(NULL); ++ uint32_t v_checksum_have = 0; + uint32_t v_checksum_want = 0; +- uint64_t v_mark = 0; ++ uint32_t v_seq_num = 0; + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -52255,77 +65784,93 @@ wuffs_zlib__decoder__do_transform_io( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_transform_io[0]; +- if (coro_susp_point) { +- v_checksum_got = self->private_data.s_do_transform_io[0].v_checksum_got; +- } ++ uint32_t coro_susp_point = self->private_impl.p_decode_pass; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_bad_call_sequence) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } else if (self->private_impl.f_quirks[0u]) { +- } else if ( ! self->private_impl.f_want_dictionary) { ++ self->private_impl.f_workbuf_wi = 0u; ++ while (true) { ++ if ((self->private_impl.f_workbuf_wi > self->private_impl.f_pass_workbuf_length) || (self->private_impl.f_pass_workbuf_length > ((uint64_t)(a_workbuf.len)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; ++ } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint16_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_0 = wuffs_base__peek_u16be__no_bounds_check(iop_a_src); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_transform_io[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ wuffs_base__io_buffer* o_0_v_w = v_w; ++ uint8_t* o_0_iop_v_w = iop_v_w; ++ uint8_t* o_0_io0_v_w = io0_v_w; ++ uint8_t* o_0_io1_v_w = io1_v_w; ++ uint8_t* o_0_io2_v_w = io2_v_w; ++ v_w = wuffs_private_impl__io_writer__set( ++ &u_w, ++ &iop_v_w, ++ &io0_v_w, ++ &io1_v_w, ++ &io2_v_w, ++ wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ self->private_impl.f_workbuf_wi, ++ self->private_impl.f_pass_workbuf_length), ++ ((uint64_t)(self->private_impl.f_workbuf_hist_pos_base + self->private_impl.f_workbuf_wi))); ++ { ++ const bool o_1_closed_a_src = a_src->meta.closed; ++ const uint8_t* o_1_io2_a_src = io2_a_src; ++ wuffs_private_impl__io_reader__limit(&io2_a_src, iop_a_src, ++ ((uint64_t)(self->private_impl.f_chunk_length))); ++ if (a_src) { ++ size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); ++ a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); ++ a_src->meta.wi = n; ++ } ++ v_w_mark = ((uint64_t)(iop_v_w - io0_v_w)); ++ v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ u_w.meta.wi = ((size_t)(iop_v_w - u_w.data.ptr)); ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 8) { +- t_0 = ((uint16_t)(*scratch >> 48)); +- break; ++ wuffs_base__status t_0 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, v_w, a_src, wuffs_base__utility__empty_slice_u8()); ++ v_zlib_status = t_0; ++ iop_v_w = u_w.data.ptr + u_w.meta.wi; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; + } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_private_impl__io__since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); ++ } ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)(wuffs_private_impl__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_workbuf_wi, wuffs_private_impl__io__count_since(v_w_mark, ((uint64_t)(iop_v_w - io0_v_w)))); ++ io2_a_src = o_1_io2_a_src; ++ if (a_src) { ++ a_src->meta.closed = o_1_closed_a_src; ++ a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); + } + } +- v_x = t_0; +- } +- if (((v_x >> 8u) & 15u) != 8u) { +- status = wuffs_base__make_status(wuffs_zlib__error__bad_compression_method); +- goto exit; +- } +- if ((v_x >> 12u) > 7u) { +- status = wuffs_base__make_status(wuffs_zlib__error__bad_compression_window_size); +- goto exit; +- } +- if ((v_x % 31u) != 0u) { +- status = wuffs_base__make_status(wuffs_zlib__error__bad_parity_check); +- goto exit; ++ v_w = o_0_v_w; ++ iop_v_w = o_0_iop_v_w; ++ io0_v_w = o_0_io0_v_w; ++ io1_v_w = o_0_io1_v_w; ++ io2_v_w = o_0_io2_v_w; + } +- self->private_impl.f_want_dictionary = ((v_x & 32u) != 0u); +- if (self->private_impl.f_want_dictionary) { +- self->private_impl.f_dict_id_got = 1u; ++ if (wuffs_base__status__is_ok(&v_zlib_status)) { ++ if (self->private_impl.f_chunk_length > 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__too_much_data); ++ goto exit; ++ } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); + uint32_t t_1; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { + t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); + iop_a_src += 4; + } else { +- self->private_data.s_do_transform_io[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ self->private_data.s_decode_pass.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch; ++ uint64_t* scratch = &self->private_data.s_decode_pass.scratch; + uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); + *scratch >>= 8; + *scratch <<= 8; +@@ -52338,101 +65883,208 @@ wuffs_zlib__decoder__do_transform_io( + *scratch |= ((uint64_t)(num_bits_1)); + } + } +- self->private_impl.f_dict_id_want = t_1; ++ v_checksum_want = t_1; + } +- status = wuffs_base__make_status(wuffs_zlib__note__dictionary_required); +- goto ok; +- } else if (self->private_impl.f_got_dictionary) { +- status = wuffs_base__make_status(wuffs_zlib__error__incorrect_dictionary); +- goto exit; +- } +- } else if (self->private_impl.f_dict_id_got != self->private_impl.f_dict_id_want) { +- if (self->private_impl.f_got_dictionary) { +- status = wuffs_base__make_status(wuffs_zlib__error__incorrect_dictionary); ++ if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_chunk_type_array[0u] == 73u)) { ++ v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__utility__empty_slice_u8()); ++ if (v_checksum_have != v_checksum_want) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_checksum); ++ goto exit; ++ } ++ } ++ break; ++ } else if (v_zlib_status.repr == wuffs_base__suspension__short_write) { ++ if ((1u <= self->private_impl.f_interlace_pass) && (self->private_impl.f_interlace_pass <= 6u)) { ++ break; ++ } ++ status = wuffs_base__make_status(wuffs_base__error__too_much_data); + goto exit; +- } +- status = wuffs_base__make_status(wuffs_zlib__note__dictionary_required); +- goto ok; +- } +- self->private_impl.f_header_complete = true; +- while (true) { +- v_mark = ((uint64_t)(iop_a_dst - io0_a_dst)); +- { +- if (a_dst) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ } else if (v_zlib_status.repr != wuffs_base__suspension__short_read) { ++ status = v_zlib_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; + } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ goto ok; ++ } else if (self->private_impl.f_chunk_length == 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_pass.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_pass.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); ++ if (num_bits_2 == 24) { ++ t_2 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)); ++ } ++ } ++ v_checksum_want = t_2; + } +- wuffs_base__status t_2 = wuffs_deflate__decoder__transform_io(&self->private_data.f_flate, a_dst, a_src, a_workbuf); +- v_status = t_2; +- if (a_dst) { +- iop_a_dst = a_dst->data.ptr + a_dst->meta.wi; ++ if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_chunk_type_array[0u] == 73u)) { ++ v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__utility__empty_slice_u8()); ++ if (v_checksum_have != v_checksum_want) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_checksum); ++ goto exit; ++ } + } +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_pass.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_pass.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); ++ if (num_bits_3 == 24) { ++ t_3 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)); ++ } ++ } ++ self->private_impl.f_chunk_length = t_3; + } +- } +- if ( ! self->private_impl.f_ignore_checksum && ! self->private_impl.f_quirks[0u]) { +- v_checksum_got = wuffs_adler32__hasher__update_u32(&self->private_data.f_checksum, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); +- } +- if (wuffs_base__status__is_ok(&v_status)) { +- break; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); +- } +- if ( ! self->private_impl.f_quirks[0u]) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- uint32_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_transform_io[0].scratch = 0; ++ { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ uint32_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_pass.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_pass.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; ++ if (num_bits_4 == 24) { ++ t_4 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_4 += 8u; ++ *scratch |= ((uint64_t)(num_bits_4)) << 56; + } +- uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); +- if (num_bits_3 == 24) { +- t_3 = ((uint32_t)(*scratch >> 32)); +- break; ++ } ++ self->private_impl.f_chunk_type = t_4; ++ } ++ if (self->private_impl.f_chunk_type_array[0u] == 73u) { ++ if (self->private_impl.f_chunk_type != 1413563465u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4)); ++ } ++ } else { ++ if ((self->private_impl.f_chunk_type != 1413571686u) || (self->private_impl.f_chunk_length < 4u)) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length -= 4u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ uint32_t t_5; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_5 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_pass.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_pass.scratch; ++ uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); ++ if (num_bits_5 == 24) { ++ t_5 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_5 += 8u; ++ *scratch |= ((uint64_t)(num_bits_5)); ++ } + } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)); ++ v_seq_num = t_5; ++ } ++ if (v_seq_num != self->private_impl.f_next_animation_seq_num) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number); ++ goto exit; ++ } else if (self->private_impl.f_next_animation_seq_num >= 4294967295u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); ++ goto exit; + } ++ self->private_impl.f_next_animation_seq_num += 1u; + } +- v_checksum_want = t_3; +- } +- if ( ! self->private_impl.f_ignore_checksum && (v_checksum_got != v_checksum_want)) { +- status = wuffs_base__make_status(wuffs_zlib__error__bad_checksum); ++ continue; ++ } else if (((uint64_t)(io2_a_src - iop_a_src)) > 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__internal_error_zlib_decoder_did_not_exhaust_its_input); + goto exit; + } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); ++ } ++ if (self->private_impl.f_workbuf_wi != self->private_impl.f_pass_workbuf_length) { ++ status = wuffs_base__make_status(wuffs_base__error__not_enough_data); ++ goto exit; ++ } else if (0u < ((uint64_t)(a_workbuf.len))) { ++ if (a_workbuf.ptr[0u] == 4u) { ++ a_workbuf.ptr[0u] = 1u; ++ } + } + + ok: +- self->private_impl.p_do_transform_io[0] = 0; ++ self->private_impl.p_decode_pass = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_transform_io[0].v_checksum_got = v_checksum_got; ++ self->private_impl.p_decode_pass = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -52440,2021 +66092,1710 @@ wuffs_zlib__decoder__do_transform_io( + return status; + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG) +- +-// ---------------- Status Codes Implementations +- +-const char wuffs_png__error__bad_animation_sequence_number[] = "#png: bad animation sequence number"; +-const char wuffs_png__error__bad_checksum[] = "#png: bad checksum"; +-const char wuffs_png__error__bad_chunk[] = "#png: bad chunk"; +-const char wuffs_png__error__bad_filter[] = "#png: bad filter"; +-const char wuffs_png__error__bad_header[] = "#png: bad header"; +-const char wuffs_png__error__bad_text_chunk_not_latin_1[] = "#png: bad text chunk (not Latin-1)"; +-const char wuffs_png__error__missing_palette[] = "#png: missing palette"; +-const char wuffs_png__error__truncated_input[] = "#png: truncated input"; +-const char wuffs_png__error__unsupported_cgbi_extension[] = "#png: unsupported CgBI extension"; +-const char wuffs_png__error__unsupported_png_compression_method[] = "#png: unsupported PNG compression method"; +-const char wuffs_png__error__unsupported_png_file[] = "#png: unsupported PNG file"; +-const char wuffs_png__error__internal_error_inconsistent_i_o[] = "#png: internal error: inconsistent I/O"; +-const char wuffs_png__error__internal_error_inconsistent_chunk_type[] = "#png: internal error: inconsistent chunk type"; +-const char wuffs_png__error__internal_error_inconsistent_frame_bounds[] = "#png: internal error: inconsistent frame bounds"; +-const char wuffs_png__error__internal_error_inconsistent_workbuf_length[] = "#png: internal error: inconsistent workbuf length"; +-const char wuffs_png__error__internal_error_zlib_decoder_did_not_exhaust_its_input[] = "#png: internal error: zlib decoder did not exhaust its input"; +- +-// ---------------- Private Consts +- +-#define WUFFS_PNG__ANCILLARY_BIT 32 +- +-static const uint8_t +-WUFFS_PNG__INTERLACING[8][6] WUFFS_BASE__POTENTIALLY_UNUSED = { +- { +- 0, 0, 0, 0, 0, 0, +- }, { +- 3, 7, 0, 3, 7, 0, +- }, { +- 3, 3, 4, 3, 7, 0, +- }, { +- 2, 3, 0, 3, 3, 4, +- }, { +- 2, 1, 2, 2, 3, 0, +- }, { +- 1, 1, 0, 2, 1, 2, +- }, { +- 1, 0, 1, 1, 1, 0, +- }, { +- 0, 0, 0, 1, 0, 1, +- }, +-}; +- +-static const uint8_t +-WUFFS_PNG__LOW_BIT_DEPTH_MULTIPLIERS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 255, 85, 0, 17, 0, 0, 0, +-}; +- +-static const uint8_t +-WUFFS_PNG__LOW_BIT_DEPTH_NUM_PACKS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 8, 4, 0, 2, 0, 0, 0, +-}; +- +-static const uint8_t +-WUFFS_PNG__NUM_CHANNELS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 1, 0, 3, 1, 2, 0, 4, 0, +-}; +- +-static const uint16_t +-WUFFS_PNG__LATIN_1[256] WUFFS_BASE__POTENTIALLY_UNUSED = { +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 32, 33, 34, 35, 36, 37, 38, 39, +- 40, 41, 42, 43, 44, 45, 46, 47, +- 48, 49, 50, 51, 52, 53, 54, 55, +- 56, 57, 58, 59, 60, 61, 62, 63, +- 64, 65, 66, 67, 68, 69, 70, 71, +- 72, 73, 74, 75, 76, 77, 78, 79, +- 80, 81, 82, 83, 84, 85, 86, 87, +- 88, 89, 90, 91, 92, 93, 94, 95, +- 96, 97, 98, 99, 100, 101, 102, 103, +- 104, 105, 106, 107, 108, 109, 110, 111, +- 112, 113, 114, 115, 116, 117, 118, 119, +- 120, 121, 122, 123, 124, 125, 126, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 41410, 41666, 41922, 42178, 42434, 42690, 42946, +- 43202, 43458, 43714, 43970, 44226, 44482, 44738, 44994, +- 45250, 45506, 45762, 46018, 46274, 46530, 46786, 47042, +- 47298, 47554, 47810, 48066, 48322, 48578, 48834, 49090, +- 32963, 33219, 33475, 33731, 33987, 34243, 34499, 34755, +- 35011, 35267, 35523, 35779, 36035, 36291, 36547, 36803, +- 37059, 37315, 37571, 37827, 38083, 38339, 38595, 38851, +- 39107, 39363, 39619, 39875, 40131, 40387, 40643, 40899, +- 41155, 41411, 41667, 41923, 42179, 42435, 42691, 42947, +- 43203, 43459, 43715, 43971, 44227, 44483, 44739, 44995, +- 45251, 45507, 45763, 46019, 46275, 46531, 46787, 47043, +- 47299, 47555, 47811, 48067, 48323, 48579, 48835, 49091, +-}; +- +-// ---------------- Private Initializer Prototypes +- +-// ---------------- Private Function Prototypes +- +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1_distance_4_arm_neon( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr); +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3_distance_4_arm_neon( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_3_arm_neon( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_4_arm_neon( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1__choosy_default( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1_distance_3_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1_distance_4_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_2( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3__choosy_default( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3_distance_3_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3_distance_4_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4__choosy_default( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_3_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_4_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +- +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1_distance_4_x86_sse42( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3_distance_4_x86_sse42( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_3_x86_sse42( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_4_x86_sse42( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev); +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__do_decode_image_config( +- wuffs_png__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_ihdr( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__assign_filter_distance( +- wuffs_png__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-static uint64_t +-wuffs_png__decoder__calculate_bytes_per_row( +- const wuffs_png__decoder* self, +- uint32_t a_width); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__choose_filter_implementations( +- wuffs_png__decoder* self); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_other_chunk( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src, +- bool a_framy); +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_actl( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++// -------- func png.decoder.frame_dirty_rect + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_chrm( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_png__decoder__frame_dirty_rect( ++ const wuffs_png__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_exif( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++ return wuffs_base__utility__make_rect_ie_u32( ++ self->private_impl.f_frame_rect_x0, ++ self->private_impl.f_frame_rect_y0, ++ self->private_impl.f_frame_rect_x1, ++ self->private_impl.f_frame_rect_y1); ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_fctl( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++// -------- func png.decoder.num_animation_loops + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_gama( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_png__decoder__num_animation_loops( ++ const wuffs_png__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_iccp( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++ return self->private_impl.f_num_animation_loops_value; ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_plte( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++// -------- func png.decoder.num_decoded_frame_configs + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_srgb( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_png__decoder__num_decoded_frame_configs( ++ const wuffs_png__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_trns( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++ return ((uint64_t)(self->private_impl.f_num_decoded_frame_configs_value)); ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__do_decode_frame_config( +- wuffs_png__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); ++// -------- func png.decoder.num_decoded_frames + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__skip_frame( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src); ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_png__decoder__num_decoded_frames( ++ const wuffs_png__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__do_decode_frame( +- wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); ++ return ((uint64_t)(self->private_impl.f_num_decoded_frames_value)); ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_pass( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf); ++// -------- func png.decoder.restart_frame + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__do_tell_me_more( ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_png__decoder__restart_frame( + wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src); ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__filter_and_swizzle( +- wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf); ++ if (self->private_impl.f_call_sequence < 32u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } else if ((a_index >= ((uint64_t)(self->private_impl.f_num_animation_frames_value))) || ((a_index == 0u) && (a_io_position != self->private_impl.f_first_config_io_position))) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_call_sequence = 40u; ++ if (self->private_impl.f_interlace_pass >= 1u) { ++ self->private_impl.f_interlace_pass = 1u; ++ } ++ self->private_impl.f_frame_config_io_position = a_io_position; ++ self->private_impl.f_num_decoded_frame_configs_value = ((uint32_t)(a_index)); ++ self->private_impl.f_num_decoded_frames_value = self->private_impl.f_num_decoded_frame_configs_value; ++ return wuffs_base__make_status(NULL); ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__filter_and_swizzle__choosy_default( +- wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf); ++// -------- func png.decoder.set_report_metadata + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__filter_and_swizzle_tricky( ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_png__decoder__set_report_metadata( + wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf); +- +-// ---------------- VTables ++ uint32_t a_fourcc, ++ bool a_report) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); ++ } + +-const wuffs_base__image_decoder__func_ptrs +-wuffs_png__decoder__func_ptrs_for__wuffs_base__image_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__pixel_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__pixel_blend, +- wuffs_base__slice_u8, +- wuffs_base__decode_frame_options*))(&wuffs_png__decoder__decode_frame), +- (wuffs_base__status(*)(void*, +- wuffs_base__frame_config*, +- wuffs_base__io_buffer*))(&wuffs_png__decoder__decode_frame_config), +- (wuffs_base__status(*)(void*, +- wuffs_base__image_config*, +- wuffs_base__io_buffer*))(&wuffs_png__decoder__decode_image_config), +- (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_png__decoder__frame_dirty_rect), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_png__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_png__decoder__history_retain_length), +- (uint32_t(*)(const void*))(&wuffs_png__decoder__num_animation_loops), +- (uint64_t(*)(const void*))(&wuffs_png__decoder__num_decoded_frame_configs), +- (uint64_t(*)(const void*))(&wuffs_png__decoder__num_decoded_frames), +- (wuffs_base__status(*)(void*, +- uint64_t, +- uint64_t))(&wuffs_png__decoder__restart_frame), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_png__decoder__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- uint32_t, +- bool))(&wuffs_png__decoder__set_report_metadata), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__more_information*, +- wuffs_base__io_buffer*))(&wuffs_png__decoder__tell_me_more), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_png__decoder__workbuf_len), +-}; ++ if (a_fourcc == 1128813133u) { ++ self->private_impl.f_report_metadata_chrm = a_report; ++ } else if (a_fourcc == 1163413830u) { ++ self->private_impl.f_report_metadata_exif = a_report; ++ } else if (a_fourcc == 1195461953u) { ++ self->private_impl.f_report_metadata_gama = a_report; ++ } else if (a_fourcc == 1229144912u) { ++ self->private_impl.f_report_metadata_iccp = a_report; ++ } else if (a_fourcc == 1263947808u) { ++ self->private_impl.f_report_metadata_kvp = a_report; ++ } else if (a_fourcc == 1397901122u) { ++ self->private_impl.f_report_metadata_srgb = a_report; ++ } ++ return wuffs_base__make_empty_struct(); ++} + +-// ---------------- Initializer Implementations ++// -------- func png.decoder.tell_me_more + +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_png__decoder__initialize( ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_png__decoder__tell_me_more( + wuffs_png__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); + } +- +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); +- } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); +- } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- self->private_impl.choosy_filter_1 = &wuffs_png__decoder__filter_1__choosy_default; +- self->private_impl.choosy_filter_3 = &wuffs_png__decoder__filter_3__choosy_default; +- self->private_impl.choosy_filter_4 = &wuffs_png__decoder__filter_4__choosy_default; +- self->private_impl.choosy_filter_and_swizzle = &wuffs_png__decoder__filter_and_swizzle__choosy_default; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- { +- wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize( +- &self->private_data.f_crc32, sizeof(self->private_data.f_crc32), WUFFS_VERSION, options); +- if (z.repr) { +- return z; +- } +- } +- { +- wuffs_base__status z = wuffs_zlib__decoder__initialize( +- &self->private_data.f_zlib, sizeof(self->private_data.f_zlib), WUFFS_VERSION, options); +- if (z.repr) { +- return z; ++ uint32_t coro_susp_point = self->private_impl.p_tell_me_more; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_png__decoder__do_tell_me_more(self, a_dst, a_minfo, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_png__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } +- } +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = +- wuffs_base__image_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = +- (const void*)(&wuffs_png__decoder__func_ptrs_for__wuffs_base__image_decoder); +- return wuffs_base__make_status(NULL); +-} + +-wuffs_png__decoder* +-wuffs_png__decoder__alloc(void) { +- wuffs_png__decoder* x = +- (wuffs_png__decoder*)(calloc(sizeof(wuffs_png__decoder), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_png__decoder__initialize( +- x, sizeof(wuffs_png__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; ++ ok: ++ self->private_impl.p_tell_me_more = 0; ++ goto exit; + } +- return x; +-} + +-size_t +-sizeof__wuffs_png__decoder(void) { +- return sizeof(wuffs_png__decoder); +-} ++ goto suspend; ++ suspend: ++ self->private_impl.p_tell_me_more = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0; + +-// ---------------- Function Implementations ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} + +-// ‼ WUFFS MULTI-FILE SECTION +arm_neon +-// -------- func png.decoder.filter_1_distance_4_arm_neon ++// -------- func png.decoder.do_tell_me_more + +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1_distance_4_arm_neon( ++static wuffs_base__status ++wuffs_png__decoder__do_tell_me_more( + wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr) { +- wuffs_base__slice_u8 v_curr = {0}; +- uint8x8_t v_fa = {0}; +- uint8x8_t v_fx = {0}; ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- v_curr.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8); +- while (v_curr.ptr < i_end0_curr) { +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, v_fa); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, v_fa); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; +- } +- v_curr.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end1_curr) { +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, v_fa); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; ++ uint8_t v_c8 = 0; ++ uint16_t v_c16 = 0; ++ wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer(); ++ wuffs_base__io_buffer* v_w = &u_w; ++ uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint64_t v_num_written = 0; ++ uint64_t v_w_mark = 0; ++ uint64_t v_r_mark = 0; ++ wuffs_base__status v_zlib_status = wuffs_base__make_status(NULL); ++ ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; + } +- v_curr.len = 0; + } +- return wuffs_base__make_empty_struct(); +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-// ‼ WUFFS MULTI-FILE SECTION -arm_neon +- +-// ‼ WUFFS MULTI-FILE SECTION +arm_neon +-// -------- func png.decoder.filter_3_distance_4_arm_neon ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } + +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3_distance_4_arm_neon( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- uint8x8_t v_fa = {0}; +- uint8x8_t v_fb = {0}; +- uint8x8_t v_fx = {0}; ++ uint32_t coro_susp_point = self->private_impl.p_do_tell_me_more; ++ if (coro_susp_point) { ++ v_zlib_status = self->private_data.s_do_tell_me_more.v_zlib_status; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (((uint64_t)(a_prev.len)) == 0u) { +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- v_curr.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8); +- while (v_curr.ptr < i_end0_curr) { +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; ++ if (((uint8_t)(self->private_impl.f_call_sequence & 16u)) == 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } ++ if (self->private_impl.f_metadata_fourcc == 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); ++ goto exit; ++ } ++ do { ++ if (self->private_impl.f_metadata_flavor == 3u) { ++ while (true) { ++ if (wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) != self->private_impl.f_metadata_y) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position); ++ goto exit; ++ } else if (a_minfo != NULL) { ++ wuffs_base__more_information__set(a_minfo, ++ self->private_impl.f_metadata_flavor, ++ self->private_impl.f_metadata_fourcc, ++ self->private_impl.f_metadata_x, ++ self->private_impl.f_metadata_y, ++ self->private_impl.f_metadata_z); ++ } ++ if (self->private_impl.f_metadata_y >= self->private_impl.f_metadata_z) { ++ goto label__goto_done__break; ++ } ++ self->private_impl.f_metadata_y = self->private_impl.f_metadata_z; ++ status = wuffs_base__make_status(wuffs_base__suspension__even_more_information); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ } ++ if (self->private_impl.f_metadata_is_zlib_compressed) { ++ if (self->private_impl.f_zlib_is_dirty) { ++ wuffs_private_impl__ignore_status(wuffs_zlib__decoder__initialize(&self->private_data.f_zlib, ++ sizeof (wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ if (self->private_impl.f_ignore_checksum) { ++ wuffs_zlib__decoder__set_quirk(&self->private_data.f_zlib, 1u, 1u); ++ } ++ } ++ self->private_impl.f_zlib_is_dirty = true; ++ self->private_impl.f_ztxt_hist_pos = 0u; ++ } ++ label__loop__continue:; ++ while (true) { ++ if (a_minfo != NULL) { ++ wuffs_base__more_information__set(a_minfo, ++ self->private_impl.f_metadata_flavor, ++ self->private_impl.f_metadata_fourcc, ++ self->private_impl.f_metadata_x, ++ self->private_impl.f_metadata_y, ++ self->private_impl.f_metadata_z); ++ } ++ if (self->private_impl.f_metadata_flavor != 4u) { ++ break; ++ } ++ if (self->private_impl.f_metadata_is_zlib_compressed) { ++ if (self->private_impl.f_chunk_type == 1346585449u) { ++ { ++ const bool o_0_closed_a_src = a_src->meta.closed; ++ const uint8_t* o_0_io2_a_src = io2_a_src; ++ wuffs_private_impl__io_reader__limit(&io2_a_src, iop_a_src, ++ ((uint64_t)(self->private_impl.f_chunk_length))); ++ if (a_src) { ++ size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); ++ a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); ++ a_src->meta.wi = n; ++ } ++ v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ 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__status t_0 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, a_dst, a_src, wuffs_base__utility__empty_slice_u8()); ++ v_zlib_status = t_0; ++ 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; ++ } ++ } ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)(wuffs_private_impl__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); ++ io2_a_src = o_0_io2_a_src; ++ if (a_src) { ++ a_src->meta.closed = o_0_closed_a_src; ++ a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); ++ } ++ } ++ if (wuffs_base__status__is_ok(&v_zlib_status)) { ++ self->private_impl.f_metadata_is_zlib_compressed = false; ++ break; ++ } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) { ++ status = v_zlib_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ status = v_zlib_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ } else if (self->private_impl.f_chunk_type == 1951945833u) { ++ { ++ const bool o_1_closed_a_src = a_src->meta.closed; ++ const uint8_t* o_1_io2_a_src = io2_a_src; ++ wuffs_private_impl__io_reader__limit(&io2_a_src, iop_a_src, ++ ((uint64_t)(self->private_impl.f_chunk_length))); ++ if (a_src) { ++ size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); ++ a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); ++ a_src->meta.wi = n; ++ } ++ v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ 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__status t_1 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, a_dst, a_src, wuffs_base__utility__empty_slice_u8()); ++ v_zlib_status = t_1; ++ 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; ++ } ++ } ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)(wuffs_private_impl__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); ++ io2_a_src = o_1_io2_a_src; ++ if (a_src) { ++ a_src->meta.closed = o_1_closed_a_src; ++ a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); ++ } ++ } ++ if (wuffs_base__status__is_ok(&v_zlib_status)) { ++ self->private_impl.f_metadata_is_zlib_compressed = false; ++ break; ++ } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) { ++ status = v_zlib_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ status = v_zlib_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ } else if (self->private_impl.f_chunk_type == 1951945850u) { ++ if (self->private_impl.f_ztxt_ri == self->private_impl.f_ztxt_wi) { ++ { ++ wuffs_base__io_buffer* o_2_v_w = v_w; ++ uint8_t* o_2_iop_v_w = iop_v_w; ++ uint8_t* o_2_io0_v_w = io0_v_w; ++ uint8_t* o_2_io1_v_w = io1_v_w; ++ uint8_t* o_2_io2_v_w = io2_v_w; ++ v_w = wuffs_private_impl__io_writer__set( ++ &u_w, ++ &iop_v_w, ++ &io0_v_w, ++ &io1_v_w, ++ &io2_v_w, ++ wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024), ++ self->private_impl.f_ztxt_hist_pos); ++ { ++ const bool o_3_closed_a_src = a_src->meta.closed; ++ const uint8_t* o_3_io2_a_src = io2_a_src; ++ wuffs_private_impl__io_reader__limit(&io2_a_src, iop_a_src, ++ ((uint64_t)(self->private_impl.f_chunk_length))); ++ if (a_src) { ++ size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); ++ a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); ++ a_src->meta.wi = n; ++ } ++ v_w_mark = ((uint64_t)(iop_v_w - io0_v_w)); ++ v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ u_w.meta.wi = ((size_t)(iop_v_w - u_w.data.ptr)); ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_2 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, v_w, a_src, wuffs_base__utility__empty_slice_u8()); ++ v_zlib_status = t_2; ++ iop_v_w = u_w.data.ptr + u_w.meta.wi; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)(wuffs_private_impl__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); ++ v_num_written = wuffs_private_impl__io__count_since(v_w_mark, ((uint64_t)(iop_v_w - io0_v_w))); ++ io2_a_src = o_3_io2_a_src; ++ if (a_src) { ++ a_src->meta.closed = o_3_closed_a_src; ++ a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); ++ } ++ } ++ v_w = o_2_v_w; ++ iop_v_w = o_2_iop_v_w; ++ io0_v_w = o_2_io0_v_w; ++ io1_v_w = o_2_io1_v_w; ++ io2_v_w = o_2_io2_v_w; ++ } ++ if (v_num_written > 1024u) { ++ status = wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_i_o); ++ goto exit; ++ } ++ self->private_impl.f_ztxt_ri = 0u; ++ self->private_impl.f_ztxt_wi = ((uint32_t)(v_num_written)); ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_ztxt_hist_pos, v_num_written); ++ } ++ while (self->private_impl.f_ztxt_ri < self->private_impl.f_ztxt_wi) { ++ v_c16 = WUFFS_PNG__LATIN_1[self->private_data.f_dst_palette[self->private_impl.f_ztxt_ri]]; ++ if (v_c16 == 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_text_chunk_not_latin_1); ++ goto exit; ++ } else if (v_c16 <= 127u) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ goto label__loop__continue; ++ } ++ self->private_impl.f_ztxt_ri += 1u; ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(v_c16))), iop_a_dst += 1); ++ } else { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ goto label__loop__continue; ++ } ++ self->private_impl.f_ztxt_ri += 1u; ++ (wuffs_base__poke_u16le__no_bounds_check(iop_a_dst, v_c16), iop_a_dst += 2); ++ } ++ } ++ if (wuffs_base__status__is_ok(&v_zlib_status)) { ++ self->private_impl.f_metadata_is_zlib_compressed = false; ++ break; ++ } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) { ++ status = v_zlib_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } else if (v_zlib_status.repr != wuffs_base__suspension__short_write) { ++ status = v_zlib_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_chunk_type); ++ goto exit; ++ } ++ } else if ((self->private_impl.f_chunk_type == 1951945833u) && (self->private_impl.f_metadata_fourcc == 1263947862u)) { ++ while (true) { ++ if (self->private_impl.f_chunk_length <= 0u) { ++ goto label__loop__break; ++ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); ++ goto label__loop__continue; ++ } else if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); ++ goto label__loop__continue; ++ } ++ self->private_impl.f_chunk_length -= 1u; ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_c8), iop_a_dst += 1); ++ } ++ } else { ++ while (true) { ++ if (self->private_impl.f_chunk_length <= 0u) { ++ if (self->private_impl.f_metadata_fourcc == 1263947851u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ goto label__loop__break; ++ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); ++ goto label__loop__continue; ++ } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ if (v_c8 == 0u) { ++ self->private_impl.f_chunk_length -= 1u; ++ iop_a_src += 1u; ++ goto label__loop__break; ++ } ++ v_c16 = WUFFS_PNG__LATIN_1[v_c8]; ++ if (v_c16 == 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_text_chunk_not_latin_1); ++ goto exit; ++ } else if (v_c16 <= 127u) { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); ++ goto label__loop__continue; ++ } ++ self->private_impl.f_chunk_length -= 1u; ++ iop_a_src += 1u; ++ (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(v_c16))), iop_a_dst += 1); ++ } else { ++ if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); ++ goto label__loop__continue; ++ } ++ self->private_impl.f_chunk_length -= 1u; ++ iop_a_src += 1u; ++ (wuffs_base__poke_u16le__no_bounds_check(iop_a_dst, v_c16), iop_a_dst += 2); ++ } ++ } ++ } + } +- v_curr.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end1_curr) { +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; ++ label__loop__break:; ++ if (self->private_impl.f_metadata_fourcc == 1263947851u) { ++ self->private_impl.f_metadata_fourcc = 1263947862u; ++ if (self->private_impl.f_chunk_type == 1951945833u) { ++ if (self->private_impl.f_chunk_length <= 1u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length -= 2u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ if (v_c8 == 0u) { ++ self->private_impl.f_metadata_is_zlib_compressed = false; ++ } else if (v_c8 == 1u) { ++ self->private_impl.f_metadata_is_zlib_compressed = true; ++ } else { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; ++ } ++ if ((v_c8 != 0u) && self->private_impl.f_metadata_is_zlib_compressed) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method); ++ goto exit; ++ } ++ self->private_impl.f_metadata_fourcc -= 2u; ++ while (self->private_impl.f_metadata_fourcc != 1263947862u) { ++ self->private_impl.f_metadata_fourcc += 1u; ++ while (true) { ++ if (self->private_impl.f_chunk_length <= 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length -= 1u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; ++ } ++ if (v_c8 == 0u) { ++ break; ++ } ++ } ++ } ++ } else if (self->private_impl.f_chunk_type == 1951945850u) { ++ if (self->private_impl.f_chunk_length <= 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; ++ } ++ self->private_impl.f_chunk_length -= 1u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; ++ } ++ if (v_c8 != 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method); ++ goto exit; ++ } ++ self->private_impl.f_metadata_is_zlib_compressed = true; ++ } ++ self->private_impl.f_call_sequence &= 239u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; + } +- v_curr.len = 0; ++ } while (0); ++ label__goto_done__break:; ++ if (self->private_impl.f_chunk_length != 0u) { ++ status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ goto exit; + } +- } else { +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8); +- while (v_curr.ptr < i_end0_curr) { +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- } +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end1_curr) { +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb)); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fa = v_fx; +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- } +- v_curr.len = 0; +- v_prev.len = 0; ++ self->private_data.s_do_tell_me_more.scratch = 4u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ if (self->private_data.s_do_tell_me_more.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_tell_me_more.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- } +- return wuffs_base__make_empty_struct(); +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-// ‼ WUFFS MULTI-FILE SECTION -arm_neon +- +-// ‼ WUFFS MULTI-FILE SECTION +arm_neon +-// -------- func png.decoder.filter_4_distance_3_arm_neon +- +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_3_arm_neon( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- uint8x8_t v_fa = {0}; +- uint8x8_t v_fb = {0}; +- uint8x8_t v_fc = {0}; +- uint8x8_t v_fx = {0}; +- uint16x8_t v_fafb = {0}; +- uint16x8_t v_fcfc = {0}; +- uint16x8_t v_pa = {0}; +- uint16x8_t v_pb = {0}; +- uint16x8_t v_pc = {0}; +- uint16x8_t v_cmpab = {0}; +- uint16x8_t v_cmpac = {0}; +- uint8x8_t v_picka = {0}; +- uint8x8_t v_pickb = {0}; ++ iop_a_src += self->private_data.s_do_tell_me_more.scratch; ++ self->private_impl.f_metadata_flavor = 0u; ++ self->private_impl.f_metadata_fourcc = 0u; ++ self->private_impl.f_metadata_x = 0u; ++ self->private_impl.f_metadata_y = 0u; ++ self->private_impl.f_metadata_z = 0u; ++ self->private_impl.f_call_sequence &= 239u; ++ status = wuffs_base__make_status(NULL); ++ goto ok; + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + wuffs_base__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 7, 6); +- while (v_curr.ptr < i_end0_curr) { +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fafb = vaddl_u8(v_fa, v_fb); +- v_fcfc = vaddl_u8(v_fc, v_fc); +- v_pa = vabdl_u8(v_fb, v_fc); +- v_pb = vabdl_u8(v_fa, v_fc); +- v_pc = vabdq_u16(v_fafb, v_fcfc); +- v_cmpab = vcleq_u16(v_pa, v_pb); +- v_cmpac = vcleq_u16(v_pa, v_pc); +- v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); +- v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); +- v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); +- wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fc = v_fb; +- v_fa = v_fx; +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fafb = vaddl_u8(v_fa, v_fb); +- v_fcfc = vaddl_u8(v_fc, v_fc); +- v_pa = vabdl_u8(v_fb, v_fc); +- v_pb = vabdl_u8(v_fa, v_fc); +- v_pc = vabdq_u16(v_fafb, v_fcfc); +- v_cmpab = vcleq_u16(v_pa, v_pb); +- v_cmpac = vcleq_u16(v_pa, v_pc); +- v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); +- v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); +- v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); +- wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fc = v_fb; +- v_fa = v_fx; +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- } +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + wuffs_base__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 4, 3); +- while (v_curr.ptr < i_end1_curr) { +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fafb = vaddl_u8(v_fa, v_fb); +- v_fcfc = vaddl_u8(v_fc, v_fc); +- v_pa = vabdl_u8(v_fb, v_fc); +- v_pb = vabdl_u8(v_fa, v_fc); +- v_pc = vabdq_u16(v_fafb, v_fcfc); +- v_cmpab = vcleq_u16(v_pa, v_pb); +- v_cmpac = vcleq_u16(v_pa, v_pc); +- v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); +- v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); +- v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); +- wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fc = v_fb; +- v_fa = v_fx; +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- } +- v_curr.len = 3; +- v_prev.len = 3; +- uint8_t* i_end2_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3); +- while (v_curr.ptr < i_end2_curr) { +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u24le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u24le__no_bounds_check(v_curr.ptr))); +- v_fafb = vaddl_u8(v_fa, v_fb); +- v_fcfc = vaddl_u8(v_fc, v_fc); +- v_pa = vabdl_u8(v_fb, v_fc); +- v_pb = vabdl_u8(v_fa, v_fc); +- v_pc = vabdq_u16(v_fafb, v_fcfc); +- v_cmpab = vcleq_u16(v_pa, v_pb); +- v_cmpac = vcleq_u16(v_pa, v_pc); +- v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); +- v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); +- v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); +- wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- } +- v_curr.len = 0; +- v_prev.len = 0; ++ ok: ++ self->private_impl.p_do_tell_me_more = 0; ++ goto exit; + } +- return wuffs_base__make_empty_struct(); +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-// ‼ WUFFS MULTI-FILE SECTION -arm_neon + +-// ‼ WUFFS MULTI-FILE SECTION +arm_neon +-// -------- func png.decoder.filter_4_distance_4_arm_neon +- +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_4_arm_neon( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- uint8x8_t v_fa = {0}; +- uint8x8_t v_fb = {0}; +- uint8x8_t v_fc = {0}; +- uint8x8_t v_fx = {0}; +- uint16x8_t v_fafb = {0}; +- uint16x8_t v_fcfc = {0}; +- uint16x8_t v_pa = {0}; +- uint16x8_t v_pb = {0}; +- uint16x8_t v_pc = {0}; +- uint16x8_t v_cmpab = {0}; +- uint16x8_t v_cmpac = {0}; +- uint8x8_t v_picka = {0}; +- uint8x8_t v_pickb = {0}; ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_tell_me_more = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_tell_me_more.v_zlib_status = v_zlib_status; + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8); +- while (v_curr.ptr < i_end0_curr) { +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fafb = vaddl_u8(v_fa, v_fb); +- v_fcfc = vaddl_u8(v_fc, v_fc); +- v_pa = vabdl_u8(v_fb, v_fc); +- v_pb = vabdl_u8(v_fa, v_fc); +- v_pc = vabdq_u16(v_fafb, v_fcfc); +- v_cmpab = vcleq_u16(v_pa, v_pb); +- v_cmpac = vcleq_u16(v_pa, v_pc); +- v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); +- v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); +- v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fc = v_fb; +- v_fa = v_fx; +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fafb = vaddl_u8(v_fa, v_fb); +- v_fcfc = vaddl_u8(v_fc, v_fc); +- v_pa = vabdl_u8(v_fb, v_fc); +- v_pb = vabdl_u8(v_fa, v_fc); +- v_pc = vabdq_u16(v_fafb, v_fcfc); +- v_cmpab = vcleq_u16(v_pa, v_pb); +- v_cmpac = vcleq_u16(v_pa, v_pc); +- v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); +- v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); +- v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fc = v_fb; +- v_fa = v_fx; +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- } +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end1_curr) { +- v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_fafb = vaddl_u8(v_fa, v_fb); +- v_fcfc = vaddl_u8(v_fc, v_fc); +- v_pa = vabdl_u8(v_fb, v_fc); +- v_pb = vabdl_u8(v_fa, v_fc); +- v_pc = vabdq_u16(v_fafb, v_fcfc); +- v_cmpab = vcleq_u16(v_pa, v_pb); +- v_cmpac = vcleq_u16(v_pa, v_pc); +- v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac)); +- v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc)); +- v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc))); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0u)); +- v_fc = v_fb; +- v_fa = v_fx; +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- } +- v_curr.len = 0; +- v_prev.len = 0; ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); + } +- return wuffs_base__make_empty_struct(); +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +-// ‼ WUFFS MULTI-FILE SECTION -arm_neon +- +-// -------- func png.decoder.filter_1 +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr) { +- return (*self->private_impl.choosy_filter_1)(self, a_curr); +-} +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1__choosy_default( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr) { +- uint64_t v_filter_distance = 0; +- uint8_t v_fa = 0; +- uint64_t v_i_start = 0; +- uint64_t v_i = 0; +- +- v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance)); +- v_i_start = 0u; +- while (v_i_start < v_filter_distance) { +- v_fa = 0u; +- v_i = v_i_start; +- while (v_i < ((uint64_t)(a_curr.len))) { +- a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + v_fa)); +- v_fa = a_curr.ptr[v_i]; +- v_i += v_filter_distance; +- } +- v_i_start += 1u; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func png.decoder.filter_1_distance_3_fallback +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1_distance_3_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr) { +- wuffs_base__slice_u8 v_curr = {0}; +- uint8_t v_fa0 = 0; +- uint8_t v_fa1 = 0; +- uint8_t v_fa2 = 0; + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- v_curr.len = 3; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6); +- while (v_curr.ptr < i_end0_curr) { +- v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; +- v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; +- } +- v_curr.len = 3; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3); +- while (v_curr.ptr < i_end1_curr) { +- v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; +- } +- v_curr.len = 0; +- } +- return wuffs_base__make_empty_struct(); ++ return status; + } + +-// -------- func png.decoder.filter_1_distance_4_fallback ++// -------- func png.decoder.workbuf_len + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1_distance_4_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr) { +- wuffs_base__slice_u8 v_curr = {0}; +- uint8_t v_fa0 = 0; +- uint8_t v_fa1 = 0; +- uint8_t v_fa2 = 0; +- uint8_t v_fa3 = 0; +- +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- v_curr.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end0_curr) { +- v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_fa3 = ((uint8_t)(v_fa3 + v_curr.ptr[3u])); +- v_curr.ptr[3u] = v_fa3; +- v_curr.ptr += 4; +- } +- v_curr.len = 0; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_png__decoder__workbuf_len( ++ const wuffs_png__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); + } +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func png.decoder.filter_2 +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_2( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- uint64_t v_n = 0; +- uint64_t v_i = 0; +- +- v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len))); +- v_i = 0u; +- while (v_i < v_n) { +- a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + a_prev.ptr[v_i])); +- v_i += 1u; ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); + } +- return wuffs_base__make_empty_struct(); ++ ++ return wuffs_base__utility__make_range_ii_u64(self->private_impl.f_overall_workbuf_length, self->private_impl.f_overall_workbuf_length); + } + +-// -------- func png.decoder.filter_3 ++// -------- func png.decoder.filter_and_swizzle + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3( ++static wuffs_base__status ++wuffs_png__decoder__filter_and_swizzle( + wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- return (*self->private_impl.choosy_filter_3)(self, a_curr, a_prev); ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf) { ++ return (*self->private_impl.choosy_filter_and_swizzle)(self, a_dst, a_workbuf); + } + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3__choosy_default( ++static wuffs_base__status ++wuffs_png__decoder__filter_and_swizzle__choosy_default( + wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- uint64_t v_filter_distance = 0; +- uint64_t v_n = 0; +- uint64_t v_i = 0; ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint64_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row0 = 0; ++ uint64_t v_dst_bytes_per_row1 = 0; ++ wuffs_base__slice_u8 v_dst_palette = {0}; ++ wuffs_base__table_u8 v_tab = {0}; ++ uint32_t v_y = 0; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint8_t v_filter = 0; ++ wuffs_base__slice_u8 v_curr_row = {0}; ++ wuffs_base__slice_u8 v_prev_row = {0}; + +- v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance)); +- if (((uint64_t)(a_prev.len)) == 0u) { +- v_i = v_filter_distance; +- while (v_i < ((uint64_t)(a_curr.len))) { +- a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + (a_curr.ptr[(v_i - v_filter_distance)] / 2u))); +- v_i += 1u; +- } ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ } ++ v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8u))); ++ v_dst_bytes_per_row0 = (((uint64_t)(self->private_impl.f_frame_rect_x0)) * v_dst_bytes_per_pixel); ++ v_dst_bytes_per_row1 = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * v_dst_bytes_per_pixel); ++ v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ if (v_dst_bytes_per_row1 < ((uint64_t)(v_tab.width))) { ++ v_tab = wuffs_base__table_u8__subtable_ij(v_tab, ++ 0u, ++ 0u, ++ v_dst_bytes_per_row1, ++ ((uint64_t)(v_tab.height))); ++ } ++ if (v_dst_bytes_per_row0 < ((uint64_t)(v_tab.width))) { ++ v_tab = wuffs_base__table_u8__subtable_ij(v_tab, ++ v_dst_bytes_per_row0, ++ 0u, ++ ((uint64_t)(v_tab.width)), ++ ((uint64_t)(v_tab.height))); + } else { +- v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len))); +- v_i = 0u; +- while ((v_i < v_n) && (v_i < v_filter_distance)) { +- a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + (a_prev.ptr[v_i] / 2u))); +- v_i += 1u; ++ v_tab = wuffs_base__table_u8__subtable_ij(v_tab, ++ 0u, ++ 0u, ++ 0u, ++ 0u); ++ } ++ v_y = self->private_impl.f_frame_rect_y0; ++ while (v_y < self->private_impl.f_frame_rect_y1) { ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, v_y); ++ if (1u > ((uint64_t)(a_workbuf.len))) { ++ return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length); + } +- v_i = v_filter_distance; +- while (v_i < v_n) { +- a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)(((((uint32_t)(a_curr.ptr[(v_i - v_filter_distance)])) + ((uint32_t)(a_prev.ptr[v_i]))) / 2u))))); +- v_i += 1u; ++ v_filter = a_workbuf.ptr[0u]; ++ a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, 1u); ++ if (self->private_impl.f_pass_bytes_per_row > ((uint64_t)(a_workbuf.len))) { ++ return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length); ++ } ++ v_curr_row = wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_pass_bytes_per_row); ++ a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, self->private_impl.f_pass_bytes_per_row); ++ if (v_filter == 0u) { ++ } else if (v_filter == 1u) { ++ wuffs_png__decoder__filter_1(self, v_curr_row); ++ } else if (v_filter == 2u) { ++ wuffs_png__decoder__filter_2(self, v_curr_row, v_prev_row); ++ } else if (v_filter == 3u) { ++ wuffs_png__decoder__filter_3(self, v_curr_row, v_prev_row); ++ } else if (v_filter == 4u) { ++ wuffs_png__decoder__filter_4(self, v_curr_row, v_prev_row); ++ } else { ++ return wuffs_base__make_status(wuffs_png__error__bad_filter); + } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, v_curr_row); ++ v_prev_row = v_curr_row; ++ v_y += 1u; + } +- return wuffs_base__make_empty_struct(); ++ return wuffs_base__make_status(NULL); + } + +-// -------- func png.decoder.filter_3_distance_3_fallback ++// -------- func png.decoder.filter_and_swizzle_tricky + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3_distance_3_fallback( ++static wuffs_base__status ++wuffs_png__decoder__filter_and_swizzle_tricky( + wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- uint8_t v_fa0 = 0; +- uint8_t v_fa1 = 0; +- uint8_t v_fa2 = 0; ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint64_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row1 = 0; ++ wuffs_base__slice_u8 v_dst_palette = {0}; ++ wuffs_base__table_u8 v_tab = {0}; ++ uint64_t v_src_bytes_per_pixel = 0; ++ uint32_t v_x = 0; ++ uint32_t v_y = 0; ++ uint64_t v_i = 0; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint8_t v_filter = 0; ++ wuffs_base__slice_u8 v_s = {0}; ++ wuffs_base__slice_u8 v_curr_row = {0}; ++ wuffs_base__slice_u8 v_prev_row = {0}; ++ uint8_t v_bits_unpacked[8] = {0}; ++ uint8_t v_bits_packed = 0; ++ uint8_t v_packs_remaining = 0; ++ uint8_t v_multiplier = 0; ++ uint8_t v_shift = 0; + +- if (((uint64_t)(a_prev.len)) == 0u) { +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- v_curr.len = 3; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6); +- while (v_curr.ptr < i_end0_curr) { +- v_fa0 = ((uint8_t)((v_fa0 / 2u) + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)((v_fa1 / 2u) + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)((v_fa2 / 2u) + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; +- v_fa0 = ((uint8_t)((v_fa0 / 2u) + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)((v_fa1 / 2u) + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)((v_fa2 / 2u) + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ } ++ v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8u))); ++ v_dst_bytes_per_row1 = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * v_dst_bytes_per_pixel); ++ v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ v_src_bytes_per_pixel = 1u; ++ if (self->private_impl.f_depth >= 8u) { ++ v_src_bytes_per_pixel = (((uint64_t)(WUFFS_PNG__NUM_CHANNELS[self->private_impl.f_color_type])) * ((uint64_t)(((uint8_t)(self->private_impl.f_depth >> 3u))))); ++ } ++ if (self->private_impl.f_chunk_type_array[0u] == 73u) { ++ v_y = ((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][5u])); ++ } else { ++ v_y = self->private_impl.f_frame_rect_y0; ++ } ++ while (v_y < self->private_impl.f_frame_rect_y1) { ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, v_y); ++ if (v_dst_bytes_per_row1 < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row1); ++ } ++ if (1u > ((uint64_t)(a_workbuf.len))) { ++ return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length); ++ } ++ v_filter = a_workbuf.ptr[0u]; ++ a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, 1u); ++ if (self->private_impl.f_pass_bytes_per_row > ((uint64_t)(a_workbuf.len))) { ++ return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length); ++ } ++ v_curr_row = wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_pass_bytes_per_row); ++ a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, self->private_impl.f_pass_bytes_per_row); ++ if (v_filter == 0u) { ++ } else if (v_filter == 1u) { ++ wuffs_png__decoder__filter_1(self, v_curr_row); ++ } else if (v_filter == 2u) { ++ wuffs_png__decoder__filter_2(self, v_curr_row, v_prev_row); ++ } else if (v_filter == 3u) { ++ wuffs_png__decoder__filter_3(self, v_curr_row, v_prev_row); ++ } else if (v_filter == 4u) { ++ wuffs_png__decoder__filter_4(self, v_curr_row, v_prev_row); ++ } else { ++ return wuffs_base__make_status(wuffs_png__error__bad_filter); ++ } ++ v_s = v_curr_row; ++ if (self->private_impl.f_chunk_type_array[0u] == 73u) { ++ v_x = ((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][2u])); ++ } else { ++ v_x = self->private_impl.f_frame_rect_x0; ++ } ++ if (self->private_impl.f_depth == 8u) { ++ while (v_x < self->private_impl.f_frame_rect_x1) { ++ v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel); ++ if (v_i <= ((uint64_t)(v_dst.len))) { ++ if (((uint32_t)(self->private_impl.f_remap_transparency)) != 0u) { ++ if (self->private_impl.f_color_type == 0u) { ++ if (1u <= ((uint64_t)(v_s.len))) { ++ v_bits_unpacked[0u] = v_s.ptr[0u]; ++ v_bits_unpacked[1u] = v_s.ptr[0u]; ++ v_bits_unpacked[2u] = v_s.ptr[0u]; ++ v_bits_unpacked[3u] = 255u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 1u); ++ if (((uint32_t)(self->private_impl.f_remap_transparency)) == ((((uint32_t)(v_bits_unpacked[0u])) << 0u) | ++ (((uint32_t)(v_bits_unpacked[1u])) << 8u) | ++ (((uint32_t)(v_bits_unpacked[2u])) << 16u) | ++ (((uint32_t)(v_bits_unpacked[3u])) << 24u))) { ++ v_bits_unpacked[0u] = 0u; ++ v_bits_unpacked[1u] = 0u; ++ v_bits_unpacked[2u] = 0u; ++ v_bits_unpacked[3u] = 0u; ++ } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4)); ++ } ++ } else { ++ if (3u <= ((uint64_t)(v_s.len))) { ++ v_bits_unpacked[0u] = v_s.ptr[2u]; ++ v_bits_unpacked[1u] = v_s.ptr[1u]; ++ v_bits_unpacked[2u] = v_s.ptr[0u]; ++ v_bits_unpacked[3u] = 255u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 3u); ++ if (((uint32_t)(self->private_impl.f_remap_transparency)) == ((((uint32_t)(v_bits_unpacked[0u])) << 0u) | ++ (((uint32_t)(v_bits_unpacked[1u])) << 8u) | ++ (((uint32_t)(v_bits_unpacked[2u])) << 16u) | ++ (((uint32_t)(v_bits_unpacked[3u])) << 24u))) { ++ v_bits_unpacked[0u] = 0u; ++ v_bits_unpacked[1u] = 0u; ++ v_bits_unpacked[2u] = 0u; ++ v_bits_unpacked[3u] = 0u; ++ } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4)); ++ } ++ } ++ } else if (v_src_bytes_per_pixel <= ((uint64_t)(v_s.len))) { ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__slice_u8__subslice_j(v_s, v_src_bytes_per_pixel)); ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, v_src_bytes_per_pixel); ++ } ++ } ++ v_x += (((uint32_t)(1u)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0u]); + } +- v_curr.len = 3; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3); +- while (v_curr.ptr < i_end1_curr) { +- v_fa0 = ((uint8_t)((v_fa0 / 2u) + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)((v_fa1 / 2u) + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)((v_fa2 / 2u) + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; ++ } else if (self->private_impl.f_depth < 8u) { ++ v_multiplier = 1u; ++ if (self->private_impl.f_color_type == 0u) { ++ v_multiplier = WUFFS_PNG__LOW_BIT_DEPTH_MULTIPLIERS[self->private_impl.f_depth]; + } +- v_curr.len = 0; +- } +- } else { +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 3; +- v_prev.len = 3; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6); +- while (v_curr.ptr < i_end0_curr) { +- v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0u]))) / 2u))) + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1u]))) / 2u))) + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2u]))) / 2u))) + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0u]))) / 2u))) + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1u]))) / 2u))) + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2u]))) / 2u))) + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; +- v_prev.ptr += 3; ++ v_shift = ((uint8_t)(((uint8_t)(8u - self->private_impl.f_depth)) & 7u)); ++ v_packs_remaining = 0u; ++ while (v_x < self->private_impl.f_frame_rect_x1) { ++ v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel); ++ if (v_i <= ((uint64_t)(v_dst.len))) { ++ if ((v_packs_remaining == 0u) && (1u <= ((uint64_t)(v_s.len)))) { ++ v_packs_remaining = WUFFS_PNG__LOW_BIT_DEPTH_NUM_PACKS[self->private_impl.f_depth]; ++ v_bits_packed = v_s.ptr[0u]; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 1u); ++ } ++ v_bits_unpacked[0u] = ((uint8_t)(((uint8_t)(v_bits_packed >> v_shift)) * v_multiplier)); ++ v_bits_packed = ((uint8_t)(v_bits_packed << self->private_impl.f_depth)); ++ v_packs_remaining = ((uint8_t)(v_packs_remaining - 1u)); ++ if (((uint32_t)(self->private_impl.f_remap_transparency)) != 0u) { ++ v_bits_unpacked[1u] = v_bits_unpacked[0u]; ++ v_bits_unpacked[2u] = v_bits_unpacked[0u]; ++ v_bits_unpacked[3u] = 255u; ++ if (((uint32_t)(self->private_impl.f_remap_transparency)) == ((((uint32_t)(v_bits_unpacked[0u])) << 0u) | ++ (((uint32_t)(v_bits_unpacked[1u])) << 8u) | ++ (((uint32_t)(v_bits_unpacked[2u])) << 16u) | ++ (((uint32_t)(v_bits_unpacked[3u])) << 24u))) { ++ v_bits_unpacked[0u] = 0u; ++ v_bits_unpacked[1u] = 0u; ++ v_bits_unpacked[2u] = 0u; ++ v_bits_unpacked[3u] = 0u; ++ } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4)); ++ } else { ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 1)); ++ } ++ } ++ v_x += (((uint32_t)(1u)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0u]); + } +- v_curr.len = 3; +- v_prev.len = 3; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3); +- while (v_curr.ptr < i_end1_curr) { +- v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0u]))) / 2u))) + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1u]))) / 2u))) + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2u]))) / 2u))) + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_curr.ptr += 3; +- v_prev.ptr += 3; ++ } else { ++ while (v_x < self->private_impl.f_frame_rect_x1) { ++ v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel); ++ if (v_i <= ((uint64_t)(v_dst.len))) { ++ if (self->private_impl.f_color_type == 0u) { ++ if (2u <= ((uint64_t)(v_s.len))) { ++ v_bits_unpacked[0u] = v_s.ptr[1u]; ++ v_bits_unpacked[1u] = v_s.ptr[0u]; ++ v_bits_unpacked[2u] = v_s.ptr[1u]; ++ v_bits_unpacked[3u] = v_s.ptr[0u]; ++ v_bits_unpacked[4u] = v_s.ptr[1u]; ++ v_bits_unpacked[5u] = v_s.ptr[0u]; ++ v_bits_unpacked[6u] = 255u; ++ v_bits_unpacked[7u] = 255u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 2u); ++ if (self->private_impl.f_remap_transparency == ((((uint64_t)(v_bits_unpacked[0u])) << 0u) | ++ (((uint64_t)(v_bits_unpacked[1u])) << 8u) | ++ (((uint64_t)(v_bits_unpacked[2u])) << 16u) | ++ (((uint64_t)(v_bits_unpacked[3u])) << 24u) | ++ (((uint64_t)(v_bits_unpacked[4u])) << 32u) | ++ (((uint64_t)(v_bits_unpacked[5u])) << 40u) | ++ (((uint64_t)(v_bits_unpacked[6u])) << 48u) | ++ (((uint64_t)(v_bits_unpacked[7u])) << 56u))) { ++ v_bits_unpacked[0u] = 0u; ++ v_bits_unpacked[1u] = 0u; ++ v_bits_unpacked[2u] = 0u; ++ v_bits_unpacked[3u] = 0u; ++ v_bits_unpacked[4u] = 0u; ++ v_bits_unpacked[5u] = 0u; ++ v_bits_unpacked[6u] = 0u; ++ v_bits_unpacked[7u] = 0u; ++ } ++ } ++ } else if (self->private_impl.f_color_type == 2u) { ++ if (6u <= ((uint64_t)(v_s.len))) { ++ v_bits_unpacked[0u] = v_s.ptr[5u]; ++ v_bits_unpacked[1u] = v_s.ptr[4u]; ++ v_bits_unpacked[2u] = v_s.ptr[3u]; ++ v_bits_unpacked[3u] = v_s.ptr[2u]; ++ v_bits_unpacked[4u] = v_s.ptr[1u]; ++ v_bits_unpacked[5u] = v_s.ptr[0u]; ++ v_bits_unpacked[6u] = 255u; ++ v_bits_unpacked[7u] = 255u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 6u); ++ if (self->private_impl.f_remap_transparency == ((((uint64_t)(v_bits_unpacked[0u])) << 0u) | ++ (((uint64_t)(v_bits_unpacked[1u])) << 8u) | ++ (((uint64_t)(v_bits_unpacked[2u])) << 16u) | ++ (((uint64_t)(v_bits_unpacked[3u])) << 24u) | ++ (((uint64_t)(v_bits_unpacked[4u])) << 32u) | ++ (((uint64_t)(v_bits_unpacked[5u])) << 40u) | ++ (((uint64_t)(v_bits_unpacked[6u])) << 48u) | ++ (((uint64_t)(v_bits_unpacked[7u])) << 56u))) { ++ v_bits_unpacked[0u] = 0u; ++ v_bits_unpacked[1u] = 0u; ++ v_bits_unpacked[2u] = 0u; ++ v_bits_unpacked[3u] = 0u; ++ v_bits_unpacked[4u] = 0u; ++ v_bits_unpacked[5u] = 0u; ++ v_bits_unpacked[6u] = 0u; ++ v_bits_unpacked[7u] = 0u; ++ } ++ } ++ } else if (self->private_impl.f_color_type == 4u) { ++ if (4u <= ((uint64_t)(v_s.len))) { ++ v_bits_unpacked[0u] = v_s.ptr[1u]; ++ v_bits_unpacked[1u] = v_s.ptr[0u]; ++ v_bits_unpacked[2u] = v_s.ptr[1u]; ++ v_bits_unpacked[3u] = v_s.ptr[0u]; ++ v_bits_unpacked[4u] = v_s.ptr[1u]; ++ v_bits_unpacked[5u] = v_s.ptr[0u]; ++ v_bits_unpacked[6u] = v_s.ptr[3u]; ++ v_bits_unpacked[7u] = v_s.ptr[2u]; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ } ++ } else { ++ if (8u <= ((uint64_t)(v_s.len))) { ++ v_bits_unpacked[0u] = v_s.ptr[5u]; ++ v_bits_unpacked[1u] = v_s.ptr[4u]; ++ v_bits_unpacked[2u] = v_s.ptr[3u]; ++ v_bits_unpacked[3u] = v_s.ptr[2u]; ++ v_bits_unpacked[4u] = v_s.ptr[1u]; ++ v_bits_unpacked[5u] = v_s.ptr[0u]; ++ v_bits_unpacked[6u] = v_s.ptr[7u]; ++ v_bits_unpacked[7u] = v_s.ptr[6u]; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 8u); ++ } ++ } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 8)); ++ } ++ v_x += (((uint32_t)(1u)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0u]); + } +- v_curr.len = 0; +- v_prev.len = 0; + } ++ v_prev_row = v_curr_row; ++ v_y += (((uint32_t)(1u)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][3u]); + } +- return wuffs_base__make_empty_struct(); ++ return wuffs_base__make_status(NULL); + } + +-// -------- func png.decoder.filter_3_distance_4_fallback ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__QOI) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_qoi__error__bad_footer[] = "#qoi: bad footer"; ++const char wuffs_qoi__error__bad_header[] = "#qoi: bad header"; ++const char wuffs_qoi__error__truncated_input[] = "#qoi: truncated input"; ++ ++// ---------------- Private Consts ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3_distance_4_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- uint8_t v_fa0 = 0; +- uint8_t v_fa1 = 0; +- uint8_t v_fa2 = 0; +- uint8_t v_fa3 = 0; ++static wuffs_base__status ++wuffs_qoi__decoder__do_decode_image_config( ++ wuffs_qoi__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_qoi__decoder__do_decode_frame_config( ++ wuffs_qoi__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_qoi__decoder__do_decode_frame( ++ wuffs_qoi__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_qoi__decoder__from_src_to_buffer( ++ wuffs_qoi__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_qoi__decoder__from_buffer_to_dst( ++ wuffs_qoi__decoder* self, ++ wuffs_base__pixel_buffer* a_dst); ++ ++// ---------------- VTables ++ ++const wuffs_base__image_decoder__func_ptrs ++wuffs_qoi__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_qoi__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_qoi__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_qoi__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_qoi__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_qoi__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_qoi__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_qoi__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_qoi__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_qoi__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_qoi__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_qoi__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_qoi__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_qoi__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_qoi__decoder__initialize( ++ wuffs_qoi__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } + +- if (((uint64_t)(a_prev.len)) == 0u) { +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- v_curr.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end0_curr) { +- v_fa0 = ((uint8_t)((v_fa0 / 2u) + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)((v_fa1 / 2u) + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)((v_fa2 / 2u) + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_fa3 = ((uint8_t)((v_fa3 / 2u) + v_curr.ptr[3u])); +- v_curr.ptr[3u] = v_fa3; +- v_curr.ptr += 4; +- } +- v_curr.len = 0; ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); + } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif + } else { +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end0_curr) { +- v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0u]))) / 2u))) + v_curr.ptr[0u])); +- v_curr.ptr[0u] = v_fa0; +- v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1u]))) / 2u))) + v_curr.ptr[1u])); +- v_curr.ptr[1u] = v_fa1; +- v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2u]))) / 2u))) + v_curr.ptr[2u])); +- v_curr.ptr[2u] = v_fa2; +- v_fa3 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa3)) + ((uint32_t)(v_prev.ptr[3u]))) / 2u))) + v_curr.ptr[3u])); +- v_curr.ptr[3u] = v_fa3; +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- } +- v_curr.len = 0; +- v_prev.len = 0; ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); + } + } +- return wuffs_base__make_empty_struct(); ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_qoi__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); + } + +-// -------- func png.decoder.filter_4 ++wuffs_qoi__decoder* ++wuffs_qoi__decoder__alloc(void) { ++ wuffs_qoi__decoder* x = ++ (wuffs_qoi__decoder*)(calloc(1, sizeof(wuffs_qoi__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_qoi__decoder__initialize( ++ x, sizeof(wuffs_qoi__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- return (*self->private_impl.choosy_filter_4)(self, a_curr, a_prev); ++size_t ++sizeof__wuffs_qoi__decoder(void) { ++ return sizeof(wuffs_qoi__decoder); + } + ++// ---------------- Function Implementations ++ ++// -------- func qoi.decoder.get_quirk ++ + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4__choosy_default( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- uint64_t v_filter_distance = 0; +- uint64_t v_n = 0; +- uint64_t v_i = 0; +- uint32_t v_fa = 0; +- uint32_t v_fb = 0; +- uint32_t v_fc = 0; +- uint32_t v_pp = 0; +- uint32_t v_pa = 0; +- uint32_t v_pb = 0; +- uint32_t v_pc = 0; ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_qoi__decoder__get_quirk( ++ const wuffs_qoi__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } + +- v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance)); +- v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len))); +- v_i = 0u; +- while ((v_i < v_n) && (v_i < v_filter_distance)) { +- a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + a_prev.ptr[v_i])); +- v_i += 1u; ++ return 0u; ++} ++ ++// -------- func qoi.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_qoi__decoder__set_quirk( ++ wuffs_qoi__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- v_i = v_filter_distance; +- while (v_i < v_n) { +- v_fa = ((uint32_t)(a_curr.ptr[(v_i - v_filter_distance)])); +- v_fb = ((uint32_t)(a_prev.ptr[v_i])); +- v_fc = ((uint32_t)(a_prev.ptr[(v_i - v_filter_distance)])); +- v_pp = ((uint32_t)(((uint32_t)(v_fa + v_fb)) - v_fc)); +- v_pa = ((uint32_t)(v_pp - v_fa)); +- if (v_pa >= 2147483648u) { +- v_pa = ((uint32_t)(0u - v_pa)); +- } +- v_pb = ((uint32_t)(v_pp - v_fb)); +- if (v_pb >= 2147483648u) { +- v_pb = ((uint32_t)(0u - v_pb)); +- } +- v_pc = ((uint32_t)(v_pp - v_fc)); +- if (v_pc >= 2147483648u) { +- v_pc = ((uint32_t)(0u - v_pc)); +- } +- if ((v_pa <= v_pb) && (v_pa <= v_pc)) { +- } else if (v_pb <= v_pc) { +- v_fa = v_fb; +- } else { +- v_fa = v_fc; +- } +- a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)(v_fa)))); +- v_i += 1u; ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } +- return wuffs_base__make_empty_struct(); ++ ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func png.decoder.filter_4_distance_3_fallback ++// -------- func qoi.decoder.decode_image_config + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_3_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- uint32_t v_fa0 = 0; +- uint32_t v_fa1 = 0; +- uint32_t v_fa2 = 0; +- uint32_t v_fb0 = 0; +- uint32_t v_fb1 = 0; +- uint32_t v_fb2 = 0; +- uint32_t v_fc0 = 0; +- uint32_t v_fc1 = 0; +- uint32_t v_fc2 = 0; +- uint32_t v_pp0 = 0; +- uint32_t v_pp1 = 0; +- uint32_t v_pp2 = 0; +- uint32_t v_pa0 = 0; +- uint32_t v_pa1 = 0; +- uint32_t v_pa2 = 0; +- uint32_t v_pb0 = 0; +- uint32_t v_pb1 = 0; +- uint32_t v_pb2 = 0; +- uint32_t v_pc0 = 0; +- uint32_t v_pc1 = 0; +- uint32_t v_pc2 = 0; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_qoi__decoder__decode_image_config( ++ wuffs_qoi__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 3; +- v_prev.len = 3; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3); +- while (v_curr.ptr < i_end0_curr) { +- v_fb0 = ((uint32_t)(v_prev.ptr[0u])); +- v_pp0 = ((uint32_t)(((uint32_t)(v_fa0 + v_fb0)) - v_fc0)); +- v_pa0 = ((uint32_t)(v_pp0 - v_fa0)); +- if (v_pa0 >= 2147483648u) { +- v_pa0 = ((uint32_t)(0u - v_pa0)); +- } +- v_pb0 = ((uint32_t)(v_pp0 - v_fb0)); +- if (v_pb0 >= 2147483648u) { +- v_pb0 = ((uint32_t)(0u - v_pb0)); +- } +- v_pc0 = ((uint32_t)(v_pp0 - v_fc0)); +- if (v_pc0 >= 2147483648u) { +- v_pc0 = ((uint32_t)(0u - v_pc0)); +- } +- if ((v_pa0 <= v_pb0) && (v_pa0 <= v_pc0)) { +- } else if (v_pb0 <= v_pc0) { +- v_fa0 = v_fb0; +- } else { +- v_fa0 = v_fc0; +- } +- v_curr.ptr[0u] = ((uint8_t)(v_curr.ptr[0u] + ((uint8_t)(v_fa0)))); +- v_fa0 = ((uint32_t)(v_curr.ptr[0u])); +- v_fc0 = v_fb0; +- v_fb1 = ((uint32_t)(v_prev.ptr[1u])); +- v_pp1 = ((uint32_t)(((uint32_t)(v_fa1 + v_fb1)) - v_fc1)); +- v_pa1 = ((uint32_t)(v_pp1 - v_fa1)); +- if (v_pa1 >= 2147483648u) { +- v_pa1 = ((uint32_t)(0u - v_pa1)); +- } +- v_pb1 = ((uint32_t)(v_pp1 - v_fb1)); +- if (v_pb1 >= 2147483648u) { +- v_pb1 = ((uint32_t)(0u - v_pb1)); +- } +- v_pc1 = ((uint32_t)(v_pp1 - v_fc1)); +- if (v_pc1 >= 2147483648u) { +- v_pc1 = ((uint32_t)(0u - v_pc1)); +- } +- if ((v_pa1 <= v_pb1) && (v_pa1 <= v_pc1)) { +- } else if (v_pb1 <= v_pc1) { +- v_fa1 = v_fb1; +- } else { +- v_fa1 = v_fc1; +- } +- v_curr.ptr[1u] = ((uint8_t)(v_curr.ptr[1u] + ((uint8_t)(v_fa1)))); +- v_fa1 = ((uint32_t)(v_curr.ptr[1u])); +- v_fc1 = v_fb1; +- v_fb2 = ((uint32_t)(v_prev.ptr[2u])); +- v_pp2 = ((uint32_t)(((uint32_t)(v_fa2 + v_fb2)) - v_fc2)); +- v_pa2 = ((uint32_t)(v_pp2 - v_fa2)); +- if (v_pa2 >= 2147483648u) { +- v_pa2 = ((uint32_t)(0u - v_pa2)); +- } +- v_pb2 = ((uint32_t)(v_pp2 - v_fb2)); +- if (v_pb2 >= 2147483648u) { +- v_pb2 = ((uint32_t)(0u - v_pb2)); +- } +- v_pc2 = ((uint32_t)(v_pp2 - v_fc2)); +- if (v_pc2 >= 2147483648u) { +- v_pc2 = ((uint32_t)(0u - v_pc2)); ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_qoi__decoder__do_decode_image_config(self, a_dst, a_src); ++ v_status = t_0; + } +- if ((v_pa2 <= v_pb2) && (v_pa2 <= v_pc2)) { +- } else if (v_pb2 <= v_pc2) { +- v_fa2 = v_fb2; +- } else { +- v_fa2 = v_fc2; ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_qoi__error__truncated_input); ++ goto exit; + } +- v_curr.ptr[2u] = ((uint8_t)(v_curr.ptr[2u] + ((uint8_t)(v_fa2)))); +- v_fa2 = ((uint32_t)(v_curr.ptr[2u])); +- v_fc2 = v_fb2; +- v_curr.ptr += 3; +- v_prev.ptr += 3; ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } +- v_curr.len = 0; +- v_prev.len = 0; ++ ++ ok: ++ self->private_impl.p_decode_image_config = 0; ++ goto exit; + } +- return wuffs_base__make_empty_struct(); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; + } + +-// -------- func png.decoder.filter_4_distance_4_fallback ++// -------- func qoi.decoder.do_decode_image_config + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_4_fallback( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- uint32_t v_fa0 = 0; +- uint32_t v_fa1 = 0; +- uint32_t v_fa2 = 0; +- uint32_t v_fa3 = 0; +- uint32_t v_fb0 = 0; +- uint32_t v_fb1 = 0; +- uint32_t v_fb2 = 0; +- uint32_t v_fb3 = 0; +- uint32_t v_fc0 = 0; +- uint32_t v_fc1 = 0; +- uint32_t v_fc2 = 0; +- uint32_t v_fc3 = 0; +- uint32_t v_pp0 = 0; +- uint32_t v_pp1 = 0; +- uint32_t v_pp2 = 0; +- uint32_t v_pp3 = 0; +- uint32_t v_pa0 = 0; +- uint32_t v_pa1 = 0; +- uint32_t v_pa2 = 0; +- uint32_t v_pa3 = 0; +- uint32_t v_pb0 = 0; +- uint32_t v_pb1 = 0; +- uint32_t v_pb2 = 0; +- uint32_t v_pb3 = 0; +- uint32_t v_pc0 = 0; +- uint32_t v_pc1 = 0; +- uint32_t v_pc2 = 0; +- uint32_t v_pc3 = 0; ++static wuffs_base__status ++wuffs_qoi__decoder__do_decode_image_config( ++ wuffs_qoi__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end0_curr) { +- v_fb0 = ((uint32_t)(v_prev.ptr[0u])); +- v_pp0 = ((uint32_t)(((uint32_t)(v_fa0 + v_fb0)) - v_fc0)); +- v_pa0 = ((uint32_t)(v_pp0 - v_fa0)); +- if (v_pa0 >= 2147483648u) { +- v_pa0 = ((uint32_t)(0u - v_pa0)); +- } +- v_pb0 = ((uint32_t)(v_pp0 - v_fb0)); +- if (v_pb0 >= 2147483648u) { +- v_pb0 = ((uint32_t)(0u - v_pb0)); +- } +- v_pc0 = ((uint32_t)(v_pp0 - v_fc0)); +- if (v_pc0 >= 2147483648u) { +- v_pc0 = ((uint32_t)(0u - v_pc0)); +- } +- if ((v_pa0 <= v_pb0) && (v_pa0 <= v_pc0)) { +- } else if (v_pb0 <= v_pc0) { +- v_fa0 = v_fb0; +- } else { +- v_fa0 = v_fc0; +- } +- v_curr.ptr[0u] = ((uint8_t)(v_curr.ptr[0u] + ((uint8_t)(v_fa0)))); +- v_fa0 = ((uint32_t)(v_curr.ptr[0u])); +- v_fc0 = v_fb0; +- v_fb1 = ((uint32_t)(v_prev.ptr[1u])); +- v_pp1 = ((uint32_t)(((uint32_t)(v_fa1 + v_fb1)) - v_fc1)); +- v_pa1 = ((uint32_t)(v_pp1 - v_fa1)); +- if (v_pa1 >= 2147483648u) { +- v_pa1 = ((uint32_t)(0u - v_pa1)); +- } +- v_pb1 = ((uint32_t)(v_pp1 - v_fb1)); +- if (v_pb1 >= 2147483648u) { +- v_pb1 = ((uint32_t)(0u - v_pb1)); +- } +- v_pc1 = ((uint32_t)(v_pp1 - v_fc1)); +- if (v_pc1 >= 2147483648u) { +- v_pc1 = ((uint32_t)(0u - v_pc1)); +- } +- if ((v_pa1 <= v_pb1) && (v_pa1 <= v_pc1)) { +- } else if (v_pb1 <= v_pc1) { +- v_fa1 = v_fb1; ++ uint32_t v_a = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_image_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; + } else { +- v_fa1 = v_fc1; +- } +- v_curr.ptr[1u] = ((uint8_t)(v_curr.ptr[1u] + ((uint8_t)(v_fa1)))); +- v_fa1 = ((uint32_t)(v_curr.ptr[1u])); +- v_fc1 = v_fb1; +- v_fb2 = ((uint32_t)(v_prev.ptr[2u])); +- v_pp2 = ((uint32_t)(((uint32_t)(v_fa2 + v_fb2)) - v_fc2)); +- v_pa2 = ((uint32_t)(v_pp2 - v_fa2)); +- if (v_pa2 >= 2147483648u) { +- v_pa2 = ((uint32_t)(0u - v_pa2)); +- } +- v_pb2 = ((uint32_t)(v_pp2 - v_fb2)); +- if (v_pb2 >= 2147483648u) { +- v_pb2 = ((uint32_t)(0u - v_pb2)); +- } +- v_pc2 = ((uint32_t)(v_pp2 - v_fc2)); +- if (v_pc2 >= 2147483648u) { +- v_pc2 = ((uint32_t)(0u - v_pc2)); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } + } +- if ((v_pa2 <= v_pb2) && (v_pa2 <= v_pc2)) { +- } else if (v_pb2 <= v_pc2) { +- v_fa2 = v_fb2; ++ v_a = t_0; ++ } ++ if (v_a != 1718185841u) { ++ status = wuffs_base__make_status(wuffs_qoi__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; + } else { +- v_fa2 = v_fc2; +- } +- v_curr.ptr[2u] = ((uint8_t)(v_curr.ptr[2u] + ((uint8_t)(v_fa2)))); +- v_fa2 = ((uint32_t)(v_curr.ptr[2u])); +- v_fc2 = v_fb2; +- v_fb3 = ((uint32_t)(v_prev.ptr[3u])); +- v_pp3 = ((uint32_t)(((uint32_t)(v_fa3 + v_fb3)) - v_fc3)); +- v_pa3 = ((uint32_t)(v_pp3 - v_fa3)); +- if (v_pa3 >= 2147483648u) { +- v_pa3 = ((uint32_t)(0u - v_pa3)); +- } +- v_pb3 = ((uint32_t)(v_pp3 - v_fb3)); +- if (v_pb3 >= 2147483648u) { +- v_pb3 = ((uint32_t)(0u - v_pb3)); +- } +- v_pc3 = ((uint32_t)(v_pp3 - v_fc3)); +- if (v_pc3 >= 2147483648u) { +- v_pc3 = ((uint32_t)(0u - v_pc3)); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)); ++ } + } +- if ((v_pa3 <= v_pb3) && (v_pa3 <= v_pc3)) { +- } else if (v_pb3 <= v_pc3) { +- v_fa3 = v_fb3; ++ v_a = t_1; ++ } ++ if (v_a > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } ++ self->private_impl.f_width = v_a; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); ++ iop_a_src += 4; + } else { +- v_fa3 = v_fc3; ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); ++ if (num_bits_2 == 24) { ++ t_2 = ((uint32_t)(*scratch >> 32)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)); ++ } + } +- v_curr.ptr[3u] = ((uint8_t)(v_curr.ptr[3u] + ((uint8_t)(v_fa3)))); +- v_fa3 = ((uint32_t)(v_curr.ptr[3u])); +- v_fc3 = v_fb3; +- v_curr.ptr += 4; +- v_prev.ptr += 4; ++ v_a = t_2; + } +- v_curr.len = 0; +- v_prev.len = 0; +- } +- return wuffs_base__make_empty_struct(); +-} ++ if (v_a > 16777215u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); ++ goto exit; ++ } ++ self->private_impl.f_height = v_a; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint32_t t_3 = *iop_a_src++; ++ v_a = t_3; ++ } ++ if (v_a == 3u) { ++ self->private_impl.f_pixfmt = 2415954056u; ++ } else if (v_a == 4u) { ++ self->private_impl.f_pixfmt = 2164295816u; ++ } else { ++ status = wuffs_base__make_status(wuffs_qoi__error__bad_header); ++ goto exit; ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src++; ++ if (a_dst != NULL) { ++ wuffs_base__image_config__set( ++ a_dst, ++ self->private_impl.f_pixfmt, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ 14u, ++ (self->private_impl.f_pixfmt == 2415954056u)); ++ } ++ self->private_impl.f_call_sequence = 32u; + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-// -------- func png.decoder.filter_1_distance_4_x86_sse42 ++ goto ok; ++ ok: ++ self->private_impl.p_do_decode_image_config = 0; ++ goto exit; ++ } + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_1_distance_4_x86_sse42( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr) { +- wuffs_base__slice_u8 v_curr = {0}; +- __m128i v_x128 = {0}; +- __m128i v_a128 = {0}; ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- v_curr.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8); +- while (v_curr.ptr < i_end0_curr) { +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_a128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_a128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- } +- v_curr.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end1_curr) { +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_a128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- } +- v_curr.len = 0; ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- return wuffs_base__make_empty_struct(); ++ ++ return status; + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-// -------- func png.decoder.filter_3_distance_4_x86_sse42 ++// -------- func qoi.decoder.decode_frame_config + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_3_distance_4_x86_sse42( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- __m128i v_x128 = {0}; +- __m128i v_a128 = {0}; +- __m128i v_b128 = {0}; +- __m128i v_p128 = {0}; +- __m128i v_k128 = {0}; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_qoi__decoder__decode_frame_config( ++ wuffs_qoi__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 2)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- if (((uint64_t)(a_prev.len)) == 0u) { +- v_k128 = _mm_set1_epi8((int8_t)(254u)); +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- v_curr.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8); +- while (v_curr.ptr < i_end0_curr) { +- v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- } +- v_curr.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end1_curr) { +- v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- } +- v_curr.len = 0; +- } +- } else { +- v_k128 = _mm_set1_epi8((int8_t)(1u)); +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8); +- while (v_curr.ptr < i_end0_curr) { +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_p128 = _mm_avg_epu8(v_a128, v_b128); +- v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128))); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_p128 = _mm_avg_epu8(v_a128, v_b128); +- v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128))); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- v_prev.ptr += 4; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_qoi__decoder__do_decode_frame_config(self, a_dst, a_src); ++ v_status = t_0; + } +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end1_curr) { +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_p128 = _mm_avg_epu8(v_a128, v_b128); +- v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128))); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- v_prev.ptr += 4; ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_qoi__error__truncated_input); ++ goto exit; + } +- v_curr.len = 0; +- v_prev.len = 0; ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } +- } +- return wuffs_base__make_empty_struct(); +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-// -------- func png.decoder.filter_4_distance_3_x86_sse42 ++ ok: ++ self->private_impl.p_decode_frame_config = 0; ++ goto exit; ++ } + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_3_x86_sse42( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- __m128i v_x128 = {0}; +- __m128i v_a128 = {0}; +- __m128i v_b128 = {0}; +- __m128i v_c128 = {0}; +- __m128i v_p128 = {0}; +- __m128i v_pa128 = {0}; +- __m128i v_pb128 = {0}; +- __m128i v_pc128 = {0}; +- __m128i v_smallest128 = {0}; +- __m128i v_z128 = {0}; ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + wuffs_base__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 7, 6); +- while (v_curr.ptr < i_end0_curr) { +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); +- v_pa128 = _mm_sub_epi16(v_b128, v_c128); +- v_pb128 = _mm_sub_epi16(v_a128, v_c128); +- v_pc128 = _mm_add_epi16(v_pa128, v_pb128); +- v_pa128 = _mm_abs_epi16(v_pa128); +- v_pb128 = _mm_abs_epi16(v_pb128); +- v_pc128 = _mm_abs_epi16(v_pc128); +- v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); +- v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- v_c128 = v_b128; +- v_x128 = _mm_packus_epi16(v_x128, v_x128); +- wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); +- v_pa128 = _mm_sub_epi16(v_b128, v_c128); +- v_pb128 = _mm_sub_epi16(v_a128, v_c128); +- v_pc128 = _mm_add_epi16(v_pa128, v_pb128); +- v_pa128 = _mm_abs_epi16(v_pa128); +- v_pb128 = _mm_abs_epi16(v_pb128); +- v_pc128 = _mm_abs_epi16(v_pc128); +- v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); +- v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- v_c128 = v_b128; +- v_x128 = _mm_packus_epi16(v_x128, v_x128); +- wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- } +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + wuffs_base__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 4, 3); +- while (v_curr.ptr < i_end1_curr) { +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); +- v_pa128 = _mm_sub_epi16(v_b128, v_c128); +- v_pb128 = _mm_sub_epi16(v_a128, v_c128); +- v_pc128 = _mm_add_epi16(v_pa128, v_pb128); +- v_pa128 = _mm_abs_epi16(v_pa128); +- v_pb128 = _mm_abs_epi16(v_pb128); +- v_pc128 = _mm_abs_epi16(v_pc128); +- v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); +- v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- v_c128 = v_b128; +- v_x128 = _mm_packus_epi16(v_x128, v_x128); +- wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- } +- v_curr.len = 3; +- v_prev.len = 3; +- uint8_t* i_end2_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3); +- while (v_curr.ptr < i_end2_curr) { +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u24le__no_bounds_check(v_prev.ptr))); +- v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); +- v_pa128 = _mm_sub_epi16(v_b128, v_c128); +- v_pb128 = _mm_sub_epi16(v_a128, v_c128); +- v_pc128 = _mm_add_epi16(v_pa128, v_pb128); +- v_pa128 = _mm_abs_epi16(v_pa128); +- v_pb128 = _mm_abs_epi16(v_pb128); +- v_pc128 = _mm_abs_epi16(v_pc128); +- v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); +- v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u24le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_x128 = _mm_packus_epi16(v_x128, v_x128); +- wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 3; +- v_prev.ptr += 3; +- } +- v_curr.len = 0; +- v_prev.len = 0; ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; + } +- return wuffs_base__make_empty_struct(); ++ return status; + } +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 + +-// ‼ WUFFS MULTI-FILE SECTION +x86_sse42 +-// -------- func png.decoder.filter_4_distance_4_x86_sse42 ++// -------- func qoi.decoder.do_decode_frame_config + +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2") + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_png__decoder__filter_4_distance_4_x86_sse42( +- wuffs_png__decoder* self, +- wuffs_base__slice_u8 a_curr, +- wuffs_base__slice_u8 a_prev) { +- wuffs_base__slice_u8 v_curr = {0}; +- wuffs_base__slice_u8 v_prev = {0}; +- __m128i v_x128 = {0}; +- __m128i v_a128 = {0}; +- __m128i v_b128 = {0}; +- __m128i v_c128 = {0}; +- __m128i v_p128 = {0}; +- __m128i v_pa128 = {0}; +- __m128i v_pb128 = {0}; +- __m128i v_pc128 = {0}; +- __m128i v_smallest128 = {0}; +- __m128i v_z128 = {0}; ++static wuffs_base__status ++wuffs_qoi__decoder__do_decode_frame_config( ++ wuffs_qoi__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- { +- wuffs_base__slice_u8 i_slice_curr = a_curr; +- v_curr.ptr = i_slice_curr.ptr; +- wuffs_base__slice_u8 i_slice_prev = a_prev; +- v_prev.ptr = i_slice_prev.ptr; +- i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len))); +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8); +- while (v_curr.ptr < i_end0_curr) { +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); +- v_pa128 = _mm_sub_epi16(v_b128, v_c128); +- v_pb128 = _mm_sub_epi16(v_a128, v_c128); +- v_pc128 = _mm_add_epi16(v_pa128, v_pb128); +- v_pa128 = _mm_abs_epi16(v_pa128); +- v_pb128 = _mm_abs_epi16(v_pb128); +- v_pc128 = _mm_abs_epi16(v_pc128); +- v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); +- v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- v_c128 = v_b128; +- v_x128 = _mm_packus_epi16(v_x128, v_x128); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); +- v_pa128 = _mm_sub_epi16(v_b128, v_c128); +- v_pb128 = _mm_sub_epi16(v_a128, v_c128); +- v_pc128 = _mm_add_epi16(v_pa128, v_pb128); +- v_pa128 = _mm_abs_epi16(v_pa128); +- v_pb128 = _mm_abs_epi16(v_pb128); +- v_pc128 = _mm_abs_epi16(v_pc128); +- v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); +- v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- v_c128 = v_b128; +- v_x128 = _mm_packus_epi16(v_x128, v_x128); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- v_prev.ptr += 4; +- } +- v_curr.len = 4; +- v_prev.len = 4; +- uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4); +- while (v_curr.ptr < i_end1_curr) { +- v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr))); +- v_b128 = _mm_unpacklo_epi8(v_b128, v_z128); +- v_pa128 = _mm_sub_epi16(v_b128, v_c128); +- v_pb128 = _mm_sub_epi16(v_a128, v_c128); +- v_pc128 = _mm_add_epi16(v_pa128, v_pb128); +- v_pa128 = _mm_abs_epi16(v_pa128); +- v_pb128 = _mm_abs_epi16(v_pb128); +- v_pc128 = _mm_abs_epi16(v_pc128); +- v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128)); +- v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128)); +- v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr))); +- v_x128 = _mm_unpacklo_epi8(v_x128, v_z128); +- v_x128 = _mm_add_epi8(v_x128, v_p128); +- v_a128 = v_x128; +- v_c128 = v_b128; +- v_x128 = _mm_packus_epi16(v_x128, v_x128); +- wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128)))); +- v_curr.ptr += 4; +- v_prev.ptr += 4; ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_qoi__decoder__do_decode_image_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (16u != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); ++ goto exit; ++ } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ self->private_impl.f_call_sequence = 96u; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; + } +- v_curr.len = 0; +- v_prev.len = 0; +- } +- return wuffs_base__make_empty_struct(); +-} +-#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +-// ‼ WUFFS MULTI-FILE SECTION -x86_sse42 +- +-// -------- func png.decoder.get_quirk +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_png__decoder__get_quirk( +- const wuffs_png__decoder* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height), ++ ((wuffs_base__flicks)(0u)), ++ 0u, ++ 14u, ++ 0u, ++ (self->private_impl.f_pixfmt == 2415954056u), ++ false, ++ 0u); ++ } ++ self->private_impl.f_call_sequence = 64u; + +- if ((a_key == 1u) && self->private_impl.f_ignore_checksum) { +- return 1u; ++ ok: ++ self->private_impl.p_do_decode_frame_config = 0; ++ goto exit; + } +- return 0u; +-} + +-// -------- func png.decoder.set_quirk ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_png__decoder__set_quirk( +- wuffs_png__decoder* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- if (a_key == 1u) { +- self->private_impl.f_ignore_checksum = (a_value > 0u); +- wuffs_zlib__decoder__set_quirk(&self->private_data.f_zlib, a_key, a_value); +- return wuffs_base__make_status(NULL); +- } +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ return status; + } + +-// -------- func png.decoder.decode_image_config ++// -------- func qoi.decoder.decode_frame + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_png__decoder__decode_image_config( +- wuffs_png__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { ++wuffs_qoi__decoder__decode_frame( ++ wuffs_qoi__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +@@ -54464,12 +67805,12 @@ wuffs_png__decoder__decode_image_config( + ? wuffs_base__error__disabled_by_previous_error + : wuffs_base__error__initialize_not_called); + } +- if (!a_src) { ++ if (!a_dst || !a_src) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { ++ (self->private_impl.active_coroutine != 3)) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } +@@ -54478,17 +67819,22 @@ wuffs_png__decoder__decode_image_config( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_png__decoder__do_decode_image_config(self, a_dst, a_src); ++ wuffs_base__status t_0 = wuffs_qoi__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_png__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_qoi__error__truncated_input); + goto exit; + } + status = v_status; +@@ -54496,14 +67842,14 @@ wuffs_png__decoder__decode_image_config( + } + + ok: +- self->private_impl.p_decode_image_config[0] = 0; ++ self->private_impl.p_decode_frame = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; + + goto exit; + exit: +@@ -54513,21 +67859,21 @@ wuffs_png__decoder__decode_image_config( + return status; + } + +-// -------- func png.decoder.do_decode_image_config ++// -------- func qoi.decoder.do_decode_frame + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__do_decode_image_config( +- wuffs_png__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { ++wuffs_qoi__decoder__do_decode_frame( ++ wuffs_qoi__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint64_t v_magic = 0; +- uint64_t v_mark = 0; +- uint32_t v_checksum_have = 0; +- uint32_t v_checksum_want = 0; + wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint64_t v_c64 = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -54540,281 +67886,332 @@ wuffs_png__decoder__do_decode_image_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config[0]; +- if (coro_susp_point) { +- v_checksum_have = self->private_data.s_do_decode_image_config[0].v_checksum_have; +- } ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } else if ( ! self->private_impl.f_seen_ihdr) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint64_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { +- t_0 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src); +- iop_a_src += 8; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; +- if (num_bits_0 == 56) { +- t_0 = ((uint64_t)(*scratch)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)) << 56; +- } +- } +- v_magic = t_0; ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- if (v_magic != 727905341920923785u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_header); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_qoi__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette(a_dst), ++ wuffs_base__utility__make_pixel_format(self->private_impl.f_pixfmt), ++ wuffs_base__utility__empty_slice_u8(), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); + goto exit; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint64_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { +- t_1 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src); +- iop_a_src += 8; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; +- if (num_bits_1 == 56) { +- t_1 = ((uint64_t)(*scratch)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)) << 56; +- } +- } +- v_magic = t_1; ++ goto ok; ++ } ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y = 0u; ++ self->private_data.f_pixel[0u] = 0u; ++ self->private_data.f_pixel[1u] = 0u; ++ self->private_data.f_pixel[2u] = 0u; ++ self->private_data.f_pixel[3u] = 255u; ++ wuffs_private_impl__bulk_memset(&self->private_data.f_cache[0], 256u, 0u); ++ self->private_impl.f_remaining_pixels_times_4 = (((uint64_t)(self->private_impl.f_width)) * ((uint64_t)(self->private_impl.f_height)) * 4u); ++ while (self->private_impl.f_remaining_pixels_times_4 > 0u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- if (v_magic != 5927942488114331648u) { +- if (v_magic == 5278895250759221248u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_cgbi_extension); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_qoi__decoder__from_src_to_buffer(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (self->private_impl.f_remaining_pixels_times_4 < ((uint64_t)(self->private_impl.f_buffer_index))) { ++ status = wuffs_base__make_status(wuffs_base__error__too_much_data); ++ goto exit; ++ } ++ self->private_impl.f_remaining_pixels_times_4 -= ((uint64_t)(self->private_impl.f_buffer_index)); ++ v_status = wuffs_qoi__decoder__from_buffer_to_dst(self, a_dst); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); + goto exit; + } +- status = wuffs_base__make_status(wuffs_png__error__bad_header); +- goto exit; ++ goto ok; + } +- self->private_impl.f_chunk_type_array[0u] = 73u; +- self->private_impl.f_chunk_type_array[1u] = 72u; +- self->private_impl.f_chunk_type_array[2u] = 68u; +- self->private_impl.f_chunk_type_array[3u] = 82u; +- wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, +- sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); +- wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4)); +- while (true) { +- v_mark = ((uint64_t)(iop_a_src - io0_a_src)); +- { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint64_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_0 = wuffs_base__peek_u64be__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_decode_frame.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- wuffs_base__status t_2 = wuffs_png__decoder__decode_ihdr(self, a_src); +- v_status = t_2; +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ uint64_t* scratch = &self->private_data.s_do_decode_frame.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); ++ if (num_bits_0 == 56) { ++ t_0 = ((uint64_t)(*scratch >> 0)); ++ break; + } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)); + } +- if ( ! self->private_impl.f_ignore_checksum) { +- v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); +- } +- if (wuffs_base__status__is_ok(&v_status)) { +- break; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); + } ++ v_c64 = t_0; ++ } ++ if (v_c64 != 1u) { ++ status = wuffs_base__make_status(wuffs_qoi__error__bad_footer); ++ goto exit; ++ } ++ self->private_impl.f_call_sequence = 96u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func qoi.decoder.from_src_to_buffer ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_qoi__decoder__from_src_to_buffer( ++ wuffs_qoi__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint8_t v_dg = 0; ++ uint32_t v_bi = 0; ++ uint32_t v_bj = 0; ++ uint32_t v_bk = 0; ++ uint32_t v_ci = 0; ++ uint32_t v_hash4 = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_from_src_to_buffer; ++ if (coro_susp_point) { ++ v_dg = self->private_data.s_from_src_to_buffer.v_dg; ++ v_bi = self->private_data.s_from_src_to_buffer.v_bi; ++ v_bk = self->private_data.s_from_src_to_buffer.v_bk; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ v_bk = 7936u; ++ if (self->private_impl.f_remaining_pixels_times_4 < 7936u) { ++ v_bk = ((uint32_t)(self->private_impl.f_remaining_pixels_times_4)); ++ } ++ while (v_bi < v_bk) { + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- uint32_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); +- if (num_bits_3 == 24) { +- t_3 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)); +- } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- v_checksum_want = t_3; +- } +- if ( ! self->private_impl.f_ignore_checksum && (v_checksum_have != v_checksum_want)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_checksum); +- goto exit; +- } +- self->private_impl.f_seen_ihdr = true; +- } else if (self->private_impl.f_metadata_fourcc != 0u) { +- self->private_impl.f_call_sequence = 16u; +- status = wuffs_base__make_status(wuffs_base__note__metadata_reported); +- goto ok; +- } +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 8u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); +- continue; ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; + } +- self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32u))); +- if (self->private_impl.f_chunk_type == 1413563465u) { +- if ( ! self->private_impl.f_seen_actl || self->private_impl.f_seen_fctl) { +- break; ++ if (v_c8 == 254u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ self->private_data.f_pixel[2u] = t_1; + } +- self->private_impl.f_seen_idat = true; +- } else if (self->private_impl.f_chunk_type == 1413571686u) { +- if (self->private_impl.f_seen_idat && self->private_impl.f_seen_fctl) { +- break; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ self->private_data.f_pixel[1u] = t_2; + } +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- iop_a_src += 8u; +- if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32u) == 0u)) { +- self->private_impl.f_chunk_type_array[0u] = ((uint8_t)((self->private_impl.f_chunk_type >> 0u))); +- self->private_impl.f_chunk_type_array[1u] = ((uint8_t)((self->private_impl.f_chunk_type >> 8u))); +- self->private_impl.f_chunk_type_array[2u] = ((uint8_t)((self->private_impl.f_chunk_type >> 16u))); +- self->private_impl.f_chunk_type_array[3u] = ((uint8_t)((self->private_impl.f_chunk_type >> 24u))); +- wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, +- sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); +- wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4)); +- } +- while (true) { +- v_mark = ((uint64_t)(iop_a_src - io0_a_src)); + { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- wuffs_base__status t_4 = wuffs_png__decoder__decode_other_chunk(self, a_src, false); +- v_status = t_4; +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ uint8_t t_3 = *iop_a_src++; ++ self->private_data.f_pixel[0u] = t_3; ++ } ++ } else if (v_c8 == 255u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint8_t t_4 = *iop_a_src++; ++ self->private_data.f_pixel[2u] = t_4; + } +- if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32u) == 0u)) { +- v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ self->private_data.f_pixel[1u] = t_5; + } +- if (wuffs_base__status__is_ok(&v_status)) { +- break; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ self->private_data.f_pixel[0u] = t_6; + } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); +- } +- if (self->private_impl.f_metadata_fourcc != 0u) { +- self->private_impl.f_call_sequence = 16u; +- status = wuffs_base__make_status(wuffs_base__note__metadata_reported); +- goto ok; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- uint32_t t_5; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_5 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); +- if (num_bits_5 == 24) { +- t_5 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_5 += 8u; +- *scratch |= ((uint64_t)(num_bits_5)); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint8_t t_7 = *iop_a_src++; ++ self->private_data.f_pixel[3u] = t_7; + } +- v_checksum_want = t_5; +- } +- if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32u) == 0u) && (v_checksum_have != v_checksum_want)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_checksum); +- goto exit; +- } +- } +- if ((self->private_impl.f_color_type == 3u) && ! self->private_impl.f_seen_plte) { +- status = wuffs_base__make_status(wuffs_png__error__missing_palette); +- goto exit; +- } +- self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- self->private_impl.f_first_config_io_position = self->private_impl.f_frame_config_io_position; +- if (a_dst != NULL) { +- wuffs_base__image_config__set( +- a_dst, +- self->private_impl.f_dst_pixfmt, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height, +- self->private_impl.f_first_config_io_position, +- ((self->private_impl.f_color_type <= 3u) && ! self->private_impl.f_seen_trns)); +- } +- if ( ! self->private_impl.f_seen_actl) { +- self->private_impl.f_num_animation_frames_value = 1u; +- self->private_impl.f_first_rect_x0 = 0u; +- self->private_impl.f_first_rect_y0 = 0u; +- self->private_impl.f_first_rect_x1 = self->private_impl.f_width; +- self->private_impl.f_first_rect_y1 = self->private_impl.f_height; +- self->private_impl.f_first_duration = 0u; +- self->private_impl.f_first_disposal = 0u; +- self->private_impl.f_first_overwrite_instead_of_blend = false; +- } +- self->private_impl.f_call_sequence = 32u; ++ } else if (((uint8_t)(v_c8 >> 6u)) == 0u) { ++ v_ci = (4u * ((uint32_t)(((uint8_t)(v_c8 & 63u))))); ++ self->private_data.f_pixel[0u] = self->private_data.f_cache[(v_ci + 0u)]; ++ self->private_data.f_pixel[1u] = self->private_data.f_cache[(v_ci + 1u)]; ++ self->private_data.f_pixel[2u] = self->private_data.f_cache[(v_ci + 2u)]; ++ self->private_data.f_pixel[3u] = self->private_data.f_cache[(v_ci + 3u)]; ++ self->private_data.f_buffer[(v_bi + 0u)] = self->private_data.f_pixel[0u]; ++ self->private_data.f_buffer[(v_bi + 1u)] = self->private_data.f_pixel[1u]; ++ self->private_data.f_buffer[(v_bi + 2u)] = self->private_data.f_pixel[2u]; ++ self->private_data.f_buffer[(v_bi + 3u)] = self->private_data.f_pixel[3u]; ++ v_bi += 4u; ++ continue; ++ } else if (((uint8_t)(v_c8 >> 6u)) == 1u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_data.f_pixel[2u] += ((uint8_t)(((uint8_t)(((uint8_t)(v_c8 >> 4u)) & 3u)) + 254u)); ++ self->private_data.f_pixel[1u] += ((uint8_t)(((uint8_t)(((uint8_t)(v_c8 >> 2u)) & 3u)) + 254u)); ++ self->private_data.f_pixel[0u] += ((uint8_t)(((uint8_t)(((uint8_t)(v_c8 >> 0u)) & 3u)) + 254u)); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (((uint8_t)(v_c8 >> 6u)) == 2u) { ++ v_dg = ((uint8_t)(((uint8_t)(v_c8 & 63u)) + 224u)); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_8 = *iop_a_src++; ++ v_c8 = t_8; ++ } ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_data.f_pixel[2u] += ((uint8_t)(((uint8_t)(v_dg + 248u)) + ((uint8_t)(15u & ((uint8_t)(v_c8 >> 4u)))))); ++ self->private_data.f_pixel[1u] += v_dg; ++ self->private_data.f_pixel[0u] += ((uint8_t)(((uint8_t)(v_dg + 248u)) + ((uint8_t)(15u & ((uint8_t)(v_c8 >> 0u)))))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ v_bj = (v_bi + (4u * (63u & (1u + ((uint32_t)(v_c8)))))); ++ while (v_bi < v_bj) { ++ self->private_data.f_buffer[(v_bi + 0u)] = self->private_data.f_pixel[0u]; ++ self->private_data.f_buffer[(v_bi + 1u)] = self->private_data.f_pixel[1u]; ++ self->private_data.f_buffer[(v_bi + 2u)] = self->private_data.f_pixel[2u]; ++ self->private_data.f_buffer[(v_bi + 3u)] = self->private_data.f_pixel[3u]; ++ v_bi += 4u; ++ } ++ continue; ++ } ++ v_hash4 = (4u * (63u & ((((uint32_t)(self->private_data.f_pixel[2u])) * 3u) + ++ (((uint32_t)(self->private_data.f_pixel[1u])) * 5u) + ++ (((uint32_t)(self->private_data.f_pixel[0u])) * 7u) + ++ (((uint32_t)(self->private_data.f_pixel[3u])) * 11u)))); ++ self->private_data.f_cache[(v_hash4 + 0u)] = self->private_data.f_pixel[0u]; ++ self->private_data.f_cache[(v_hash4 + 1u)] = self->private_data.f_pixel[1u]; ++ self->private_data.f_cache[(v_hash4 + 2u)] = self->private_data.f_pixel[2u]; ++ self->private_data.f_cache[(v_hash4 + 3u)] = self->private_data.f_pixel[3u]; ++ self->private_data.f_buffer[(v_bi + 0u)] = self->private_data.f_pixel[0u]; ++ self->private_data.f_buffer[(v_bi + 1u)] = self->private_data.f_pixel[1u]; ++ self->private_data.f_buffer[(v_bi + 2u)] = self->private_data.f_pixel[2u]; ++ self->private_data.f_buffer[(v_bi + 3u)] = self->private_data.f_pixel[3u]; ++ v_bi += 4u; ++ } ++ self->private_impl.f_buffer_index = v_bi; + ++ goto ok; + ok: +- self->private_impl.p_do_decode_image_config[0] = 0; ++ self->private_impl.p_from_src_to_buffer = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_decode_image_config[0].v_checksum_have = v_checksum_have; ++ self->private_impl.p_from_src_to_buffer = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_from_src_to_buffer.v_dg = v_dg; ++ self->private_data.s_from_src_to_buffer.v_bi = v_bi; ++ self->private_data.s_from_src_to_buffer.v_bk = v_bk; + + goto exit; + exit: +@@ -54825,1068 +68222,1113 @@ wuffs_png__decoder__do_decode_image_config( + return status; + } + +-// -------- func png.decoder.decode_ihdr ++// -------- func qoi.decoder.from_buffer_to_dst + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__decode_ihdr( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_a32 = 0; +- uint8_t v_a8 = 0; ++wuffs_qoi__decoder__from_buffer_to_dst( ++ wuffs_qoi__decoder* self, ++ wuffs_base__pixel_buffer* a_dst) { ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row = 0; ++ wuffs_base__table_u8 v_tab = {0}; ++ uint32_t v_bi = 0; ++ uint32_t v_rem_x = 0; ++ wuffs_base__slice_u8 v_dst = {0}; ++ wuffs_base__slice_u8 v_src = {0}; ++ uint32_t v_src_length = 0; ++ uint64_t v_i = 0; + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } +- +- uint32_t coro_susp_point = self->private_impl.p_decode_ihdr[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_ihdr[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_ihdr[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } +- } +- v_a32 = t_0; +- } +- if ((v_a32 == 0u) || (v_a32 > 2147483647u)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_header); +- goto exit; +- } else if (v_a32 > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } +- self->private_impl.f_width = v_a32; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_ihdr[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_ihdr[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); +- if (num_bits_1 == 24) { +- t_1 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)); +- } +- } +- v_a32 = t_1; +- } +- if ((v_a32 == 0u) || (v_a32 > 2147483647u)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_header); +- goto exit; +- } else if (v_a32 > 16777215u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } +- self->private_impl.f_height = v_a32; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_2 = *iop_a_src++; +- v_a8 = t_2; +- } +- if (v_a8 > 16u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_header); +- goto exit; +- } +- self->private_impl.f_depth = v_a8; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_3 = *iop_a_src++; +- v_a8 = t_3; +- } +- if ((v_a8 == 1u) || (v_a8 == 5u) || (v_a8 > 6u)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_header); +- goto exit; +- } +- self->private_impl.f_color_type = v_a8; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_4 = *iop_a_src++; +- v_a8 = t_4; +- } +- if (v_a8 != 0u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ while (v_bi < self->private_impl.f_buffer_index) { ++ if (self->private_impl.f_width <= self->private_impl.f_dst_x) { ++ self->private_impl.f_dst_x = 0u; ++ self->private_impl.f_dst_y += 1u; ++ if (self->private_impl.f_dst_y >= self->private_impl.f_height) { ++ break; + } +- uint8_t t_5 = *iop_a_src++; +- v_a8 = t_5; +- } +- if (v_a8 != 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_header); +- goto exit; ++ v_rem_x = self->private_impl.f_width; ++ } else { ++ v_rem_x = (self->private_impl.f_width - self->private_impl.f_dst_x); + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_6 = *iop_a_src++; +- v_a8 = t_6; ++ v_src = wuffs_base__make_slice_u8_ij(self->private_data.f_buffer, v_bi, self->private_impl.f_buffer_index); ++ if (((uint64_t)((4u * v_rem_x))) < ((uint64_t)(v_src.len))) { ++ v_src = wuffs_base__slice_u8__subslice_j(v_src, ((uint64_t)((4u * v_rem_x)))); + } +- if (v_a8 == 0u) { +- self->private_impl.f_interlace_pass = 0u; +- } else if (v_a8 == 1u) { +- self->private_impl.f_interlace_pass = 1u; +- self->private_impl.choosy_filter_and_swizzle = ( +- &wuffs_png__decoder__filter_and_swizzle_tricky); +- } else { +- status = wuffs_base__make_status(wuffs_png__error__bad_header); +- goto exit; ++ v_src_length = ((uint32_t)(((uint64_t)(v_src.len)))); ++ v_bi += v_src_length; ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, self->private_impl.f_dst_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); + } +- self->private_impl.f_filter_distance = 0u; +- wuffs_png__decoder__assign_filter_distance(self); +- if (self->private_impl.f_filter_distance == 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_header); +- goto exit; ++ v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_dst_bytes_per_pixel))); ++ self->private_impl.f_dst_x += (v_src_length / 4u); ++ if (v_i < ((uint64_t)(v_dst.len))) { ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), wuffs_base__pixel_buffer__palette(a_dst), v_src); + } +- self->private_impl.f_overall_workbuf_length = (((uint64_t)(self->private_impl.f_height)) * (1u + wuffs_png__decoder__calculate_bytes_per_row(self, self->private_impl.f_width))); +- wuffs_png__decoder__choose_filter_implementations(self); ++ } ++ return wuffs_base__make_status(NULL); ++} + +- goto ok; +- ok: +- self->private_impl.p_decode_ihdr[0] = 0; +- goto exit; ++// -------- func qoi.decoder.frame_dirty_rect ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_qoi__decoder__frame_dirty_rect( ++ const wuffs_qoi__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); + } + +- goto suspend; +- suspend: +- self->private_impl.p_decode_ihdr[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ return wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height); ++} ++ ++// -------- func qoi.decoder.num_animation_loops ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_qoi__decoder__num_animation_loops( ++ const wuffs_qoi__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func qoi.decoder.num_decoded_frame_configs ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_qoi__decoder__num_decoded_frame_configs( ++ const wuffs_qoi__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 32u) { ++ return 1u; ++ } ++ return 0u; ++} + ++// -------- func qoi.decoder.num_decoded_frames ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_qoi__decoder__num_decoded_frames( ++ const wuffs_qoi__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 64u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func qoi.decoder.restart_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_qoi__decoder__restart_frame( ++ wuffs_qoi__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (self->private_impl.f_call_sequence < 32u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } ++ if ((a_index != 0u) || (a_io_position != 14u)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_call_sequence = 40u; ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func qoi.decoder.set_report_metadata ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_qoi__decoder__set_report_metadata( ++ wuffs_qoi__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func qoi.decoder.tell_me_more ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_qoi__decoder__tell_me_more( ++ wuffs_qoi__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); ++ goto exit; ++ ++ goto ok; ++ ok: + goto exit; + exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; + } +- + return status; + } + +-// -------- func png.decoder.assign_filter_distance ++// -------- func qoi.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_qoi__decoder__workbuf_len( ++ const wuffs_qoi__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__QOI) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__SHA256) ++ ++// ---------------- Status Codes Implementations ++ ++// ---------------- Private Consts ++ ++static const uint32_t ++WUFFS_SHA256__INITIAL_SHA256_H[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1779033703u, 3144134277u, 1013904242u, 2773480762u, 1359893119u, 2600822924u, 528734635u, 1541459225u, ++}; ++ ++static const uint32_t ++WUFFS_SHA256__K[64] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1116352408u, 1899447441u, 3049323471u, 3921009573u, 961987163u, 1508970993u, 2453635748u, 2870763221u, ++ 3624381080u, 310598401u, 607225278u, 1426881987u, 1925078388u, 2162078206u, 2614888103u, 3248222580u, ++ 3835390401u, 4022224774u, 264347078u, 604807628u, 770255983u, 1249150122u, 1555081692u, 1996064986u, ++ 2554220882u, 2821834349u, 2952996808u, 3210313671u, 3336571891u, 3584528711u, 113926993u, 338241895u, ++ 666307205u, 773529912u, 1294757372u, 1396182291u, 1695183700u, 1986661051u, 2177026350u, 2456956037u, ++ 2730485921u, 2820302411u, 3259730800u, 3345764771u, 3516065817u, 3600352804u, 4094571909u, 275423344u, ++ 430227734u, 506948616u, 659060556u, 883997877u, 958139571u, 1322822218u, 1537002063u, 1747873779u, ++ 1955562222u, 2024104815u, 2227730452u, 2361852424u, 2428436474u, 2756734187u, 3204031479u, 3329325298u, ++}; ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_png__decoder__assign_filter_distance( +- wuffs_png__decoder* self) { +- if (self->private_impl.f_depth < 8u) { +- if ((self->private_impl.f_depth != 1u) && (self->private_impl.f_depth != 2u) && (self->private_impl.f_depth != 4u)) { +- return wuffs_base__make_empty_struct(); +- } else if (self->private_impl.f_color_type == 0u) { +- self->private_impl.f_dst_pixfmt = 536870920u; +- self->private_impl.f_src_pixfmt = 536870920u; +- } else if (self->private_impl.f_color_type == 3u) { +- self->private_impl.f_dst_pixfmt = 2198077448u; +- self->private_impl.f_src_pixfmt = 2198077448u; ++wuffs_sha256__hasher__up( ++ wuffs_sha256__hasher* self, ++ wuffs_base__slice_u8 a_x); ++ ++// ---------------- VTables ++ ++const wuffs_base__hasher_bitvec256__func_ptrs ++wuffs_sha256__hasher__func_ptrs_for__wuffs_base__hasher_bitvec256 = { ++ (wuffs_base__bitvec256(*)(const void*))(&wuffs_sha256__hasher__checksum_bitvec256), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_sha256__hasher__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_sha256__hasher__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_sha256__hasher__update), ++ (wuffs_base__bitvec256(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_sha256__hasher__update_bitvec256), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_sha256__hasher__initialize( ++ wuffs_sha256__hasher* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; + } else { +- return wuffs_base__make_empty_struct(); ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); + } +- self->private_impl.f_filter_distance = 1u; +- self->private_impl.choosy_filter_and_swizzle = ( +- &wuffs_png__decoder__filter_and_swizzle_tricky); +- } else if (self->private_impl.f_color_type == 0u) { +- if (self->private_impl.f_depth == 8u) { +- self->private_impl.f_dst_pixfmt = 536870920u; +- self->private_impl.f_src_pixfmt = 536870920u; +- self->private_impl.f_filter_distance = 1u; +- } else if (self->private_impl.f_depth == 16u) { +- if (self->private_impl.f_interlace_pass == 0u) { +- self->private_impl.f_dst_pixfmt = 536870923u; +- self->private_impl.f_src_pixfmt = 537919499u; +- } else { +- self->private_impl.f_dst_pixfmt = 2164308923u; +- self->private_impl.f_src_pixfmt = 2164308923u; ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__hasher_bitvec256.vtable_name = ++ wuffs_base__hasher_bitvec256__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__hasher_bitvec256.function_pointers = ++ (const void*)(&wuffs_sha256__hasher__func_ptrs_for__wuffs_base__hasher_bitvec256); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_sha256__hasher* ++wuffs_sha256__hasher__alloc(void) { ++ wuffs_sha256__hasher* x = ++ (wuffs_sha256__hasher*)(calloc(1, sizeof(wuffs_sha256__hasher))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_sha256__hasher__initialize( ++ x, sizeof(wuffs_sha256__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; ++} ++ ++size_t ++sizeof__wuffs_sha256__hasher(void) { ++ return sizeof(wuffs_sha256__hasher); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func sha256.hasher.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_sha256__hasher__get_quirk( ++ const wuffs_sha256__hasher* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func sha256.hasher.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_sha256__hasher__set_quirk( ++ wuffs_sha256__hasher* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func sha256.hasher.update ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_sha256__hasher__update( ++ wuffs_sha256__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); ++ } ++ ++ uint64_t v_new_lmu = 0; ++ ++ if ((self->private_impl.f_length_modulo_u64 == 0u) && ! self->private_impl.f_length_overflows_u64) { ++ self->private_impl.f_h0 = WUFFS_SHA256__INITIAL_SHA256_H[0u]; ++ self->private_impl.f_h1 = WUFFS_SHA256__INITIAL_SHA256_H[1u]; ++ self->private_impl.f_h2 = WUFFS_SHA256__INITIAL_SHA256_H[2u]; ++ self->private_impl.f_h3 = WUFFS_SHA256__INITIAL_SHA256_H[3u]; ++ self->private_impl.f_h4 = WUFFS_SHA256__INITIAL_SHA256_H[4u]; ++ self->private_impl.f_h5 = WUFFS_SHA256__INITIAL_SHA256_H[5u]; ++ self->private_impl.f_h6 = WUFFS_SHA256__INITIAL_SHA256_H[6u]; ++ self->private_impl.f_h7 = WUFFS_SHA256__INITIAL_SHA256_H[7u]; ++ } ++ v_new_lmu = ((uint64_t)(self->private_impl.f_length_modulo_u64 + ((uint64_t)(a_x.len)))); ++ self->private_impl.f_length_overflows_u64 = ((v_new_lmu < self->private_impl.f_length_modulo_u64) || self->private_impl.f_length_overflows_u64); ++ self->private_impl.f_length_modulo_u64 = v_new_lmu; ++ if (self->private_impl.f_buf_len != 0u) { ++ while (self->private_impl.f_buf_len < 64u) { ++ if (((uint64_t)(a_x.len)) <= 0u) { ++ return wuffs_base__make_empty_struct(); + } +- self->private_impl.f_filter_distance = 2u; +- } +- } else if (self->private_impl.f_color_type == 2u) { +- if (self->private_impl.f_depth == 8u) { +- self->private_impl.f_dst_pixfmt = 2147485832u; +- self->private_impl.f_src_pixfmt = 2684356744u; +- self->private_impl.f_filter_distance = 3u; +- } else if (self->private_impl.f_depth == 16u) { +- self->private_impl.f_dst_pixfmt = 2164308923u; +- self->private_impl.f_src_pixfmt = 2164308923u; +- self->private_impl.f_filter_distance = 6u; +- self->private_impl.choosy_filter_and_swizzle = ( +- &wuffs_png__decoder__filter_and_swizzle_tricky); +- } +- } else if (self->private_impl.f_color_type == 3u) { +- if (self->private_impl.f_depth == 8u) { +- self->private_impl.f_dst_pixfmt = 2198077448u; +- self->private_impl.f_src_pixfmt = 2198077448u; +- self->private_impl.f_filter_distance = 1u; +- } +- } else if (self->private_impl.f_color_type == 4u) { +- if (self->private_impl.f_depth == 8u) { +- self->private_impl.f_dst_pixfmt = 2164295816u; +- self->private_impl.f_src_pixfmt = 2164295816u; +- self->private_impl.f_filter_distance = 2u; +- self->private_impl.choosy_filter_and_swizzle = ( +- &wuffs_png__decoder__filter_and_swizzle_tricky); +- } else if (self->private_impl.f_depth == 16u) { +- self->private_impl.f_dst_pixfmt = 2164308923u; +- self->private_impl.f_src_pixfmt = 2164308923u; +- self->private_impl.f_filter_distance = 4u; +- self->private_impl.choosy_filter_and_swizzle = ( +- &wuffs_png__decoder__filter_and_swizzle_tricky); +- } +- } else if (self->private_impl.f_color_type == 6u) { +- if (self->private_impl.f_depth == 8u) { +- self->private_impl.f_dst_pixfmt = 2164295816u; +- self->private_impl.f_src_pixfmt = 2701166728u; +- self->private_impl.f_filter_distance = 4u; +- } else if (self->private_impl.f_depth == 16u) { +- self->private_impl.f_dst_pixfmt = 2164308923u; +- self->private_impl.f_src_pixfmt = 2164308923u; +- self->private_impl.f_filter_distance = 8u; +- self->private_impl.choosy_filter_and_swizzle = ( +- &wuffs_png__decoder__filter_and_swizzle_tricky); ++ self->private_impl.f_buf_data[self->private_impl.f_buf_len] = a_x.ptr[0u]; ++ self->private_impl.f_buf_len += 1u; ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); + } ++ self->private_impl.f_buf_len = 0u; ++ wuffs_sha256__hasher__up(self, wuffs_base__make_slice_u8(self->private_impl.f_buf_data, 64)); + } ++ wuffs_sha256__hasher__up(self, a_x); + return wuffs_base__make_empty_struct(); + } + +-// -------- func png.decoder.calculate_bytes_per_row ++// -------- func sha256.hasher.update_bitvec256 + + WUFFS_BASE__GENERATED_C_CODE +-static uint64_t +-wuffs_png__decoder__calculate_bytes_per_row( +- const wuffs_png__decoder* self, +- uint32_t a_width) { +- uint64_t v_bytes_per_channel = 0; +- +- if (self->private_impl.f_depth == 1u) { +- return ((uint64_t)(((a_width + 7u) / 8u))); +- } else if (self->private_impl.f_depth == 2u) { +- return ((uint64_t)(((a_width + 3u) / 4u))); +- } else if (self->private_impl.f_depth == 4u) { +- return ((uint64_t)(((a_width + 1u) / 2u))); ++WUFFS_BASE__MAYBE_STATIC wuffs_base__bitvec256 ++wuffs_sha256__hasher__update_bitvec256( ++ wuffs_sha256__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); + } +- v_bytes_per_channel = ((uint64_t)((self->private_impl.f_depth >> 3u))); +- return (((uint64_t)(a_width)) * v_bytes_per_channel * ((uint64_t)(WUFFS_PNG__NUM_CHANNELS[self->private_impl.f_color_type]))); ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); ++ } ++ ++ wuffs_sha256__hasher__update(self, a_x); ++ return wuffs_sha256__hasher__checksum_bitvec256(self); + } + +-// -------- func png.decoder.choose_filter_implementations ++// -------- func sha256.hasher.up + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__empty_struct +-wuffs_png__decoder__choose_filter_implementations( +- wuffs_png__decoder* self) { +- if (self->private_impl.f_filter_distance == 3u) { +- self->private_impl.choosy_filter_1 = ( +- &wuffs_png__decoder__filter_1_distance_3_fallback); +- self->private_impl.choosy_filter_3 = ( +- &wuffs_png__decoder__filter_3_distance_3_fallback); +- self->private_impl.choosy_filter_4 = ( +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_4_distance_3_arm_neon : +-#endif +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_4_distance_3_x86_sse42 : +-#endif +- &wuffs_png__decoder__filter_4_distance_3_fallback); +- } else if (self->private_impl.f_filter_distance == 4u) { +- self->private_impl.choosy_filter_1 = ( +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_1_distance_4_arm_neon : +-#endif +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_1_distance_4_x86_sse42 : +-#endif +- &wuffs_png__decoder__filter_1_distance_4_fallback); +- self->private_impl.choosy_filter_3 = ( +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_3_distance_4_arm_neon : +-#endif +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_3_distance_4_x86_sse42 : +-#endif +- &wuffs_png__decoder__filter_3_distance_4_fallback); +- self->private_impl.choosy_filter_4 = ( +-#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON) +- wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_4_distance_4_arm_neon : +-#endif +-#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY) +- wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_4_distance_4_x86_sse42 : +-#endif +- &wuffs_png__decoder__filter_4_distance_4_fallback); ++wuffs_sha256__hasher__up( ++ wuffs_sha256__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ wuffs_base__slice_u8 v_p = {0}; ++ uint32_t v_w[64] = {0}; ++ uint32_t v_w2 = 0; ++ uint32_t v_w15 = 0; ++ uint32_t v_s0 = 0; ++ uint32_t v_s1 = 0; ++ uint32_t v_t1 = 0; ++ uint32_t v_t2 = 0; ++ uint32_t v_a = 0; ++ uint32_t v_b = 0; ++ uint32_t v_c = 0; ++ uint32_t v_d = 0; ++ uint32_t v_e = 0; ++ uint32_t v_f = 0; ++ uint32_t v_g = 0; ++ uint32_t v_h = 0; ++ uint32_t v_i = 0; ++ uint32_t v_buf_len = 0; ++ ++ v_a = self->private_impl.f_h0; ++ v_b = self->private_impl.f_h1; ++ v_c = self->private_impl.f_h2; ++ v_d = self->private_impl.f_h3; ++ v_e = self->private_impl.f_h4; ++ v_f = self->private_impl.f_h5; ++ v_g = self->private_impl.f_h6; ++ v_h = self->private_impl.f_h7; ++ { ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 64; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 64) * 64)); ++ while (v_p.ptr < i_end0_p) { ++ v_w[0u] = ((((uint32_t)(v_p.ptr[0u])) << 24u) | ++ (((uint32_t)(v_p.ptr[1u])) << 16u) | ++ (((uint32_t)(v_p.ptr[2u])) << 8u) | ++ ((uint32_t)(v_p.ptr[3u]))); ++ v_w[1u] = ((((uint32_t)(v_p.ptr[4u])) << 24u) | ++ (((uint32_t)(v_p.ptr[5u])) << 16u) | ++ (((uint32_t)(v_p.ptr[6u])) << 8u) | ++ ((uint32_t)(v_p.ptr[7u]))); ++ v_w[2u] = ((((uint32_t)(v_p.ptr[8u])) << 24u) | ++ (((uint32_t)(v_p.ptr[9u])) << 16u) | ++ (((uint32_t)(v_p.ptr[10u])) << 8u) | ++ ((uint32_t)(v_p.ptr[11u]))); ++ v_w[3u] = ((((uint32_t)(v_p.ptr[12u])) << 24u) | ++ (((uint32_t)(v_p.ptr[13u])) << 16u) | ++ (((uint32_t)(v_p.ptr[14u])) << 8u) | ++ ((uint32_t)(v_p.ptr[15u]))); ++ v_w[4u] = ((((uint32_t)(v_p.ptr[16u])) << 24u) | ++ (((uint32_t)(v_p.ptr[17u])) << 16u) | ++ (((uint32_t)(v_p.ptr[18u])) << 8u) | ++ ((uint32_t)(v_p.ptr[19u]))); ++ v_w[5u] = ((((uint32_t)(v_p.ptr[20u])) << 24u) | ++ (((uint32_t)(v_p.ptr[21u])) << 16u) | ++ (((uint32_t)(v_p.ptr[22u])) << 8u) | ++ ((uint32_t)(v_p.ptr[23u]))); ++ v_w[6u] = ((((uint32_t)(v_p.ptr[24u])) << 24u) | ++ (((uint32_t)(v_p.ptr[25u])) << 16u) | ++ (((uint32_t)(v_p.ptr[26u])) << 8u) | ++ ((uint32_t)(v_p.ptr[27u]))); ++ v_w[7u] = ((((uint32_t)(v_p.ptr[28u])) << 24u) | ++ (((uint32_t)(v_p.ptr[29u])) << 16u) | ++ (((uint32_t)(v_p.ptr[30u])) << 8u) | ++ ((uint32_t)(v_p.ptr[31u]))); ++ v_w[8u] = ((((uint32_t)(v_p.ptr[32u])) << 24u) | ++ (((uint32_t)(v_p.ptr[33u])) << 16u) | ++ (((uint32_t)(v_p.ptr[34u])) << 8u) | ++ ((uint32_t)(v_p.ptr[35u]))); ++ v_w[9u] = ((((uint32_t)(v_p.ptr[36u])) << 24u) | ++ (((uint32_t)(v_p.ptr[37u])) << 16u) | ++ (((uint32_t)(v_p.ptr[38u])) << 8u) | ++ ((uint32_t)(v_p.ptr[39u]))); ++ v_w[10u] = ((((uint32_t)(v_p.ptr[40u])) << 24u) | ++ (((uint32_t)(v_p.ptr[41u])) << 16u) | ++ (((uint32_t)(v_p.ptr[42u])) << 8u) | ++ ((uint32_t)(v_p.ptr[43u]))); ++ v_w[11u] = ((((uint32_t)(v_p.ptr[44u])) << 24u) | ++ (((uint32_t)(v_p.ptr[45u])) << 16u) | ++ (((uint32_t)(v_p.ptr[46u])) << 8u) | ++ ((uint32_t)(v_p.ptr[47u]))); ++ v_w[12u] = ((((uint32_t)(v_p.ptr[48u])) << 24u) | ++ (((uint32_t)(v_p.ptr[49u])) << 16u) | ++ (((uint32_t)(v_p.ptr[50u])) << 8u) | ++ ((uint32_t)(v_p.ptr[51u]))); ++ v_w[13u] = ((((uint32_t)(v_p.ptr[52u])) << 24u) | ++ (((uint32_t)(v_p.ptr[53u])) << 16u) | ++ (((uint32_t)(v_p.ptr[54u])) << 8u) | ++ ((uint32_t)(v_p.ptr[55u]))); ++ v_w[14u] = ((((uint32_t)(v_p.ptr[56u])) << 24u) | ++ (((uint32_t)(v_p.ptr[57u])) << 16u) | ++ (((uint32_t)(v_p.ptr[58u])) << 8u) | ++ ((uint32_t)(v_p.ptr[59u]))); ++ v_w[15u] = ((((uint32_t)(v_p.ptr[60u])) << 24u) | ++ (((uint32_t)(v_p.ptr[61u])) << 16u) | ++ (((uint32_t)(v_p.ptr[62u])) << 8u) | ++ ((uint32_t)(v_p.ptr[63u]))); ++ v_i = 16u; ++ while (v_i < 64u) { ++ v_w2 = v_w[(v_i - 2u)]; ++ v_s1 = ((v_w2 >> 10u) ^ (((uint32_t)(v_w2 << 15u)) | (v_w2 >> 17u)) ^ (((uint32_t)(v_w2 << 13u)) | (v_w2 >> 19u))); ++ v_w15 = v_w[(v_i - 15u)]; ++ v_s0 = ((v_w15 >> 3u) ^ (((uint32_t)(v_w15 << 25u)) | (v_w15 >> 7u)) ^ (((uint32_t)(v_w15 << 14u)) | (v_w15 >> 18u))); ++ v_w[v_i] = ((uint32_t)(((uint32_t)(((uint32_t)(v_s1 + v_w[(v_i - 7u)])) + v_s0)) + v_w[(v_i - 16u)])); ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 64u) { ++ v_t1 = v_h; ++ v_t1 += ((((uint32_t)(v_e << 26u)) | (v_e >> 6u)) ^ (((uint32_t)(v_e << 21u)) | (v_e >> 11u)) ^ (((uint32_t)(v_e << 7u)) | (v_e >> 25u))); ++ v_t1 += ((v_e & v_f) ^ ((4294967295u ^ v_e) & v_g)); ++ v_t1 += WUFFS_SHA256__K[v_i]; ++ v_t1 += v_w[v_i]; ++ v_t2 = ((((uint32_t)(v_a << 30u)) | (v_a >> 2u)) ^ (((uint32_t)(v_a << 19u)) | (v_a >> 13u)) ^ (((uint32_t)(v_a << 10u)) | (v_a >> 22u))); ++ v_t2 += ((v_a & v_b) ^ (v_a & v_c) ^ (v_b & v_c)); ++ v_h = v_g; ++ v_g = v_f; ++ v_f = v_e; ++ v_e = ((uint32_t)(v_d + v_t1)); ++ v_d = v_c; ++ v_c = v_b; ++ v_b = v_a; ++ v_a = ((uint32_t)(v_t1 + v_t2)); ++ v_i += 1u; ++ } ++ v_a += self->private_impl.f_h0; ++ self->private_impl.f_h0 = v_a; ++ v_b += self->private_impl.f_h1; ++ self->private_impl.f_h1 = v_b; ++ v_c += self->private_impl.f_h2; ++ self->private_impl.f_h2 = v_c; ++ v_d += self->private_impl.f_h3; ++ self->private_impl.f_h3 = v_d; ++ v_e += self->private_impl.f_h4; ++ self->private_impl.f_h4 = v_e; ++ v_f += self->private_impl.f_h5; ++ self->private_impl.f_h5 = v_f; ++ v_g += self->private_impl.f_h6; ++ self->private_impl.f_h6 = v_g; ++ v_h += self->private_impl.f_h7; ++ self->private_impl.f_h7 = v_h; ++ v_p.ptr += 64; ++ } ++ v_p.len = 1; ++ const uint8_t* i_end1_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end1_p) { ++ self->private_impl.f_buf_data[v_buf_len] = v_p.ptr[0u]; ++ v_buf_len = ((v_buf_len + 1u) & 63u); ++ v_p.ptr += 1; ++ } ++ v_p.len = 0; + } ++ self->private_impl.f_buf_len = ((uint32_t)((((uint64_t)(a_x.len)) & 63u))); + return wuffs_base__make_empty_struct(); + } + +-// -------- func png.decoder.decode_other_chunk ++// -------- func sha256.hasher.checksum_bitvec256 + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_other_chunk( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src, +- bool a_framy) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__bitvec256 ++wuffs_sha256__hasher__checksum_bitvec256( ++ const wuffs_sha256__hasher* self) { ++ if (!self) { ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_bitvec256(0u, 0u, 0u, 0u); + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_other_chunk[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ uint32_t v_buf_len = 0; ++ uint8_t v_buf_data[64] = {0}; ++ uint64_t v_length_in_bits = 0; ++ uint32_t v_w[64] = {0}; ++ uint32_t v_w2 = 0; ++ uint32_t v_w15 = 0; ++ uint32_t v_s0 = 0; ++ uint32_t v_s1 = 0; ++ uint32_t v_t1 = 0; ++ uint32_t v_t2 = 0; ++ uint32_t v_h0 = 0; ++ uint32_t v_h1 = 0; ++ uint32_t v_h2 = 0; ++ uint32_t v_h3 = 0; ++ uint32_t v_h4 = 0; ++ uint32_t v_h5 = 0; ++ uint32_t v_h6 = 0; ++ uint32_t v_h7 = 0; ++ uint32_t v_a = 0; ++ uint32_t v_b = 0; ++ uint32_t v_c = 0; ++ uint32_t v_d = 0; ++ uint32_t v_e = 0; ++ uint32_t v_f = 0; ++ uint32_t v_g = 0; ++ uint32_t v_h = 0; ++ uint32_t v_i = 0; ++ bool v_final_block = false; + +- if ((self->private_impl.f_chunk_type == 1163152464u) && ! a_framy) { +- if (self->private_impl.f_seen_plte) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } else if (self->private_impl.f_color_type == 3u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_png__decoder__decode_plte(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } else if ((self->private_impl.f_color_type == 2u) || (self->private_impl.f_color_type == 6u)) { +- } else { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_seen_plte = true; +- } else if ((self->private_impl.f_chunk_type & 32u) == 0u) { +- if (self->private_impl.f_chunk_type != 1413563465u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } ++ v_i = 0u; ++ while (v_i < 64u) { ++ v_buf_data[v_i] = self->private_impl.f_buf_data[v_i]; ++ v_i += 1u; ++ } ++ v_buf_len = (self->private_impl.f_buf_len & 63u); ++ if (v_buf_len < 56u) { ++ v_buf_data[v_buf_len] = 128u; ++ v_buf_len += 1u; ++ while (v_buf_len < 56u) { ++ v_buf_data[v_buf_len] = 0u; ++ v_buf_len += 1u; + } +- if (self->private_impl.f_chunk_type == 1716082789u) { +- if (self->private_impl.f_report_metadata_exif) { +- if (self->private_impl.f_seen_exif) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- status = wuffs_png__decoder__decode_exif(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_exif = true; +- } +- } else if ((self->private_impl.f_chunk_type == 1951945833u) || (self->private_impl.f_chunk_type == 1951942004u) || (self->private_impl.f_chunk_type == 1951945850u)) { +- if (self->private_impl.f_report_metadata_kvp) { +- self->private_impl.f_metadata_flavor = 4u; +- self->private_impl.f_metadata_fourcc = 1263947851u; +- self->private_impl.f_metadata_x = 0u; +- self->private_impl.f_metadata_y = 0u; +- self->private_impl.f_metadata_z = 0u; +- } +- } else if ( ! a_framy) { +- if (self->private_impl.f_chunk_type == 1280598881u) { +- if (self->private_impl.f_seen_actl) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- status = wuffs_png__decoder__decode_actl(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_actl = true; +- } else if (self->private_impl.f_chunk_type == 1297238115u) { +- if (self->private_impl.f_report_metadata_chrm) { +- if (self->private_impl.f_seen_chrm) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- status = wuffs_png__decoder__decode_chrm(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_chrm = true; +- } +- } else if (self->private_impl.f_chunk_type == 1280598886u) { +- if (self->private_impl.f_seen_fctl) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- status = wuffs_png__decoder__decode_fctl(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_fctl = true; +- } else if (self->private_impl.f_chunk_type == 1095582055u) { +- if (self->private_impl.f_report_metadata_gama) { +- if (self->private_impl.f_seen_gama) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- status = wuffs_png__decoder__decode_gama(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_gama = true; +- } +- } else if (self->private_impl.f_chunk_type == 1346585449u) { +- if (self->private_impl.f_report_metadata_iccp) { +- if (self->private_impl.f_seen_iccp) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- status = wuffs_png__decoder__decode_iccp(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_iccp = true; +- } +- } else if (self->private_impl.f_chunk_type == 1111970419u) { +- if (self->private_impl.f_report_metadata_srgb) { +- if (self->private_impl.f_seen_srgb) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- status = wuffs_png__decoder__decode_srgb(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_srgb = true; +- } +- } else if (self->private_impl.f_chunk_type == 1397641844u) { +- if (self->private_impl.f_seen_trns || (self->private_impl.f_color_type > 3u) || ((self->private_impl.f_color_type == 3u) && ! self->private_impl.f_seen_plte)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- status = wuffs_png__decoder__decode_trns(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_impl.f_seen_trns = true; +- } ++ v_final_block = true; ++ } else { ++ v_buf_data[v_buf_len] = 128u; ++ v_buf_len += 1u; ++ while (v_buf_len < 64u) { ++ v_buf_data[v_buf_len] = 0u; ++ v_buf_len += 1u; ++ } ++ } ++ v_h0 = self->private_impl.f_h0; ++ v_a = v_h0; ++ v_h1 = self->private_impl.f_h1; ++ v_b = v_h1; ++ v_h2 = self->private_impl.f_h2; ++ v_c = v_h2; ++ v_h3 = self->private_impl.f_h3; ++ v_d = v_h3; ++ v_h4 = self->private_impl.f_h4; ++ v_e = v_h4; ++ v_h5 = self->private_impl.f_h5; ++ v_f = v_h5; ++ v_h6 = self->private_impl.f_h6; ++ v_g = v_h6; ++ v_h7 = self->private_impl.f_h7; ++ v_h = v_h7; ++ while (true) { ++ if (v_final_block) { ++ v_length_in_bits = ((uint64_t)(self->private_impl.f_length_modulo_u64 * 8u)); ++ v_buf_data[56u] = ((uint8_t)((v_length_in_bits >> 56u))); ++ v_buf_data[57u] = ((uint8_t)((v_length_in_bits >> 48u))); ++ v_buf_data[58u] = ((uint8_t)((v_length_in_bits >> 40u))); ++ v_buf_data[59u] = ((uint8_t)((v_length_in_bits >> 32u))); ++ v_buf_data[60u] = ((uint8_t)((v_length_in_bits >> 24u))); ++ v_buf_data[61u] = ((uint8_t)((v_length_in_bits >> 16u))); ++ v_buf_data[62u] = ((uint8_t)((v_length_in_bits >> 8u))); ++ v_buf_data[63u] = ((uint8_t)(v_length_in_bits)); ++ } ++ v_w[0u] = ((((uint32_t)(v_buf_data[0u])) << 24u) | ++ (((uint32_t)(v_buf_data[1u])) << 16u) | ++ (((uint32_t)(v_buf_data[2u])) << 8u) | ++ ((uint32_t)(v_buf_data[3u]))); ++ v_w[1u] = ((((uint32_t)(v_buf_data[4u])) << 24u) | ++ (((uint32_t)(v_buf_data[5u])) << 16u) | ++ (((uint32_t)(v_buf_data[6u])) << 8u) | ++ ((uint32_t)(v_buf_data[7u]))); ++ v_w[2u] = ((((uint32_t)(v_buf_data[8u])) << 24u) | ++ (((uint32_t)(v_buf_data[9u])) << 16u) | ++ (((uint32_t)(v_buf_data[10u])) << 8u) | ++ ((uint32_t)(v_buf_data[11u]))); ++ v_w[3u] = ((((uint32_t)(v_buf_data[12u])) << 24u) | ++ (((uint32_t)(v_buf_data[13u])) << 16u) | ++ (((uint32_t)(v_buf_data[14u])) << 8u) | ++ ((uint32_t)(v_buf_data[15u]))); ++ v_w[4u] = ((((uint32_t)(v_buf_data[16u])) << 24u) | ++ (((uint32_t)(v_buf_data[17u])) << 16u) | ++ (((uint32_t)(v_buf_data[18u])) << 8u) | ++ ((uint32_t)(v_buf_data[19u]))); ++ v_w[5u] = ((((uint32_t)(v_buf_data[20u])) << 24u) | ++ (((uint32_t)(v_buf_data[21u])) << 16u) | ++ (((uint32_t)(v_buf_data[22u])) << 8u) | ++ ((uint32_t)(v_buf_data[23u]))); ++ v_w[6u] = ((((uint32_t)(v_buf_data[24u])) << 24u) | ++ (((uint32_t)(v_buf_data[25u])) << 16u) | ++ (((uint32_t)(v_buf_data[26u])) << 8u) | ++ ((uint32_t)(v_buf_data[27u]))); ++ v_w[7u] = ((((uint32_t)(v_buf_data[28u])) << 24u) | ++ (((uint32_t)(v_buf_data[29u])) << 16u) | ++ (((uint32_t)(v_buf_data[30u])) << 8u) | ++ ((uint32_t)(v_buf_data[31u]))); ++ v_w[8u] = ((((uint32_t)(v_buf_data[32u])) << 24u) | ++ (((uint32_t)(v_buf_data[33u])) << 16u) | ++ (((uint32_t)(v_buf_data[34u])) << 8u) | ++ ((uint32_t)(v_buf_data[35u]))); ++ v_w[9u] = ((((uint32_t)(v_buf_data[36u])) << 24u) | ++ (((uint32_t)(v_buf_data[37u])) << 16u) | ++ (((uint32_t)(v_buf_data[38u])) << 8u) | ++ ((uint32_t)(v_buf_data[39u]))); ++ v_w[10u] = ((((uint32_t)(v_buf_data[40u])) << 24u) | ++ (((uint32_t)(v_buf_data[41u])) << 16u) | ++ (((uint32_t)(v_buf_data[42u])) << 8u) | ++ ((uint32_t)(v_buf_data[43u]))); ++ v_w[11u] = ((((uint32_t)(v_buf_data[44u])) << 24u) | ++ (((uint32_t)(v_buf_data[45u])) << 16u) | ++ (((uint32_t)(v_buf_data[46u])) << 8u) | ++ ((uint32_t)(v_buf_data[47u]))); ++ v_w[12u] = ((((uint32_t)(v_buf_data[48u])) << 24u) | ++ (((uint32_t)(v_buf_data[49u])) << 16u) | ++ (((uint32_t)(v_buf_data[50u])) << 8u) | ++ ((uint32_t)(v_buf_data[51u]))); ++ v_w[13u] = ((((uint32_t)(v_buf_data[52u])) << 24u) | ++ (((uint32_t)(v_buf_data[53u])) << 16u) | ++ (((uint32_t)(v_buf_data[54u])) << 8u) | ++ ((uint32_t)(v_buf_data[55u]))); ++ v_w[14u] = ((((uint32_t)(v_buf_data[56u])) << 24u) | ++ (((uint32_t)(v_buf_data[57u])) << 16u) | ++ (((uint32_t)(v_buf_data[58u])) << 8u) | ++ ((uint32_t)(v_buf_data[59u]))); ++ v_w[15u] = ((((uint32_t)(v_buf_data[60u])) << 24u) | ++ (((uint32_t)(v_buf_data[61u])) << 16u) | ++ (((uint32_t)(v_buf_data[62u])) << 8u) | ++ ((uint32_t)(v_buf_data[63u]))); ++ v_i = 16u; ++ while (v_i < 64u) { ++ v_w2 = v_w[(v_i - 2u)]; ++ v_s1 = ((v_w2 >> 10u) ^ (((uint32_t)(v_w2 << 15u)) | (v_w2 >> 17u)) ^ (((uint32_t)(v_w2 << 13u)) | (v_w2 >> 19u))); ++ v_w15 = v_w[(v_i - 15u)]; ++ v_s0 = ((v_w15 >> 3u) ^ (((uint32_t)(v_w15 << 25u)) | (v_w15 >> 7u)) ^ (((uint32_t)(v_w15 << 14u)) | (v_w15 >> 18u))); ++ v_w[v_i] = ((uint32_t)(((uint32_t)(((uint32_t)(v_s1 + v_w[(v_i - 7u)])) + v_s0)) + v_w[(v_i - 16u)])); ++ v_i += 1u; + } +- if (self->private_impl.f_metadata_fourcc == 0u) { +- self->private_data.s_decode_other_chunk[0].scratch = self->private_impl.f_chunk_length; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- if (self->private_data.s_decode_other_chunk[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_decode_other_chunk[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_decode_other_chunk[0].scratch; ++ v_i = 0u; ++ while (v_i < 64u) { ++ v_t1 = v_h; ++ v_t1 += ((((uint32_t)(v_e << 26u)) | (v_e >> 6u)) ^ (((uint32_t)(v_e << 21u)) | (v_e >> 11u)) ^ (((uint32_t)(v_e << 7u)) | (v_e >> 25u))); ++ v_t1 += ((v_e & v_f) ^ ((4294967295u ^ v_e) & v_g)); ++ v_t1 += WUFFS_SHA256__K[v_i]; ++ v_t1 += v_w[v_i]; ++ v_t2 = ((((uint32_t)(v_a << 30u)) | (v_a >> 2u)) ^ (((uint32_t)(v_a << 19u)) | (v_a >> 13u)) ^ (((uint32_t)(v_a << 10u)) | (v_a >> 22u))); ++ v_t2 += ((v_a & v_b) ^ (v_a & v_c) ^ (v_b & v_c)); ++ v_h = v_g; ++ v_g = v_f; ++ v_f = v_e; ++ v_e = ((uint32_t)(v_d + v_t1)); ++ v_d = v_c; ++ v_c = v_b; ++ v_b = v_a; ++ v_a = ((uint32_t)(v_t1 + v_t2)); ++ v_i += 1u; ++ } ++ v_a += v_h0; ++ v_b += v_h1; ++ v_c += v_h2; ++ v_d += v_h3; ++ v_e += v_h4; ++ v_f += v_h5; ++ v_g += v_h6; ++ v_h += v_h7; ++ if (v_final_block) { ++ break; ++ } ++ v_final_block = true; ++ v_h0 = v_a; ++ v_h1 = v_b; ++ v_h2 = v_c; ++ v_h3 = v_d; ++ v_h4 = v_e; ++ v_h5 = v_f; ++ v_h6 = v_g; ++ v_h7 = v_h; ++ v_buf_len = 0u; ++ while (v_buf_len < 56u) { ++ v_buf_data[v_buf_len] = 0u; ++ v_buf_len += 1u; + } +- +- goto ok; +- ok: +- self->private_impl.p_decode_other_chunk[0] = 0; +- goto exit; + } ++ return wuffs_base__utility__make_bitvec256( ++ (((uint64_t)(v_h)) | (((uint64_t)(v_g)) << 32u)), ++ (((uint64_t)(v_f)) | (((uint64_t)(v_e)) << 32u)), ++ (((uint64_t)(v_d)) | (((uint64_t)(v_c)) << 32u)), ++ (((uint64_t)(v_b)) | (((uint64_t)(v_a)) << 32u))); ++} + +- goto suspend; +- suspend: +- self->private_impl.p_decode_other_chunk[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__SHA256) + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) + +- return status; +-} ++// ---------------- Status Codes Implementations + +-// -------- func png.decoder.decode_actl ++const char wuffs_tga__error__bad_header[] = "#tga: bad header"; ++const char wuffs_tga__error__bad_run_length_encoding[] = "#tga: bad run length encoding"; ++const char wuffs_tga__error__truncated_input[] = "#tga: truncated input"; ++const char wuffs_tga__error__unsupported_tga_file[] = "#tga: unsupported TGA file"; ++ ++// ---------------- Private Consts ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__decode_actl( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++wuffs_tga__decoder__do_decode_image_config( ++ wuffs_tga__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_tga__decoder__do_decode_frame_config( ++ wuffs_tga__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_tga__decoder__do_decode_frame( ++ wuffs_tga__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++// ---------------- VTables ++ ++const wuffs_base__image_decoder__func_ptrs ++wuffs_tga__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_tga__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_tga__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_tga__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_tga__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_tga__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_tga__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_tga__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_tga__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_tga__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_tga__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_tga__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_tga__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_tga__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_tga__decoder__initialize( ++ wuffs_tga__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_tga__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_tga__decoder* ++wuffs_tga__decoder__alloc(void) { ++ wuffs_tga__decoder* x = ++ (wuffs_tga__decoder*)(calloc(1, sizeof(wuffs_tga__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_tga__decoder__initialize( ++ x, sizeof(wuffs_tga__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; + } ++ return x; ++} + +- uint32_t coro_susp_point = self->private_impl.p_decode_actl[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++size_t ++sizeof__wuffs_tga__decoder(void) { ++ return sizeof(wuffs_tga__decoder); ++} + +- if (self->private_impl.f_chunk_length != 8u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } else if (self->private_impl.f_interlace_pass > 0u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); +- goto exit; +- } +- self->private_impl.f_chunk_length = 0u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_actl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_actl[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } +- } +- self->private_impl.f_num_animation_frames_value = t_0; +- } +- if (self->private_impl.f_num_animation_frames_value == 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_actl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_actl[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); +- if (num_bits_1 == 24) { +- t_1 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)); +- } +- } +- self->private_impl.f_num_animation_loops_value = t_1; +- } ++// ---------------- Function Implementations + +- goto ok; +- ok: +- self->private_impl.p_decode_actl[0] = 0; +- goto exit; ++// -------- func tga.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_tga__decoder__get_quirk( ++ const wuffs_tga__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } + +- goto suspend; +- suspend: +- self->private_impl.p_decode_actl[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ return 0u; ++} + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++// -------- func tga.decoder.set_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__set_quirk( ++ wuffs_tga__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); + } + +- return status; ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func png.decoder.decode_chrm ++// -------- func tga.decoder.decode_image_config + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_chrm( +- wuffs_png__decoder* self, ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__decode_image_config( ++ wuffs_tga__decoder* self, ++ wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint64_t v_u = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_chrm[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_chunk_length != 32u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length = 0u; +- self->private_impl.f_metadata_flavor = 5u; +- self->private_impl.f_metadata_fourcc = 1128813133u; +- self->private_impl.f_metadata_x = 0u; +- self->private_impl.f_metadata_y = 0u; +- self->private_impl.f_metadata_z = 0u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint64_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_chrm[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 24) { +- t_0 = ((uint64_t)(*scratch >> 32)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } +- } +- v_u = t_0; +- } +- self->private_impl.f_metadata_x |= ((16777215u & v_u) << 0u); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint64_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_chrm[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); +- if (num_bits_1 == 24) { +- t_1 = ((uint64_t)(*scratch >> 32)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)); +- } +- } +- v_u = t_1; +- } +- self->private_impl.f_metadata_x |= ((16777215u & v_u) << 24u); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- uint64_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_2 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_chrm[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); +- if (num_bits_2 == 24) { +- t_2 = ((uint64_t)(*scratch >> 32)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)); +- } +- } +- v_u = t_2; +- } +- self->private_impl.f_metadata_x |= ((uint64_t)((16777215u & v_u) << 48u)); +- self->private_impl.f_metadata_y |= ((16777215u & v_u) >> 16u); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- uint64_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_3 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_chrm[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); +- if (num_bits_3 == 24) { +- t_3 = ((uint64_t)(*scratch >> 32)); +- break; +- } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)); +- } +- } +- v_u = t_3; +- } +- self->private_impl.f_metadata_y |= ((16777215u & v_u) << 8u); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- uint64_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_4 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_chrm[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); +- if (num_bits_4 == 24) { +- t_4 = ((uint64_t)(*scratch >> 32)); +- break; +- } +- num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)); +- } +- } +- v_u = t_4; +- } +- self->private_impl.f_metadata_y |= ((16777215u & v_u) << 32u); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); +- uint64_t t_5; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_5 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_chrm[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch; +- uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); +- if (num_bits_5 == 24) { +- t_5 = ((uint64_t)(*scratch >> 32)); +- break; +- } +- num_bits_5 += 8u; +- *scratch |= ((uint64_t)(num_bits_5)); +- } +- } +- v_u = t_5; +- } +- self->private_impl.f_metadata_y |= ((uint64_t)((16777215u & v_u) << 56u)); +- self->private_impl.f_metadata_z |= ((16777215u & v_u) >> 8u); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); +- uint64_t t_6; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_6 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_chrm[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch; +- uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6); +- if (num_bits_6 == 24) { +- t_6 = ((uint64_t)(*scratch >> 32)); +- break; +- } +- num_bits_6 += 8u; +- *scratch |= ((uint64_t)(num_bits_6)); +- } ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_tga__decoder__do_decode_image_config(self, a_dst, a_src); ++ v_status = t_0; + } +- v_u = t_6; +- } +- self->private_impl.f_metadata_z |= ((16777215u & v_u) << 16u); +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); +- uint64_t t_7; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_7 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_chrm[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch; +- uint32_t num_bits_7 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_7); +- if (num_bits_7 == 24) { +- t_7 = ((uint64_t)(*scratch >> 32)); +- break; +- } +- num_bits_7 += 8u; +- *scratch |= ((uint64_t)(num_bits_7)); +- } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_tga__error__truncated_input); ++ goto exit; + } +- v_u = t_7; ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); + } +- self->private_impl.f_metadata_z |= ((16777215u & v_u) << 40u); + +- goto ok; + ok: +- self->private_impl.p_decode_chrm[0] = 0; ++ self->private_impl.p_decode_image_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_chrm[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func png.decoder.decode_exif +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_exif( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } +- +- if (self->private_impl.f_chunk_length < 4u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_metadata_flavor = 3u; +- self->private_impl.f_metadata_fourcc = 1163413830u; +- self->private_impl.f_metadata_x = 0u; +- self->private_impl.f_metadata_y = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- self->private_impl.f_metadata_z = wuffs_base__u64__sat_add(self->private_impl.f_metadata_y, ((uint64_t)(self->private_impl.f_chunk_length))); +- self->private_impl.f_chunk_length = 0u; ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; + +- goto ok; +- ok: + goto exit; + exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; + } +- + return status; + } + +-// -------- func png.decoder.decode_fctl ++// -------- func tga.decoder.do_decode_image_config + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__decode_fctl( +- wuffs_png__decoder* self, ++wuffs_tga__decoder__do_decode_image_config( ++ wuffs_tga__decoder* self, ++ wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_x0 = 0; +- uint32_t v_y0 = 0; +- uint32_t v_x1 = 0; +- uint32_t v_y1 = 0; ++ uint32_t v_c32 = 0; ++ uint32_t v_c5 = 0; ++ uint32_t v_i = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -55899,309 +69341,577 @@ wuffs_png__decoder__decode_fctl( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_fctl[0]; ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config; + if (coro_susp_point) { +- v_x0 = self->private_data.s_decode_fctl[0].v_x0; +- v_x1 = self->private_data.s_decode_fctl[0].v_x1; +- v_y1 = self->private_data.s_decode_fctl[0].v_y1; ++ v_i = self->private_data.s_do_decode_image_config.v_i; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_chunk_length != 26u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ if (self->private_impl.f_call_sequence != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); + goto exit; + } +- self->private_impl.f_chunk_length = 0u; + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_fctl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- v_x0 = t_0; ++ uint8_t t_0 = *iop_a_src++; ++ self->private_impl.f_header_id_length = t_0; + } +- if (v_x0 != self->private_impl.f_next_animation_seq_num) { +- status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number); +- goto exit; +- } else if (self->private_impl.f_next_animation_seq_num >= 4294967295u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ self->private_impl.f_header_color_map_type = t_1; ++ } ++ if (self->private_impl.f_header_color_map_type > 1u) { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_header); + goto exit; + } +- self->private_impl.f_next_animation_seq_num += 1u; + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_fctl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); +- if (num_bits_1 == 24) { +- t_1 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)); +- } ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- v_x1 = t_1; ++ uint8_t t_2 = *iop_a_src++; ++ self->private_impl.f_header_image_type = t_2; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- uint32_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_fctl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); +- if (num_bits_2 == 24) { +- t_2 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)); +- } +- } +- v_y1 = t_2; ++ if ((self->private_impl.f_header_image_type == 1u) || ++ (self->private_impl.f_header_image_type == 2u) || ++ (self->private_impl.f_header_image_type == 3u) || ++ (self->private_impl.f_header_image_type == 9u) || ++ (self->private_impl.f_header_image_type == 10u) || ++ (self->private_impl.f_header_image_type == 11u)) { ++ } else { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_header); ++ goto exit; + } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- uint32_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ uint16_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_3 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); ++ iop_a_src += 2; + } else { +- self->private_data.s_decode_fctl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); +- if (num_bits_3 == 24) { +- t_3 = ((uint32_t)(*scratch >> 32)); ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; ++ if (num_bits_3 == 8) { ++ t_3 = ((uint16_t)(*scratch)); + break; + } + num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)); ++ *scratch |= ((uint64_t)(num_bits_3)) << 56; + } + } +- v_x0 = t_3; ++ self->private_impl.f_header_color_map_first_entry_index = t_3; + } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- uint32_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_4 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ uint16_t t_4; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_4 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); ++ iop_a_src += 2; + } else { +- self->private_data.s_decode_fctl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4); +- if (num_bits_4 == 24) { +- t_4 = ((uint32_t)(*scratch >> 32)); ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; ++ if (num_bits_4 == 8) { ++ t_4 = ((uint16_t)(*scratch)); + break; + } + num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)); ++ *scratch |= ((uint64_t)(num_bits_4)) << 56; + } + } +- v_y0 = t_4; ++ self->private_impl.f_header_color_map_length = t_4; + } +- v_x1 += v_x0; +- v_y1 += v_y0; +- if ((v_x0 >= v_x1) || +- (v_x0 > self->private_impl.f_width) || +- (v_x1 > self->private_impl.f_width) || +- (v_y0 >= v_y1) || +- (v_y0 > self->private_impl.f_height) || +- (v_y1 > self->private_impl.f_height)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ self->private_impl.f_header_color_map_entry_size = t_5; + } +- self->private_impl.f_frame_rect_x0 = v_x0; +- self->private_impl.f_frame_rect_y0 = v_y0; +- self->private_impl.f_frame_rect_x1 = v_x1; +- self->private_impl.f_frame_rect_y1 = v_y1; ++ if (self->private_impl.f_header_color_map_type != 0u) { ++ if ((self->private_impl.f_header_color_map_first_entry_index != 0u) || (self->private_impl.f_header_color_map_length > 256u)) { ++ status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file); ++ goto exit; ++ } else if ((self->private_impl.f_header_color_map_entry_size != 15u) && ++ (self->private_impl.f_header_color_map_entry_size != 16u) && ++ (self->private_impl.f_header_color_map_entry_size != 24u) && ++ (self->private_impl.f_header_color_map_entry_size != 32u)) { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_header); ++ goto exit; ++ } ++ } else { ++ if ((self->private_impl.f_header_color_map_first_entry_index != 0u) || (self->private_impl.f_header_color_map_length != 0u) || (self->private_impl.f_header_color_map_entry_size != 0u)) { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_header); ++ goto exit; ++ } ++ } ++ self->private_data.s_do_decode_image_config.scratch = 4u; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ if (self->private_data.s_do_decode_image_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_image_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_image_config.scratch; + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); +- uint32_t t_5; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ uint32_t t_6; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_5 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ t_6 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); + iop_a_src += 2; + } else { +- self->private_data.s_decode_fctl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch; +- uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); +- if (num_bits_5 == 8) { +- t_5 = ((uint32_t)(*scratch >> 48)); ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6; ++ if (num_bits_6 == 8) { ++ t_6 = ((uint32_t)(*scratch)); + break; + } +- num_bits_5 += 8u; +- *scratch |= ((uint64_t)(num_bits_5)); ++ num_bits_6 += 8u; ++ *scratch |= ((uint64_t)(num_bits_6)) << 56; + } + } +- v_x0 = t_5; ++ self->private_impl.f_width = t_6; + } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); +- uint32_t t_6; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ uint32_t t_7; + if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_6 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); ++ t_7 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); + iop_a_src += 2; + } else { +- self->private_data.s_decode_fctl[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch; +- uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6); +- if (num_bits_6 == 8) { +- t_6 = ((uint32_t)(*scratch >> 48)); ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7; ++ if (num_bits_7 == 8) { ++ t_7 = ((uint32_t)(*scratch)); + break; + } +- num_bits_6 += 8u; +- *scratch |= ((uint64_t)(num_bits_6)); ++ num_bits_7 += 8u; ++ *scratch |= ((uint64_t)(num_bits_7)) << 56; + } + } +- v_x1 = t_6; +- } +- if (v_x1 <= 0u) { +- self->private_impl.f_frame_duration = (((uint64_t)(v_x0)) * 7056000u); +- } else { +- self->private_impl.f_frame_duration = ((((uint64_t)(v_x0)) * 705600000u) / ((uint64_t)(v_x1))); ++ self->private_impl.f_height = t_7; + } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint32_t t_7 = *iop_a_src++; +- v_x0 = t_7; ++ uint8_t t_8 = *iop_a_src++; ++ self->private_impl.f_header_pixel_depth = t_8; + } +- if (v_x0 == 0u) { +- self->private_impl.f_frame_disposal = 0u; +- } else if (v_x0 == 1u) { +- self->private_impl.f_frame_disposal = 1u; +- } else if (v_x0 == 2u) { +- self->private_impl.f_frame_disposal = 2u; +- } else { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ if ((self->private_impl.f_header_pixel_depth != 1u) && ++ (self->private_impl.f_header_pixel_depth != 8u) && ++ (self->private_impl.f_header_pixel_depth != 15u) && ++ (self->private_impl.f_header_pixel_depth != 16u) && ++ (self->private_impl.f_header_pixel_depth != 24u) && ++ (self->private_impl.f_header_pixel_depth != 32u)) { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_header); + goto exit; + } ++ if (((uint8_t)(self->private_impl.f_header_image_type | 8u)) == 9u) { ++ self->private_impl.f_scratch_bytes_per_pixel = 1u; ++ self->private_impl.f_src_bytes_per_pixel = 1u; ++ self->private_impl.f_src_pixfmt = 2164523016u; ++ self->private_impl.f_opaque = ((self->private_impl.f_header_color_map_entry_size == 15u) || (self->private_impl.f_header_color_map_entry_size == 24u)); ++ } else if (((uint8_t)(self->private_impl.f_header_image_type | 8u)) == 10u) { ++ if ((self->private_impl.f_header_pixel_depth == 15u) || (self->private_impl.f_header_pixel_depth == 16u)) { ++ self->private_impl.f_scratch_bytes_per_pixel = 4u; ++ self->private_impl.f_src_bytes_per_pixel = 0u; ++ self->private_impl.f_src_pixfmt = 2164295816u; ++ } else if (self->private_impl.f_header_pixel_depth == 24u) { ++ self->private_impl.f_scratch_bytes_per_pixel = 3u; ++ self->private_impl.f_src_bytes_per_pixel = 3u; ++ self->private_impl.f_src_pixfmt = 2147485832u; ++ self->private_impl.f_opaque = true; ++ } else if (self->private_impl.f_header_pixel_depth == 32u) { ++ self->private_impl.f_scratch_bytes_per_pixel = 4u; ++ self->private_impl.f_src_bytes_per_pixel = 4u; ++ self->private_impl.f_src_pixfmt = 2164295816u; ++ } else { ++ status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file); ++ goto exit; ++ } ++ } else { ++ if (self->private_impl.f_header_pixel_depth == 8u) { ++ self->private_impl.f_scratch_bytes_per_pixel = 1u; ++ self->private_impl.f_src_bytes_per_pixel = 1u; ++ self->private_impl.f_src_pixfmt = 536870920u; ++ self->private_impl.f_opaque = true; ++ } else { ++ status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file); ++ goto exit; ++ } ++ } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint32_t t_8 = *iop_a_src++; +- v_x0 = t_8; +- } +- if (v_x0 == 0u) { +- self->private_impl.f_frame_overwrite_instead_of_blend = true; +- } else if (v_x0 == 1u) { +- self->private_impl.f_frame_overwrite_instead_of_blend = false; ++ uint8_t t_9 = *iop_a_src++; ++ self->private_impl.f_header_image_descriptor = t_9; ++ } ++ if (((uint8_t)(self->private_impl.f_header_image_descriptor & 16u)) != 0u) { ++ status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file); ++ goto exit; ++ } ++ self->private_data.s_do_decode_image_config.scratch = ((uint32_t)(self->private_impl.f_header_id_length)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ if (self->private_data.s_do_decode_image_config.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_image_config.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_image_config.scratch; ++ if (self->private_impl.f_header_color_map_type != 0u) { ++ while (v_i < ((uint32_t)(self->private_impl.f_header_color_map_length))) { ++ if (self->private_impl.f_header_color_map_entry_size == 24u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17); ++ uint32_t t_10; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { ++ t_10 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); ++ iop_a_src += 3; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10; ++ if (num_bits_10 == 16) { ++ t_10 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_10 += 8u; ++ *scratch |= ((uint64_t)(num_bits_10)) << 56; ++ } ++ } ++ v_c32 = t_10; ++ } ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 0u)] = ((uint8_t)((v_c32 >> 0u))); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 1u)] = ((uint8_t)((v_c32 >> 8u))); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 2u)] = ((uint8_t)((v_c32 >> 16u))); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 3u)] = 255u; ++ } else if (self->private_impl.f_header_color_map_entry_size == 32u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19); ++ uint32_t t_11; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_11 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11; ++ if (num_bits_11 == 24) { ++ t_11 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_11 += 8u; ++ *scratch |= ((uint64_t)(num_bits_11)) << 56; ++ } ++ } ++ v_c32 = t_11; ++ } ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 0u)] = ((uint8_t)((v_c32 >> 0u))); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 1u)] = ((uint8_t)((v_c32 >> 8u))); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 2u)] = ((uint8_t)((v_c32 >> 16u))); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 3u)] = ((uint8_t)((v_c32 >> 24u))); ++ } else { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21); ++ uint32_t t_12; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_12 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_12 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_12; ++ if (num_bits_12 == 8) { ++ t_12 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_12 += 8u; ++ *scratch |= ((uint64_t)(num_bits_12)) << 56; ++ } ++ } ++ v_c32 = t_12; ++ } ++ v_c5 = (31u & (v_c32 >> 0u)); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 0u)] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ v_c5 = (31u & (v_c32 >> 5u)); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 1u)] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ v_c5 = (31u & (v_c32 >> 10u)); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 2u)] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 3u)] = 255u; ++ } ++ v_i += 1u; ++ } ++ while (v_i < 256u) { ++ self->private_data.f_src_palette[((v_i * 4u) + 0u)] = 0u; ++ self->private_data.f_src_palette[((v_i * 4u) + 1u)] = 0u; ++ self->private_data.f_src_palette[((v_i * 4u) + 2u)] = 0u; ++ self->private_data.f_src_palette[((v_i * 4u) + 3u)] = 255u; ++ v_i += 1u; ++ } ++ } ++ self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ if (a_dst != NULL) { ++ wuffs_base__image_config__set( ++ a_dst, ++ self->private_impl.f_src_pixfmt, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ self->private_impl.f_frame_config_io_position, ++ self->private_impl.f_opaque); ++ } ++ self->private_impl.f_call_sequence = 32u; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_do_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_image_config.v_i = v_i; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func tga.decoder.decode_frame_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__decode_frame_config( ++ wuffs_tga__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 2)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_tga__decoder__do_decode_frame_config(self, a_dst, a_src); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_tga__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func tga.decoder.do_decode_frame_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_tga__decoder__do_decode_frame_config( ++ wuffs_tga__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame_config; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_tga__decoder__do_decode_image_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); ++ goto exit; ++ } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ self->private_impl.f_call_sequence = 96u; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; + } else { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; + } +- if (self->private_impl.f_num_decoded_frame_configs_value == 0u) { +- self->private_impl.f_first_rect_x0 = self->private_impl.f_frame_rect_x0; +- self->private_impl.f_first_rect_y0 = self->private_impl.f_frame_rect_y0; +- self->private_impl.f_first_rect_x1 = self->private_impl.f_frame_rect_x1; +- self->private_impl.f_first_rect_y1 = self->private_impl.f_frame_rect_y1; +- self->private_impl.f_first_duration = self->private_impl.f_frame_duration; +- self->private_impl.f_first_disposal = self->private_impl.f_frame_disposal; +- self->private_impl.f_first_overwrite_instead_of_blend = self->private_impl.f_frame_overwrite_instead_of_blend; ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height), ++ ((wuffs_base__flicks)(0u)), ++ 0u, ++ self->private_impl.f_frame_config_io_position, ++ 0u, ++ self->private_impl.f_opaque, ++ false, ++ 4278190080u); + } ++ self->private_impl.f_call_sequence = 64u; + +- goto ok; + ok: +- self->private_impl.p_decode_fctl[0] = 0; ++ self->private_impl.p_do_decode_frame_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_fctl[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_fctl[0].v_x0 = v_x0; +- self->private_data.s_decode_fctl[0].v_x1 = v_x1; +- self->private_data.s_decode_fctl[0].v_y1 = v_y1; ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +@@ -56212,15 +69922,114 @@ wuffs_png__decoder__decode_fctl( + return status; + } + +-// -------- func png.decoder.decode_gama ++// -------- func tga.decoder.decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__decode_frame( ++ wuffs_tga__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 3)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_tga__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_tga__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func tga.decoder.do_decode_frame + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__decode_gama( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { ++wuffs_tga__decoder__do_decode_frame( ++ wuffs_tga__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { + wuffs_base__status status = wuffs_base__make_status(NULL); + ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint64_t v_dst_bytes_per_pixel = 0; ++ uint32_t v_dst_x = 0; ++ uint32_t v_dst_y = 0; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_dst_palette = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint64_t v_dst_start = 0; ++ wuffs_base__slice_u8 v_src_palette = {0}; ++ uint64_t v_mark = 0; ++ uint64_t v_num_pixels64 = 0; ++ uint32_t v_num_pixels32 = 0; ++ uint32_t v_lit_length = 0; ++ uint32_t v_run_length = 0; ++ uint64_t v_num_dst_bytes = 0; ++ uint32_t v_num_src_bytes = 0; ++ uint32_t v_c32 = 0; ++ uint32_t v_c5 = 0; ++ + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -56232,516 +70041,739 @@ wuffs_png__decoder__decode_gama( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_gama[0]; ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame; ++ if (coro_susp_point) { ++ v_dst_bytes_per_pixel = self->private_data.s_do_decode_frame.v_dst_bytes_per_pixel; ++ v_dst_x = self->private_data.s_do_decode_frame.v_dst_x; ++ v_dst_y = self->private_data.s_do_decode_frame.v_dst_y; ++ v_mark = self->private_data.s_do_decode_frame.v_mark; ++ v_num_pixels32 = self->private_data.s_do_decode_frame.v_num_pixels32; ++ v_lit_length = self->private_data.s_do_decode_frame.v_lit_length; ++ v_run_length = self->private_data.s_do_decode_frame.v_run_length; ++ v_num_dst_bytes = self->private_data.s_do_decode_frame.v_num_dst_bytes; ++ } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_chunk_length != 4u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_tga__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ if (self->private_impl.f_header_color_map_type != 0u) { ++ v_src_palette = wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024); ++ } ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), ++ wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt), ++ v_src_palette, ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_option); + goto exit; + } +- self->private_impl.f_chunk_length = 0u; +- self->private_impl.f_metadata_flavor = 5u; +- self->private_impl.f_metadata_fourcc = 1195461953u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint64_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src))); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_gama[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_gama[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 24) { +- t_0 = ((uint64_t)(*scratch >> 32)); +- break; ++ v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8u))); ++ if (((uint8_t)(self->private_impl.f_header_image_descriptor & 32u)) == 0u) { ++ v_dst_y = ((uint32_t)(self->private_impl.f_height - 1u)); ++ } ++ if (((uint8_t)(self->private_impl.f_header_image_type & 8u)) == 0u) { ++ v_lit_length = self->private_impl.f_width; ++ } ++ label__resume__continue:; ++ while (true) { ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)); ++ while (v_dst_y < self->private_impl.f_height) { ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, v_dst_y); ++ v_dst_start = (((uint64_t)(v_dst_x)) * v_dst_bytes_per_pixel); ++ if (v_dst_start <= ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_start); ++ } else { ++ v_dst = wuffs_base__utility__empty_slice_u8(); ++ } ++ while (v_dst_x < self->private_impl.f_width) { ++ if (self->private_impl.f_src_bytes_per_pixel > 0u) { ++ if (v_lit_length > 0u) { ++ v_mark = ((uint64_t)(iop_a_src - io0_a_src)); ++ v_num_pixels64 = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(self->private_impl.f_src_bytes_per_pixel))); ++ v_num_pixels32 = ((uint32_t)(wuffs_base__u64__min(v_num_pixels64, ((uint64_t)(v_lit_length))))); ++ v_num_dst_bytes = (((uint64_t)(v_num_pixels32)) * v_dst_bytes_per_pixel); ++ v_num_src_bytes = (v_num_pixels32 * self->private_impl.f_src_bytes_per_pixel); ++ self->private_data.s_do_decode_frame.scratch = v_num_src_bytes; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (self->private_data.s_do_decode_frame.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_decode_frame.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_decode_frame.scratch; ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_private_impl__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); ++ if (v_num_dst_bytes <= ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_num_dst_bytes); ++ } else { ++ v_dst = wuffs_base__utility__empty_slice_u8(); ++ } ++ v_dst_x += v_num_pixels32; ++ v_lit_length = (((uint32_t)(v_lit_length - v_num_pixels32)) & 65535u); ++ if (v_lit_length > 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); ++ goto label__resume__continue; ++ } ++ } else if (v_run_length > 0u) { ++ v_run_length -= 1u; ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_scratch_bytes_per_pixel)); ++ if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel); ++ } ++ v_dst_x += 1u; ++ } else { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); ++ goto label__resume__continue; ++ } ++ if (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) < 128u) { ++ v_lit_length = (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) + 1u); ++ iop_a_src += 1u; ++ if ((v_lit_length + v_dst_x) > self->private_impl.f_width) { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding); ++ goto exit; ++ } ++ } else { ++ if (self->private_impl.f_src_bytes_per_pixel == 1u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ goto label__resume__continue; ++ } ++ v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127u) + 1u); ++ iop_a_src += 1u; ++ self->private_data.f_scratch[0u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ } else if (self->private_impl.f_src_bytes_per_pixel == 3u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); ++ goto label__resume__continue; ++ } ++ v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127u) + 1u); ++ iop_a_src += 1u; ++ self->private_data.f_scratch[0u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ self->private_data.f_scratch[1u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ self->private_data.f_scratch[2u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ } else { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 5u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); ++ goto label__resume__continue; ++ } ++ v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127u) + 1u); ++ iop_a_src += 1u; ++ self->private_data.f_scratch[0u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ self->private_data.f_scratch[1u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ self->private_data.f_scratch[2u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ self->private_data.f_scratch[3u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; ++ } ++ if ((v_run_length + v_dst_x) > self->private_impl.f_width) { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding); ++ goto exit; ++ } ++ } ++ } ++ } else { ++ if (v_lit_length > 0u) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); ++ goto label__resume__continue; ++ } ++ v_c32 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2u; ++ v_c5 = (31u & (v_c32 >> 0u)); ++ self->private_data.f_scratch[0u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ v_c5 = (31u & (v_c32 >> 5u)); ++ self->private_data.f_scratch[1u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ v_c5 = (31u & (v_c32 >> 10u)); ++ self->private_data.f_scratch[2u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ self->private_data.f_scratch[3u] = 255u; ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, 4)); ++ if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel); ++ } ++ v_dst_x += 1u; ++ v_lit_length -= 1u; ++ } else if (v_run_length > 0u) { ++ v_run_length -= 1u; ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_scratch_bytes_per_pixel)); ++ if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel); ++ } ++ v_dst_x += 1u; ++ } else { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); ++ goto label__resume__continue; ++ } ++ if (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) < 128u) { ++ v_lit_length = (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) + 1u); ++ iop_a_src += 1u; ++ if ((v_lit_length + v_dst_x) > self->private_impl.f_width) { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding); ++ goto exit; ++ } ++ } else { ++ if (((uint64_t)(io2_a_src - iop_a_src)) < 3u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); ++ goto label__resume__continue; ++ } ++ v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127u) + 1u); ++ iop_a_src += 1u; ++ v_c32 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2u; ++ v_c5 = (31u & (v_c32 >> 0u)); ++ self->private_data.f_scratch[0u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ v_c5 = (31u & (v_c32 >> 5u)); ++ self->private_data.f_scratch[1u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ v_c5 = (31u & (v_c32 >> 10u)); ++ self->private_data.f_scratch[2u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); ++ self->private_data.f_scratch[3u] = 255u; ++ if ((v_run_length + v_dst_x) > self->private_impl.f_width) { ++ status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding); ++ goto exit; ++ } ++ } ++ } + } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); ++ } ++ v_dst_x = 0u; ++ if (((uint8_t)(self->private_impl.f_header_image_descriptor & 32u)) == 0u) { ++ v_dst_y -= 1u; ++ } else { ++ v_dst_y += 1u; ++ } ++ if (((uint8_t)(self->private_impl.f_header_image_type & 8u)) == 0u) { ++ v_lit_length = self->private_impl.f_width; + } + } +- self->private_impl.f_metadata_x = t_0; ++ break; + } +- self->private_impl.f_metadata_y = 0u; +- self->private_impl.f_metadata_z = 0u; ++ self->private_impl.f_call_sequence = 96u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_frame.v_dst_bytes_per_pixel = v_dst_bytes_per_pixel; ++ self->private_data.s_do_decode_frame.v_dst_x = v_dst_x; ++ self->private_data.s_do_decode_frame.v_dst_y = v_dst_y; ++ self->private_data.s_do_decode_frame.v_mark = v_mark; ++ self->private_data.s_do_decode_frame.v_num_pixels32 = v_num_pixels32; ++ self->private_data.s_do_decode_frame.v_lit_length = v_lit_length; ++ self->private_data.s_do_decode_frame.v_run_length = v_run_length; ++ self->private_data.s_do_decode_frame.v_num_dst_bytes = v_num_dst_bytes; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func tga.decoder.frame_dirty_rect ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 ++wuffs_tga__decoder__frame_dirty_rect( ++ const wuffs_tga__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_rect_ie_u32(); ++ } ++ ++ return wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height); ++} ++ ++// -------- func tga.decoder.num_animation_loops ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_tga__decoder__num_animation_loops( ++ const wuffs_tga__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ return 0u; ++} ++ ++// -------- func tga.decoder.num_decoded_frame_configs ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_tga__decoder__num_decoded_frame_configs( ++ const wuffs_tga__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 32u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func tga.decoder.num_decoded_frames ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_tga__decoder__num_decoded_frames( ++ const wuffs_tga__decoder* self) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ if (self->private_impl.f_call_sequence > 64u) { ++ return 1u; ++ } ++ return 0u; ++} ++ ++// -------- func tga.decoder.restart_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__restart_frame( ++ wuffs_tga__decoder* self, ++ uint64_t a_index, ++ uint64_t a_io_position) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ if (self->private_impl.f_call_sequence < 32u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); ++ } ++ if (a_index != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ self->private_impl.f_call_sequence = 40u; ++ self->private_impl.f_frame_config_io_position = a_io_position; ++ return wuffs_base__make_status(NULL); ++} + +- goto ok; +- ok: +- self->private_impl.p_decode_gama[0] = 0; +- goto exit; ++// -------- func tga.decoder.set_report_metadata ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_tga__decoder__set_report_metadata( ++ wuffs_tga__decoder* self, ++ uint32_t a_fourcc, ++ bool a_report) { ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func tga.decoder.tell_me_more ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_tga__decoder__tell_me_more( ++ wuffs_tga__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- goto suspend; +- suspend: +- self->private_impl.p_decode_gama[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); ++ goto exit; + ++ goto ok; ++ ok: + goto exit; + exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; + } +- + return status; + } + +-// -------- func png.decoder.decode_iccp ++// -------- func tga.decoder.workbuf_len + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_iccp( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint8_t v_c = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_tga__decoder__workbuf_len( ++ const wuffs_tga__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); + } + +- uint32_t coro_susp_point = self->private_impl.p_decode_iccp[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++} + +- while (true) { +- if (self->private_impl.f_chunk_length <= 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length -= 1u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if (v_c == 0u) { +- break; +- } +- } +- if (self->private_impl.f_chunk_length <= 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length -= 1u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; +- } +- if (v_c != 0u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method); +- goto exit; +- } +- self->private_impl.f_metadata_is_zlib_compressed = true; +- self->private_impl.f_metadata_flavor = 4u; +- self->private_impl.f_metadata_fourcc = 1229144912u; +- self->private_impl.f_metadata_x = 0u; +- self->private_impl.f_metadata_y = 0u; +- self->private_impl.f_metadata_z = 0u; ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) + +- goto ok; +- ok: +- self->private_impl.p_decode_iccp[0] = 0; +- goto exit; +- } ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__VP8) + +- goto suspend; +- suspend: +- self->private_impl.p_decode_iccp[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++// ---------------- Status Codes Implementations + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++// ---------------- Private Consts + +- return status; +-} ++// ---------------- Private Initializer Prototypes + +-// -------- func png.decoder.decode_plte ++// ---------------- Private Function Prototypes + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_plte( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++// ---------------- VTables + +- uint32_t v_num_entries = 0; +- uint32_t v_i = 0; +- uint32_t v_argb = 0; ++// ---------------- Initializer Implementations + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_vp8__placeholder__initialize( ++ wuffs_vp8__placeholder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- +- uint32_t coro_susp_point = self->private_impl.p_decode_plte[0]; +- if (coro_susp_point) { +- v_num_entries = self->private_data.s_decode_plte[0].v_num_entries; +- v_i = self->private_data.s_decode_plte[0].v_i; ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); + } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((self->private_impl.f_chunk_length > 768u) || ((self->private_impl.f_chunk_length % 3u) != 0u)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- v_num_entries = (((uint32_t)(self->private_impl.f_chunk_length)) / 3u); +- self->private_impl.f_chunk_length = 0u; +- while (v_i < v_num_entries) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { +- t_0 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src))); +- iop_a_src += 3; +- } else { +- self->private_data.s_decode_plte[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_plte[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 16) { +- t_0 = ((uint32_t)(*scratch >> 40)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } +- } +- v_argb = t_0; +- } +- v_argb |= 4278190080u; +- self->private_data.f_src_palette[((4u * v_i) + 0u)] = ((uint8_t)((v_argb >> 0u))); +- self->private_data.f_src_palette[((4u * v_i) + 1u)] = ((uint8_t)((v_argb >> 8u))); +- self->private_data.f_src_palette[((4u * v_i) + 2u)] = ((uint8_t)((v_argb >> 16u))); +- self->private_data.f_src_palette[((4u * v_i) + 3u)] = ((uint8_t)((v_argb >> 24u))); +- v_i += 1u; ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); + } +- while (v_i < 256u) { +- self->private_data.f_src_palette[((4u * v_i) + 0u)] = 0u; +- self->private_data.f_src_palette[((4u * v_i) + 1u)] = 0u; +- self->private_data.f_src_palette[((4u * v_i) + 2u)] = 0u; +- self->private_data.f_src_palette[((4u * v_i) + 3u)] = 255u; +- v_i += 1u; ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); + } +- +- goto ok; +- ok: +- self->private_impl.p_decode_plte[0] = 0; +- goto exit; + } + +- goto suspend; +- suspend: +- self->private_impl.p_decode_plte[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_plte[0].v_num_entries = v_num_entries; +- self->private_data.s_decode_plte[0].v_i = v_i; ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ return wuffs_base__make_status(NULL); ++} + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++wuffs_vp8__placeholder* ++wuffs_vp8__placeholder__alloc(void) { ++ wuffs_vp8__placeholder* x = ++ (wuffs_vp8__placeholder*)(calloc(1, sizeof(wuffs_vp8__placeholder))); ++ if (!x) { ++ return NULL; + } +- +- return status; ++ if (wuffs_vp8__placeholder__initialize( ++ x, sizeof(wuffs_vp8__placeholder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; + } + +-// -------- func png.decoder.decode_srgb +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_srgb( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++size_t ++sizeof__wuffs_vp8__placeholder(void) { ++ return sizeof(wuffs_vp8__placeholder); ++} + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++// ---------------- Function Implementations + +- uint32_t coro_susp_point = self->private_impl.p_decode_srgb[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__VP8) + +- if (self->private_impl.f_chunk_length != 1u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length = 0u; +- self->private_impl.f_metadata_flavor = 5u; +- self->private_impl.f_metadata_fourcc = 1397901122u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t t_0 = *iop_a_src++; +- self->private_impl.f_metadata_x = t_0; +- } +- self->private_impl.f_metadata_y = 0u; +- self->private_impl.f_metadata_z = 0u; ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) + +- goto ok; +- ok: +- self->private_impl.p_decode_srgb[0] = 0; +- goto exit; +- } ++// ---------------- Status Codes Implementations + +- goto suspend; +- suspend: +- self->private_impl.p_decode_srgb[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++const char wuffs_wbmp__error__bad_header[] = "#wbmp: bad header"; ++const char wuffs_wbmp__error__truncated_input[] = "#wbmp: truncated input"; + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++// ---------------- Private Consts + +- return status; +-} ++// ---------------- Private Initializer Prototypes + +-// -------- func png.decoder.decode_trns ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__decode_trns( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++wuffs_wbmp__decoder__do_decode_image_config( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- uint32_t v_i = 0; +- uint32_t v_n = 0; +- uint64_t v_u = 0; ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_wbmp__decoder__do_decode_frame_config( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_wbmp__decoder__do_decode_frame( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); + +- uint32_t coro_susp_point = self->private_impl.p_decode_trns[0]; +- if (coro_susp_point) { +- v_i = self->private_data.s_decode_trns[0].v_i; +- v_n = self->private_data.s_decode_trns[0].v_n; +- } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++// ---------------- VTables + +- if (self->private_impl.f_color_type == 0u) { +- self->private_impl.choosy_filter_and_swizzle = ( +- &wuffs_png__decoder__filter_and_swizzle_tricky); +- if (self->private_impl.f_depth <= 8u) { +- self->private_impl.f_dst_pixfmt = 2164295816u; +- self->private_impl.f_src_pixfmt = 2164295816u; +- } else { +- self->private_impl.f_dst_pixfmt = 2164308923u; +- self->private_impl.f_src_pixfmt = 2164308923u; +- } +- if (self->private_impl.f_chunk_length != 2u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length = 0u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint64_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_0 = ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_decode_trns[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_trns[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 8) { +- t_0 = ((uint64_t)(*scratch >> 48)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } +- } +- v_u = t_0; +- } +- if (self->private_impl.f_depth <= 1u) { +- self->private_impl.f_remap_transparency = (((v_u & 1u) * 16777215u) | 4278190080u); +- } else if (self->private_impl.f_depth <= 2u) { +- self->private_impl.f_remap_transparency = (((v_u & 3u) * 5592405u) | 4278190080u); +- } else if (self->private_impl.f_depth <= 4u) { +- self->private_impl.f_remap_transparency = (((v_u & 15u) * 1118481u) | 4278190080u); +- } else if (self->private_impl.f_depth <= 8u) { +- self->private_impl.f_remap_transparency = (((v_u & 255u) * 65793u) | 4278190080u); +- } else { +- self->private_impl.f_remap_transparency = ((v_u * 4295032833u) | 18446462598732840960u); +- } +- } else if (self->private_impl.f_color_type == 2u) { +- self->private_impl.choosy_filter_and_swizzle = ( +- &wuffs_png__decoder__filter_and_swizzle_tricky); +- if (self->private_impl.f_depth <= 8u) { +- self->private_impl.f_dst_pixfmt = 2164295816u; +- self->private_impl.f_src_pixfmt = 2164295816u; +- } else { +- self->private_impl.f_dst_pixfmt = 2164308923u; +- self->private_impl.f_src_pixfmt = 2164308923u; +- } +- if (self->private_impl.f_chunk_length != 6u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length = 0u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint64_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 6)) { +- t_1 = ((uint64_t)(wuffs_base__peek_u48be__no_bounds_check(iop_a_src))); +- iop_a_src += 6; +- } else { +- self->private_data.s_decode_trns[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_trns[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); +- if (num_bits_1 == 40) { +- t_1 = ((uint64_t)(*scratch >> 16)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)); +- } +- } +- v_u = t_1; +- } +- if (self->private_impl.f_depth <= 8u) { +- self->private_impl.f_remap_transparency = ((255u & (v_u >> 0u)) | +- (65280u & (v_u >> 8u)) | +- (16711680u & (v_u >> 16u)) | +- 4278190080u); +- } else { +- self->private_impl.f_remap_transparency = (v_u | 18446462598732840960u); +- } +- } else if (self->private_impl.f_color_type == 3u) { +- self->private_impl.f_dst_pixfmt = 2164523016u; +- self->private_impl.f_src_pixfmt = 2164523016u; +- if (self->private_impl.f_chunk_length > 256u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- v_n = ((uint32_t)(self->private_impl.f_chunk_length)); +- self->private_impl.f_chunk_length = 0u; +- while (v_i < v_n) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_2 = *iop_a_src++; +- self->private_data.f_src_palette[((4u * v_i) + 3u)] = t_2; +- } +- v_i += 1u; +- } ++const wuffs_base__image_decoder__func_ptrs ++wuffs_wbmp__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_wbmp__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_wbmp__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_wbmp__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_wbmp__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_wbmp__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_wbmp__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_wbmp__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_wbmp__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_wbmp__decoder__initialize( ++ wuffs_wbmp__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; + } else { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); + } ++ } + +- goto ok; +- ok: +- self->private_impl.p_decode_trns[0] = 0; +- goto exit; ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_wbmp__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_wbmp__decoder* ++wuffs_wbmp__decoder__alloc(void) { ++ wuffs_wbmp__decoder* x = ++ (wuffs_wbmp__decoder*)(calloc(1, sizeof(wuffs_wbmp__decoder))); ++ if (!x) { ++ return NULL; ++ } ++ if (wuffs_wbmp__decoder__initialize( ++ x, sizeof(wuffs_wbmp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; + } ++ return x; ++} + +- goto suspend; +- suspend: +- self->private_impl.p_decode_trns[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_decode_trns[0].v_i = v_i; +- self->private_data.s_decode_trns[0].v_n = v_n; ++size_t ++sizeof__wuffs_wbmp__decoder(void) { ++ return sizeof(wuffs_wbmp__decoder); ++} + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++// ---------------- Function Implementations ++ ++// -------- func wbmp.decoder.get_quirk ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_wbmp__decoder__get_quirk( ++ const wuffs_wbmp__decoder* self, ++ uint32_t a_key) { ++ if (!self) { ++ return 0; ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; + } + +- return status; ++ return 0u; + } + +-// -------- func png.decoder.decode_frame_config ++// -------- func wbmp.decoder.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_png__decoder__decode_frame_config( +- wuffs_png__decoder* self, +- wuffs_base__frame_config* a_dst, ++wuffs_wbmp__decoder__set_quirk( ++ wuffs_wbmp__decoder* self, ++ uint32_t a_key, ++ uint64_t a_value) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++} ++ ++// -------- func wbmp.decoder.decode_image_config ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__decode_image_config( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); +@@ -56757,7 +70789,7 @@ wuffs_png__decoder__decode_frame_config( + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 2)) { ++ (self->private_impl.active_coroutine != 1)) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } +@@ -56766,17 +70798,17 @@ wuffs_png__decoder__decode_frame_config( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_png__decoder__do_decode_frame_config(self, a_dst, a_src); ++ wuffs_base__status t_0 = wuffs_wbmp__decoder__do_decode_image_config(self, a_dst, a_src); + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_png__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_wbmp__error__truncated_input); + goto exit; + } + status = v_status; +@@ -56784,14 +70816,14 @@ wuffs_png__decoder__decode_frame_config( + } + + ok: +- self->private_impl.p_decode_frame_config[0] = 0; ++ self->private_impl.p_decode_image_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; + + goto exit; + exit: +@@ -56801,17 +70833,19 @@ wuffs_png__decoder__decode_frame_config( + return status; + } + +-// -------- func png.decoder.do_decode_frame_config ++// -------- func wbmp.decoder.do_decode_image_config + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__do_decode_frame_config( +- wuffs_png__decoder* self, +- wuffs_base__frame_config* a_dst, ++wuffs_wbmp__decoder__do_decode_image_config( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_checksum_have = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_i = 0; ++ uint32_t v_p = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -56824,392 +70858,88 @@ wuffs_png__decoder__do_decode_frame_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config; ++ if (coro_susp_point) { ++ v_i = self->private_data.s_do_decode_image_config.v_i; ++ v_p = self->private_data.s_do_decode_image_config.v_p; ++ } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((self->private_impl.f_call_sequence & 16u) != 0u) { ++ if (self->private_impl.f_call_sequence != 0u) { + status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); + goto exit; +- } else if (self->private_impl.f_call_sequence == 32u) { +- } else if (self->private_impl.f_call_sequence < 32u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_png__decoder__do_decode_image_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } else if (self->private_impl.f_call_sequence == 40u) { +- if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_restart); +- goto exit; +- } +- } else if (self->private_impl.f_call_sequence == 64u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- status = wuffs_png__decoder__skip_frame(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- if (self->private_impl.f_metadata_fourcc != 0u) { +- self->private_impl.f_call_sequence = 48u; +- status = wuffs_base__make_status(wuffs_base__note__metadata_reported); +- goto ok; + } +- if (self->private_impl.f_num_decoded_frame_configs_value == 0u) { +- self->private_impl.f_frame_rect_x0 = self->private_impl.f_first_rect_x0; +- self->private_impl.f_frame_rect_y0 = self->private_impl.f_first_rect_y0; +- self->private_impl.f_frame_rect_x1 = self->private_impl.f_first_rect_x1; +- self->private_impl.f_frame_rect_y1 = self->private_impl.f_first_rect_y1; +- self->private_impl.f_frame_config_io_position = self->private_impl.f_first_config_io_position; +- self->private_impl.f_frame_duration = self->private_impl.f_first_duration; +- self->private_impl.f_frame_disposal = self->private_impl.f_first_disposal; +- self->private_impl.f_frame_overwrite_instead_of_blend = self->private_impl.f_first_overwrite_instead_of_blend; +- } else { +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_frame_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_frame_config[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } +- } +- self->private_impl.f_chunk_length = t_0; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_frame_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_frame_config[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; +- if (num_bits_1 == 24) { +- t_1 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)) << 56; +- } +- } +- self->private_impl.f_chunk_type = t_1; +- } +- if (self->private_impl.f_chunk_type == 1145980233u) { +- if (self->private_impl.f_chunk_length != 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- uint32_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_frame_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_frame_config[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; +- if (num_bits_2 == 24) { +- t_2 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)) << 56; +- } +- } +- v_checksum_have = t_2; +- } +- if ( ! self->private_impl.f_ignore_checksum && (v_checksum_have != 2187346606u)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_checksum); +- goto exit; +- } +- self->private_impl.f_call_sequence = 96u; +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } else if (self->private_impl.f_chunk_type == 1413571686u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } else if (self->private_impl.f_chunk_type == 1280598886u) { +- self->private_impl.f_frame_config_io_position = ((uint64_t)(wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) - 8u)); +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- status = wuffs_png__decoder__decode_fctl(self, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- self->private_data.s_do_decode_frame_config[0].scratch = 4u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- if (self->private_data.s_do_decode_frame_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_frame_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_frame_config[0].scratch; +- break; +- } +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); +- status = wuffs_png__decoder__decode_other_chunk(self, a_src, true); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- if (self->private_impl.f_metadata_fourcc != 0u) { +- self->private_impl.f_call_sequence = 48u; +- status = wuffs_base__make_status(wuffs_base__note__metadata_reported); +- goto ok; +- } +- self->private_data.s_do_decode_frame_config[0].scratch = 4u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); +- if (self->private_data.s_do_decode_frame_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_frame_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; ++ v_i = 0u; ++ while (v_i < 2u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- iop_a_src += self->private_data.s_do_decode_frame_config[0].scratch; +- self->private_impl.f_chunk_length = 0u; ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; + } +- } +- if (a_dst != NULL) { +- wuffs_base__frame_config__set( +- a_dst, +- wuffs_base__utility__make_rect_ie_u32( +- self->private_impl.f_frame_rect_x0, +- self->private_impl.f_frame_rect_y0, +- self->private_impl.f_frame_rect_x1, +- self->private_impl.f_frame_rect_y1), +- ((wuffs_base__flicks)(self->private_impl.f_frame_duration)), +- ((uint64_t)(self->private_impl.f_num_decoded_frame_configs_value)), +- self->private_impl.f_frame_config_io_position, +- self->private_impl.f_frame_disposal, +- ((self->private_impl.f_color_type <= 3u) && ! self->private_impl.f_seen_trns), +- self->private_impl.f_frame_overwrite_instead_of_blend, +- 0u); +- } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frame_configs_value, 1u); +- self->private_impl.f_call_sequence = 64u; +- +- ok: +- self->private_impl.p_do_decode_frame_config[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- +- return status; +-} +- +-// -------- func png.decoder.skip_frame +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__skip_frame( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- uint32_t v_seq_num = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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_skip_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- self->private_impl.f_chunk_type_array[0u] = 0u; +- self->private_impl.f_chunk_type_array[1u] = 0u; +- self->private_impl.f_chunk_type_array[2u] = 0u; +- self->private_impl.f_chunk_type_array[3u] = 0u; +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 8u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- continue; ++ if (v_c8 != 0u) { ++ status = wuffs_base__make_status(wuffs_wbmp__error__bad_header); ++ goto exit; + } +- self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32u))); +- if (self->private_impl.f_chunk_type == 1413563465u) { +- if (self->private_impl.f_chunk_type_array[0u] == 102u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_type_array[0u] = 73u; +- self->private_impl.f_chunk_type_array[1u] = 68u; +- self->private_impl.f_chunk_type_array[2u] = 65u; +- self->private_impl.f_chunk_type_array[3u] = 84u; +- } else if (self->private_impl.f_chunk_type == 1413571686u) { +- if (self->private_impl.f_chunk_type_array[0u] == 73u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_type_array[0u] = 102u; +- self->private_impl.f_chunk_type_array[1u] = 100u; +- self->private_impl.f_chunk_type_array[2u] = 65u; +- self->private_impl.f_chunk_type_array[3u] = 84u; +- if (self->private_impl.f_chunk_length < 4u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length -= 4u; +- iop_a_src += 8u; ++ v_i += 1u; ++ } ++ v_i = 0u; ++ while (v_i < 2u) { ++ v_p = 0u; ++ while (true) { + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_skip_frame[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_skip_frame[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- v_seq_num = t_0; ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; + } +- if (v_seq_num != self->private_impl.f_next_animation_seq_num) { +- status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number); +- goto exit; +- } else if (self->private_impl.f_next_animation_seq_num >= 4294967295u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); ++ v_p |= ((uint32_t)(((uint8_t)(v_c8 & 127u)))); ++ if (((uint8_t)(v_c8 >> 7u)) == 0u) { ++ break; ++ } else if (v_p > 131071u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); + goto exit; + } +- self->private_impl.f_next_animation_seq_num += 1u; +- self->private_data.s_skip_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 4u); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_skip_frame[0].scratch; +- self->private_impl.f_chunk_length = 0u; +- continue; +- } else if (self->private_impl.f_chunk_type_array[0u] != 0u) { +- break; +- } else if (self->private_impl.f_chunk_type == 1280598886u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; ++ v_p <<= 7u; + } +- self->private_data.s_skip_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 12u); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ if (v_i == 0u) { ++ self->private_impl.f_width = v_p; ++ } else { ++ self->private_impl.f_height = v_p; + } +- iop_a_src += self->private_data.s_skip_frame[0].scratch; +- self->private_impl.f_chunk_length = 0u; ++ v_i += 1u; ++ } ++ self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ if (a_dst != NULL) { ++ wuffs_base__image_config__set( ++ a_dst, ++ 2198077448u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ self->private_impl.f_frame_config_io_position, ++ true); + } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); + self->private_impl.f_call_sequence = 32u; + ++ goto ok; + ok: +- self->private_impl.p_skip_frame[0] = 0; ++ self->private_impl.p_do_decode_image_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_skip_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_image_config.v_i = v_i; ++ self->private_data.s_do_decode_image_config.v_p = v_p; + + goto exit; + exit: +@@ -57220,17 +70950,14 @@ wuffs_png__decoder__skip_frame( + return status; + } + +-// -------- func png.decoder.decode_frame ++// -------- func wbmp.decoder.decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_png__decoder__decode_frame( +- wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { ++wuffs_wbmp__decoder__decode_frame_config( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +@@ -57240,12 +70967,12 @@ wuffs_png__decoder__decode_frame( + ? wuffs_base__error__disabled_by_previous_error + : wuffs_base__error__initialize_not_called); + } +- if (!a_dst || !a_src) { ++ if (!a_src) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 3)) { ++ (self->private_impl.active_coroutine != 2)) { + self->private_impl.magic = WUFFS_BASE__DISABLED; + return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } +@@ -57254,22 +70981,17 @@ wuffs_png__decoder__decode_frame( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_frame[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_png__decoder__do_decode_frame(self, +- a_dst, +- a_src, +- a_blend, +- a_workbuf, +- a_opts); ++ wuffs_base__status t_0 = wuffs_wbmp__decoder__do_decode_frame_config(self, a_dst, a_src); + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_png__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_wbmp__error__truncated_input); + goto exit; + } + status = v_status; +@@ -57277,14 +70999,14 @@ wuffs_png__decoder__decode_frame( + } + + ok: +- self->private_impl.p_decode_frame[0] = 0; ++ self->private_impl.p_decode_frame_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; + + goto exit; + exit: +@@ -57294,24 +71016,16 @@ wuffs_png__decoder__decode_frame( + return status; + } + +-// -------- func png.decoder.do_decode_frame ++// -------- func wbmp.decoder.do_decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__do_decode_frame( +- wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { ++wuffs_wbmp__decoder__do_decode_frame_config( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_seq_num = 0; +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- uint32_t v_pass_width = 0; +- uint32_t v_pass_height = 0; +- + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -57323,210 +71037,62 @@ wuffs_png__decoder__do_decode_frame( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame[0]; ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((self->private_impl.f_call_sequence & 16u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } else if (self->private_impl.f_call_sequence >= 96u) { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } else if (self->private_impl.f_call_sequence != 64u) { ++ if (self->private_impl.f_call_sequence == 32u) { ++ } else if (self->private_impl.f_call_sequence < 32u) { + if (a_src) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_png__decoder__do_decode_frame_config(self, NULL, a_src); ++ status = wuffs_wbmp__decoder__do_decode_image_config(self, NULL, a_src); + if (a_src) { + iop_a_src = a_src->data.ptr + a_src->meta.ri; + } + if (status.repr) { + goto suspend; + } +- } +- while (true) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 8u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- continue; +- } +- self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32u))); +- if (self->private_impl.f_chunk_type == 1413563465u) { +- self->private_impl.f_chunk_type_array[0u] = 73u; +- self->private_impl.f_chunk_type_array[1u] = 68u; +- self->private_impl.f_chunk_type_array[2u] = 65u; +- self->private_impl.f_chunk_type_array[3u] = 84u; +- iop_a_src += 8u; +- if ( ! self->private_impl.f_ignore_checksum) { +- wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, +- sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); +- wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4)); +- } +- break; +- } else if (self->private_impl.f_chunk_type == 1413571686u) { +- self->private_impl.f_chunk_type_array[0u] = 102u; +- self->private_impl.f_chunk_type_array[1u] = 100u; +- self->private_impl.f_chunk_type_array[2u] = 65u; +- self->private_impl.f_chunk_type_array[3u] = 84u; +- if (self->private_impl.f_chunk_length < 4u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length -= 4u; +- iop_a_src += 8u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_0; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_frame[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_frame[0].scratch; +- uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0); +- if (num_bits_0 == 24) { +- t_0 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_0 += 8u; +- *scratch |= ((uint64_t)(num_bits_0)); +- } +- } +- v_seq_num = t_0; +- } +- if (v_seq_num != self->private_impl.f_next_animation_seq_num) { +- status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number); +- goto exit; +- } else if (self->private_impl.f_next_animation_seq_num >= 4294967295u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); +- goto exit; +- } +- self->private_impl.f_next_animation_seq_num += 1u; +- break; +- } else if (self->private_impl.f_chunk_type == 1280598886u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_data.s_do_decode_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 12u); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- if (self->private_data.s_do_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_frame[0].scratch; +- self->private_impl.f_chunk_length = 0u; +- } +- if (self->private_impl.f_zlib_is_dirty) { +- wuffs_base__ignore_status(wuffs_zlib__decoder__initialize(&self->private_data.f_zlib, +- sizeof (wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); +- if (self->private_impl.f_ignore_checksum) { +- wuffs_zlib__decoder__set_quirk(&self->private_data.f_zlib, 1u, 1u); +- } +- } +- self->private_impl.f_zlib_is_dirty = true; +- v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, +- wuffs_base__pixel_buffer__pixel_format(a_dst), +- wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), +- wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt), +- wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024), +- a_blend); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ } else if (self->private_impl.f_call_sequence == 40u) { ++ if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_restart); + goto exit; + } ++ } else if (self->private_impl.f_call_sequence == 64u) { ++ self->private_impl.f_call_sequence = 96u; ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); + goto ok; + } +- self->private_impl.f_workbuf_hist_pos_base = 0u; +- while (true) { +- if (self->private_impl.f_chunk_type_array[0u] == 73u) { +- v_pass_width = (16777215u & ((((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][1u])) + self->private_impl.f_width) >> WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0u])); +- v_pass_height = (16777215u & ((((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][4u])) + self->private_impl.f_height) >> WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][3u])); +- } else { +- v_pass_width = (16777215u & ((uint32_t)(self->private_impl.f_frame_rect_x1 - self->private_impl.f_frame_rect_x0))); +- v_pass_height = (16777215u & ((uint32_t)(self->private_impl.f_frame_rect_y1 - self->private_impl.f_frame_rect_y0))); +- } +- if ((v_pass_width > 0u) && (v_pass_height > 0u)) { +- self->private_impl.f_pass_bytes_per_row = wuffs_png__decoder__calculate_bytes_per_row(self, v_pass_width); +- self->private_impl.f_pass_workbuf_length = (((uint64_t)(v_pass_height)) * (1u + self->private_impl.f_pass_bytes_per_row)); +- while (true) { +- { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- wuffs_base__status t_1 = wuffs_png__decoder__decode_pass(self, a_src, a_workbuf); +- v_status = t_1; +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } +- if (wuffs_base__status__is_ok(&v_status)) { +- break; +- } else if (wuffs_base__status__is_error(&v_status) || ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed))) { +- if (self->private_impl.f_workbuf_wi <= ((uint64_t)(a_workbuf.len))) { +- wuffs_png__decoder__filter_and_swizzle(self, a_dst, wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_workbuf_wi)); +- } +- if (v_status.repr == wuffs_base__suspension__short_read) { +- status = wuffs_base__make_status(wuffs_png__error__truncated_input); +- goto exit; +- } +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); +- } +- v_status = wuffs_png__decoder__filter_and_swizzle(self, a_dst, a_workbuf); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } +- self->private_impl.f_workbuf_hist_pos_base += self->private_impl.f_pass_workbuf_length; +- } +- if ((self->private_impl.f_interlace_pass == 0u) || (self->private_impl.f_interlace_pass >= 7u)) { +- break; +- } +-#if defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wconversion" +-#endif +- self->private_impl.f_interlace_pass += 1u; +-#if defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif ++ if (a_dst != NULL) { ++ wuffs_base__frame_config__set( ++ a_dst, ++ wuffs_base__utility__make_rect_ie_u32( ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height), ++ ((wuffs_base__flicks)(0u)), ++ 0u, ++ self->private_impl.f_frame_config_io_position, ++ 0u, ++ true, ++ false, ++ 4278190080u); + } +- wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1u); +- self->private_impl.f_call_sequence = 32u; ++ self->private_impl.f_call_sequence = 64u; + + ok: +- self->private_impl.p_do_decode_frame[0] = 0; ++ self->private_impl.p_do_decode_frame_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +@@ -57537,338 +71103,217 @@ wuffs_png__decoder__do_decode_frame( + return status; + } + +-// -------- func png.decoder.decode_pass ++// -------- func wbmp.decoder.decode_frame + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_png__decoder__decode_pass( +- wuffs_png__decoder* self, ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__decode_frame( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, + wuffs_base__io_buffer* a_src, +- wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 3)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_w = &u_w; +- uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint64_t v_w_mark = 0; +- uint64_t v_r_mark = 0; +- wuffs_base__status v_zlib_status = wuffs_base__make_status(NULL); +- uint32_t v_checksum_have = 0; +- uint32_t v_checksum_want = 0; +- uint32_t v_seq_num = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_pass[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- self->private_impl.f_workbuf_wi = 0u; + while (true) { +- if ((self->private_impl.f_workbuf_wi > self->private_impl.f_pass_workbuf_length) || (self->private_impl.f_pass_workbuf_length > ((uint64_t)(a_workbuf.len)))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); +- goto exit; +- } + { +- wuffs_base__io_buffer* o_0_v_w = v_w; +- uint8_t *o_0_iop_v_w = iop_v_w; +- uint8_t *o_0_io0_v_w = io0_v_w; +- uint8_t *o_0_io1_v_w = io1_v_w; +- uint8_t *o_0_io2_v_w = io2_v_w; +- v_w = wuffs_base__io_writer__set( +- &u_w, +- &iop_v_w, +- &io0_v_w, +- &io1_v_w, +- &io2_v_w, +- wuffs_base__slice_u8__subslice_ij(a_workbuf, +- self->private_impl.f_workbuf_wi, +- self->private_impl.f_pass_workbuf_length), +- ((uint64_t)(self->private_impl.f_workbuf_hist_pos_base + self->private_impl.f_workbuf_wi))); +- { +- const bool o_1_closed_a_src = a_src->meta.closed; +- const uint8_t *o_1_io2_a_src = io2_a_src; +- wuffs_base__io_reader__limit(&io2_a_src, iop_a_src, +- ((uint64_t)(self->private_impl.f_chunk_length))); +- if (a_src) { +- size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); +- a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); +- a_src->meta.wi = n; +- } +- v_w_mark = ((uint64_t)(iop_v_w - io0_v_w)); +- v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); +- { +- u_w.meta.wi = ((size_t)(iop_v_w - u_w.data.ptr)); +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- wuffs_base__status t_0 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, v_w, a_src, wuffs_base__utility__empty_slice_u8()); +- v_zlib_status = t_0; +- iop_v_w = u_w.data.ptr + u_w.meta.wi; +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } +- if ( ! self->private_impl.f_ignore_checksum) { +- wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__io__since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); +- } +- wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)(wuffs_base__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_workbuf_wi, wuffs_base__io__count_since(v_w_mark, ((uint64_t)(iop_v_w - io0_v_w)))); +- io2_a_src = o_1_io2_a_src; +- if (a_src) { +- a_src->meta.closed = o_1_closed_a_src; +- a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); +- } +- } +- v_w = o_0_v_w; +- iop_v_w = o_0_iop_v_w; +- io0_v_w = o_0_io0_v_w; +- io1_v_w = o_0_io1_v_w; +- io2_v_w = o_0_io2_v_w; ++ wuffs_base__status t_0 = wuffs_wbmp__decoder__do_decode_frame(self, ++ a_dst, ++ a_src, ++ a_blend, ++ a_workbuf, ++ a_opts); ++ v_status = t_0; + } +- if (wuffs_base__status__is_ok(&v_zlib_status)) { +- if (self->private_impl.f_chunk_length > 0u) { +- status = wuffs_base__make_status(wuffs_base__error__too_much_data); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- uint32_t t_1; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_pass[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch; +- uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1); +- if (num_bits_1 == 24) { +- t_1 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_1 += 8u; +- *scratch |= ((uint64_t)(num_bits_1)); +- } +- } +- v_checksum_want = t_1; +- } +- if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_chunk_type_array[0u] == 73u)) { +- v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__utility__empty_slice_u8()); +- if (v_checksum_have != v_checksum_want) { +- status = wuffs_base__make_status(wuffs_png__error__bad_checksum); +- goto exit; +- } +- } +- break; +- } else if (v_zlib_status.repr == wuffs_base__suspension__short_write) { +- if ((1u <= self->private_impl.f_interlace_pass) && (self->private_impl.f_interlace_pass <= 6u)) { +- break; +- } +- status = wuffs_base__make_status(wuffs_base__error__too_much_data); ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_wbmp__error__truncated_input); + goto exit; +- } else if (v_zlib_status.repr != wuffs_base__suspension__short_read) { +- status = v_zlib_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } else if (self->private_impl.f_chunk_length == 0u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- uint32_t t_2; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_pass[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch; +- uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2); +- if (num_bits_2 == 24) { +- t_2 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_2 += 8u; +- *scratch |= ((uint64_t)(num_bits_2)); +- } +- } +- v_checksum_want = t_2; +- } +- if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_chunk_type_array[0u] == 73u)) { +- v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__utility__empty_slice_u8()); +- if (v_checksum_have != v_checksum_want) { +- status = wuffs_base__make_status(wuffs_png__error__bad_checksum); +- goto exit; +- } +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); +- uint32_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_pass[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3); +- if (num_bits_3 == 24) { +- t_3 = ((uint32_t)(*scratch >> 32)); +- break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func wbmp.decoder.do_decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_wbmp__decoder__do_decode_frame( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint64_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_x_in_bytes = 0; ++ uint32_t v_dst_x = 0; ++ uint32_t v_dst_y = 0; ++ wuffs_base__table_u8 v_tab = {0}; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint8_t v_src[1] = {0}; ++ uint8_t v_c8 = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame; ++ if (coro_susp_point) { ++ v_dst_bytes_per_pixel = self->private_data.s_do_decode_frame.v_dst_bytes_per_pixel; ++ v_dst_x = self->private_data.s_do_decode_frame.v_dst_x; ++ v_dst_y = self->private_data.s_do_decode_frame.v_dst_y; ++ memcpy(v_src, self->private_data.s_do_decode_frame.v_src, sizeof(v_src)); ++ v_c8 = self->private_data.s_do_decode_frame.v_c8; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_wbmp__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette(a_dst), ++ wuffs_base__utility__make_pixel_format(536870920u), ++ wuffs_base__utility__empty_slice_u8(), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ status = wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ goto exit; ++ } ++ v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8u))); ++ if (self->private_impl.f_width > 0u) { ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ while (v_dst_y < self->private_impl.f_height) { ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, v_dst_y); ++ v_dst_x = 0u; ++ while (v_dst_x < self->private_impl.f_width) { ++ if ((v_dst_x & 7u) == 0u) { ++ while (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, v_dst_y); ++ v_dst_x_in_bytes = (((uint64_t)(v_dst_x)) * v_dst_bytes_per_pixel); ++ if (v_dst_x_in_bytes <= ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_x_in_bytes); + } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)); + } ++ v_c8 = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); ++ iop_a_src += 1u; + } +- self->private_impl.f_chunk_length = t_3; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); +- uint32_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; ++ if (((uint8_t)(v_c8 & 128u)) == 0u) { ++ v_src[0u] = 0u; + } else { +- self->private_data.s_decode_pass[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; +- if (num_bits_4 == 24) { +- t_4 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)) << 56; +- } +- } +- self->private_impl.f_chunk_type = t_4; +- } +- if (self->private_impl.f_chunk_type_array[0u] == 73u) { +- if (self->private_impl.f_chunk_type != 1413563465u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- if ( ! self->private_impl.f_ignore_checksum) { +- wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, +- sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); +- wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4)); +- } +- } else { +- if ((self->private_impl.f_chunk_type != 1413571686u) || (self->private_impl.f_chunk_length < 4u)) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length -= 4u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- uint32_t t_5; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_5 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_decode_pass[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch; +- uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFFu)); +- *scratch >>= 8; +- *scratch <<= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5); +- if (num_bits_5 == 24) { +- t_5 = ((uint32_t)(*scratch >> 32)); +- break; +- } +- num_bits_5 += 8u; +- *scratch |= ((uint64_t)(num_bits_5)); +- } +- } +- v_seq_num = t_5; ++ v_src[0u] = 255u; + } +- if (v_seq_num != self->private_impl.f_next_animation_seq_num) { +- status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number); +- goto exit; +- } else if (self->private_impl.f_next_animation_seq_num >= 4294967295u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file); +- goto exit; ++ v_c8 = ((uint8_t)((((uint32_t)(v_c8)) << 1u))); ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, wuffs_base__utility__empty_slice_u8(), wuffs_base__make_slice_u8(v_src, 1)); ++ if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel); + } +- self->private_impl.f_next_animation_seq_num += 1u; ++ v_dst_x += 1u; + } +- continue; +- } else if (((uint64_t)(io2_a_src - iop_a_src)) > 0u) { +- status = wuffs_base__make_status(wuffs_png__error__internal_error_zlib_decoder_did_not_exhaust_its_input); +- goto exit; +- } +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); +- } +- if (self->private_impl.f_workbuf_wi != self->private_impl.f_pass_workbuf_length) { +- status = wuffs_base__make_status(wuffs_base__error__not_enough_data); +- goto exit; +- } else if (0u < ((uint64_t)(a_workbuf.len))) { +- if (a_workbuf.ptr[0u] == 4u) { +- a_workbuf.ptr[0u] = 1u; ++ v_dst_y += 1u; + } + } ++ self->private_impl.f_call_sequence = 96u; + + ok: +- self->private_impl.p_decode_pass[0] = 0; ++ self->private_impl.p_do_decode_frame = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_pass[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_frame.v_dst_bytes_per_pixel = v_dst_bytes_per_pixel; ++ self->private_data.s_do_decode_frame.v_dst_x = v_dst_x; ++ self->private_data.s_do_decode_frame.v_dst_y = v_dst_y; ++ memcpy(self->private_data.s_do_decode_frame.v_src, v_src, sizeof(v_src)); ++ self->private_data.s_do_decode_frame.v_c8 = v_c8; + + goto exit; + exit: +@@ -57879,12 +71324,12 @@ wuffs_png__decoder__decode_pass( + return status; + } + +-// -------- func png.decoder.frame_dirty_rect ++// -------- func wbmp.decoder.frame_dirty_rect + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_png__decoder__frame_dirty_rect( +- const wuffs_png__decoder* self) { ++wuffs_wbmp__decoder__frame_dirty_rect( ++ const wuffs_wbmp__decoder* self) { + if (!self) { + return wuffs_base__utility__empty_rect_ie_u32(); + } +@@ -57894,18 +71339,18 @@ wuffs_png__decoder__frame_dirty_rect( + } + + return wuffs_base__utility__make_rect_ie_u32( +- self->private_impl.f_frame_rect_x0, +- self->private_impl.f_frame_rect_y0, +- self->private_impl.f_frame_rect_x1, +- self->private_impl.f_frame_rect_y1); ++ 0u, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height); + } + +-// -------- func png.decoder.num_animation_loops ++// -------- func wbmp.decoder.num_animation_loops + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_png__decoder__num_animation_loops( +- const wuffs_png__decoder* self) { ++wuffs_wbmp__decoder__num_animation_loops( ++ const wuffs_wbmp__decoder* self) { + if (!self) { + return 0; + } +@@ -57914,15 +71359,15 @@ wuffs_png__decoder__num_animation_loops( + return 0; + } + +- return self->private_impl.f_num_animation_loops_value; ++ return 0u; + } + +-// -------- func png.decoder.num_decoded_frame_configs ++// -------- func wbmp.decoder.num_decoded_frame_configs + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_png__decoder__num_decoded_frame_configs( +- const wuffs_png__decoder* self) { ++wuffs_wbmp__decoder__num_decoded_frame_configs( ++ const wuffs_wbmp__decoder* self) { + if (!self) { + return 0; + } +@@ -57931,15 +71376,18 @@ wuffs_png__decoder__num_decoded_frame_configs( + return 0; + } + +- return ((uint64_t)(self->private_impl.f_num_decoded_frame_configs_value)); ++ if (self->private_impl.f_call_sequence > 32u) { ++ return 1u; ++ } ++ return 0u; + } + +-// -------- func png.decoder.num_decoded_frames ++// -------- func wbmp.decoder.num_decoded_frames + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_png__decoder__num_decoded_frames( +- const wuffs_png__decoder* self) { ++wuffs_wbmp__decoder__num_decoded_frames( ++ const wuffs_wbmp__decoder* self) { + if (!self) { + return 0; + } +@@ -57948,15 +71396,18 @@ wuffs_png__decoder__num_decoded_frames( + return 0; + } + +- return ((uint64_t)(self->private_impl.f_num_decoded_frames_value)); ++ if (self->private_impl.f_call_sequence > 64u) { ++ return 1u; ++ } ++ return 0u; + } + +-// -------- func png.decoder.restart_frame ++// -------- func wbmp.decoder.restart_frame + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_png__decoder__restart_frame( +- wuffs_png__decoder* self, ++wuffs_wbmp__decoder__restart_frame( ++ wuffs_wbmp__decoder* self, + uint64_t a_index, + uint64_t a_io_position) { + if (!self) { +@@ -57971,154 +71422,514 @@ wuffs_png__decoder__restart_frame( + + if (self->private_impl.f_call_sequence < 32u) { + return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- } else if ((a_index >= ((uint64_t)(self->private_impl.f_num_animation_frames_value))) || ((a_index == 0u) && (a_io_position != self->private_impl.f_first_config_io_position))) { ++ } ++ if (a_index != 0u) { + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + self->private_impl.f_call_sequence = 40u; +- if (self->private_impl.f_interlace_pass >= 1u) { +- self->private_impl.f_interlace_pass = 1u; +- } + self->private_impl.f_frame_config_io_position = a_io_position; +- self->private_impl.f_num_decoded_frame_configs_value = ((uint32_t)(a_index)); +- self->private_impl.f_num_decoded_frames_value = self->private_impl.f_num_decoded_frame_configs_value; + return wuffs_base__make_status(NULL); + } + +-// -------- func png.decoder.set_report_metadata ++// -------- func wbmp.decoder.set_report_metadata + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_png__decoder__set_report_metadata( +- wuffs_png__decoder* self, ++wuffs_wbmp__decoder__set_report_metadata( ++ wuffs_wbmp__decoder* self, + uint32_t a_fourcc, + bool a_report) { ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func wbmp.decoder.tell_me_more ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_wbmp__decoder__tell_me_more( ++ wuffs_wbmp__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__more_information* a_minfo, ++ wuffs_base__io_buffer* a_src) { + if (!self) { +- return wuffs_base__make_empty_struct(); ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 4)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); + } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- if (a_fourcc == 1128813133u) { +- self->private_impl.f_report_metadata_chrm = a_report; +- } else if (a_fourcc == 1163413830u) { +- self->private_impl.f_report_metadata_exif = a_report; +- } else if (a_fourcc == 1195461953u) { +- self->private_impl.f_report_metadata_gama = a_report; +- } else if (a_fourcc == 1229144912u) { +- self->private_impl.f_report_metadata_iccp = a_report; +- } else if (a_fourcc == 1263947808u) { +- self->private_impl.f_report_metadata_kvp = a_report; +- } else if (a_fourcc == 1397901122u) { +- self->private_impl.f_report_metadata_srgb = a_report; ++ status = wuffs_base__make_status(wuffs_base__error__no_more_information); ++ goto exit; ++ ++ goto ok; ++ ok: ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func wbmp.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_wbmp__decoder__workbuf_len( ++ const wuffs_wbmp__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++} ++ ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WEBP) ++ ++// ---------------- Status Codes Implementations ++ ++const char wuffs_webp__error__bad_huffman_code_over_subscribed[] = "#webp: bad Huffman code (over-subscribed)"; ++const char wuffs_webp__error__bad_huffman_code_under_subscribed[] = "#webp: bad Huffman code (under-subscribed)"; ++const char wuffs_webp__error__bad_huffman_code[] = "#webp: bad Huffman code"; ++const char wuffs_webp__error__bad_back_reference[] = "#webp: bad back-reference"; ++const char wuffs_webp__error__bad_color_cache[] = "#webp: bad color cache"; ++const char wuffs_webp__error__bad_header[] = "#webp: bad header"; ++const char wuffs_webp__error__bad_transform[] = "#webp: bad transform"; ++const char wuffs_webp__error__short_chunk[] = "#webp: short chunk"; ++const char wuffs_webp__error__truncated_input[] = "#webp: truncated input"; ++const char wuffs_webp__error__unsupported_number_of_huffman_groups[] = "#webp: unsupported number of Huffman groups"; ++const char wuffs_webp__error__unsupported_transform_after_color_indexing_transform[] = "#webp: unsupported transform after color indexing transform"; ++const char wuffs_webp__error__unsupported_webp_file[] = "#webp: unsupported WebP file"; ++const char wuffs_webp__error__internal_error_inconsistent_huffman_code[] = "#webp: internal error: inconsistent Huffman code"; ++const char wuffs_webp__error__internal_error_inconsistent_dst_buffer[] = "#webp: internal error: inconsistent dst buffer"; ++const char wuffs_webp__error__internal_error_inconsistent_n_bits[] = "#webp: internal error: inconsistent n_bits"; ++ ++// ---------------- Private Consts ++ ++static const uint8_t ++WUFFS_WEBP__CODE_LENGTH_CODE_ORDER[19] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 17u, 18u, 0u, 1u, 2u, 3u, 4u, 5u, ++ 16u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, ++ 13u, 14u, 15u, ++}; ++ ++static const uint8_t ++WUFFS_WEBP__REPEAT_N_BITS[4] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 2u, 3u, 7u, 0u, ++}; ++ ++static const uint8_t ++WUFFS_WEBP__REPEAT_COUNTS[4] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 3u, 3u, 11u, 0u, ++}; ++ ++static const uint16_t ++WUFFS_WEBP__HUFFMAN_TABLE_BASE_OFFSETS[5] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1612u, 0u, 511u, 1022u, 1533u, ++}; ++ ++static const uint8_t ++WUFFS_WEBP__DISTANCE_MAP[120] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 24u, 7u, 23u, 25u, 40u, 6u, 39u, 41u, ++ 22u, 26u, 38u, 42u, 56u, 5u, 55u, 57u, ++ 21u, 27u, 54u, 58u, 37u, 43u, 72u, 4u, ++ 71u, 73u, 20u, 28u, 53u, 59u, 70u, 74u, ++ 36u, 44u, 88u, 69u, 75u, 52u, 60u, 3u, ++ 87u, 89u, 19u, 29u, 86u, 90u, 35u, 45u, ++ 68u, 76u, 85u, 91u, 51u, 61u, 104u, 2u, ++ 103u, 105u, 18u, 30u, 102u, 106u, 34u, 46u, ++ 84u, 92u, 67u, 77u, 101u, 107u, 50u, 62u, ++ 120u, 1u, 119u, 121u, 83u, 93u, 17u, 31u, ++ 100u, 108u, 66u, 78u, 118u, 122u, 33u, 47u, ++ 117u, 123u, 49u, 63u, 99u, 109u, 82u, 94u, ++ 0u, 116u, 124u, 65u, 79u, 16u, 32u, 98u, ++ 110u, 48u, 115u, 125u, 81u, 95u, 64u, 114u, ++ 126u, 97u, 111u, 80u, 113u, 127u, 96u, 112u, ++}; ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_huffman_groups( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_n_huffman_groups); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_huffman_tree( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_hg, ++ uint32_t a_ht); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_huffman_tree_simple( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_hg, ++ uint32_t a_ht); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_code_length_code_lengths( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__build_code_lengths_huffman_nodes( ++ wuffs_webp__decoder* self); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__build_huffman_nodes( ++ wuffs_webp__decoder* self, ++ uint32_t a_hg, ++ uint32_t a_ht); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__build_code_lengths( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_pixels_slow( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_dst, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_width, ++ uint32_t a_height, ++ wuffs_base__slice_u8 a_tile_data, ++ uint32_t a_tile_size_log2); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_webp__decoder__apply_transform_predictor( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_pix, ++ wuffs_base__slice_u8 a_tile_data); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint32_t ++wuffs_webp__decoder__absolute_difference( ++ const wuffs_webp__decoder* self, ++ uint32_t a_a, ++ uint32_t a_b); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_webp__decoder__mode12( ++ const wuffs_webp__decoder* self, ++ uint8_t a_l, ++ uint8_t a_t, ++ uint8_t a_tl); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_webp__decoder__mode13( ++ const wuffs_webp__decoder* self, ++ uint8_t a_l, ++ uint8_t a_t, ++ uint8_t a_tl); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_webp__decoder__apply_transform_cross_color( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_pix, ++ wuffs_base__slice_u8 a_tile_data); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_webp__decoder__apply_transform_subtract_green( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_pix); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_webp__decoder__apply_transform_color_indexing( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_pix); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__do_decode_image_config( ++ wuffs_webp__decoder* self, ++ wuffs_base__image_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__do_decode_image_config_limited( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__do_decode_image_config_limited_vp8l( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__do_decode_frame_config( ++ wuffs_webp__decoder* self, ++ wuffs_base__frame_config* a_dst, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__do_decode_frame( ++ wuffs_webp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_transform( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_color_cache_parameters( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_hg_table( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_width, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_pixels( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_dst, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_width, ++ uint32_t a_height, ++ wuffs_base__slice_u8 a_tile_data, ++ uint32_t a_tile_size_log2); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__swizzle( ++ wuffs_webp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_src, ++ wuffs_base__pixel_blend a_blend); ++ ++// ---------------- VTables ++ ++const wuffs_base__image_decoder__func_ptrs ++wuffs_webp__decoder__func_ptrs_for__wuffs_base__image_decoder = { ++ (wuffs_base__status(*)(void*, ++ wuffs_base__pixel_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__pixel_blend, ++ wuffs_base__slice_u8, ++ wuffs_base__decode_frame_options*))(&wuffs_webp__decoder__decode_frame), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__frame_config*, ++ wuffs_base__io_buffer*))(&wuffs_webp__decoder__decode_frame_config), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__image_config*, ++ wuffs_base__io_buffer*))(&wuffs_webp__decoder__decode_image_config), ++ (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_webp__decoder__frame_dirty_rect), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_webp__decoder__get_quirk), ++ (uint32_t(*)(const void*))(&wuffs_webp__decoder__num_animation_loops), ++ (uint64_t(*)(const void*))(&wuffs_webp__decoder__num_decoded_frame_configs), ++ (uint64_t(*)(const void*))(&wuffs_webp__decoder__num_decoded_frames), ++ (wuffs_base__status(*)(void*, ++ uint64_t, ++ uint64_t))(&wuffs_webp__decoder__restart_frame), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_webp__decoder__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ uint32_t, ++ bool))(&wuffs_webp__decoder__set_report_metadata), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__more_information*, ++ wuffs_base__io_buffer*))(&wuffs_webp__decoder__tell_me_more), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_webp__decoder__workbuf_len), ++}; ++ ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_webp__decoder__initialize( ++ wuffs_webp__decoder* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ } ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ } ++ ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } ++ ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = ++ wuffs_base__image_decoder__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = ++ (const void*)(&wuffs_webp__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ return wuffs_base__make_status(NULL); ++} ++ ++wuffs_webp__decoder* ++wuffs_webp__decoder__alloc(void) { ++ wuffs_webp__decoder* x = ++ (wuffs_webp__decoder*)(calloc(1, sizeof(wuffs_webp__decoder))); ++ if (!x) { ++ return NULL; + } +- return wuffs_base__make_empty_struct(); ++ if (wuffs_webp__decoder__initialize( ++ x, sizeof(wuffs_webp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; ++ } ++ return x; + } + +-// -------- func png.decoder.tell_me_more ++size_t ++sizeof__wuffs_webp__decoder(void) { ++ return sizeof(wuffs_webp__decoder); ++} ++ ++// ---------------- Function Implementations ++ ++// -------- func webp.decoder.decode_huffman_groups + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_png__decoder__tell_me_more( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 4)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; ++static wuffs_base__status ++wuffs_webp__decoder__decode_huffman_groups( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_n_huffman_groups) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint32_t v_hg = 0; ++ uint32_t v_ht = 0; + +- uint32_t coro_susp_point = self->private_impl.p_tell_me_more[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_huffman_groups; ++ if (coro_susp_point) { ++ v_hg = self->private_data.s_decode_huffman_groups.v_hg; ++ v_ht = self->private_data.s_decode_huffman_groups.v_ht; ++ } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_png__decoder__do_tell_me_more(self, a_dst, a_minfo, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_png__error__truncated_input); +- goto exit; ++ v_hg = 0u; ++ while (v_hg < a_n_huffman_groups) { ++ v_ht = 0u; ++ while (v_ht < 5u) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_webp__decoder__decode_huffman_tree(self, a_src, v_hg, v_ht); ++ if (status.repr) { ++ goto suspend; ++ } ++ v_ht += 1u; + } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ v_hg += 1u; + } + ++ goto ok; + ok: +- self->private_impl.p_tell_me_more[0] = 0; ++ self->private_impl.p_decode_huffman_groups = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0; ++ self->private_impl.p_decode_huffman_groups = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_huffman_groups.v_hg = v_hg; ++ self->private_data.s_decode_huffman_groups.v_ht = v_ht; + + goto exit; + exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } + return status; + } + +-// -------- func png.decoder.do_tell_me_more ++// -------- func webp.decoder.decode_huffman_tree + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__do_tell_me_more( +- wuffs_png__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { ++wuffs_webp__decoder__decode_huffman_tree( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_hg, ++ uint32_t a_ht) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint8_t v_c = 0; +- uint16_t v_c2 = 0; +- wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer(); +- wuffs_base__io_buffer* v_w = &u_w; +- uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint64_t v_num_written = 0; +- uint64_t v_w_mark = 0; +- uint64_t v_r_mark = 0; +- wuffs_base__status v_zlib_status = wuffs_base__make_status(NULL); ++ uint8_t v_c8 = 0; ++ uint32_t v_use_simple = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint8_t* iop_a_dst = NULL; +- uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_dst && a_dst->data.ptr) { +- 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; +- } +- } + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; + const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -58130,462 +71941,105 @@ wuffs_png__decoder__do_tell_me_more( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_tell_me_more[0]; +- if (coro_susp_point) { +- v_zlib_status = self->private_data.s_do_tell_me_more[0].v_zlib_status; +- } ++ uint32_t coro_susp_point = self->private_impl.p_decode_huffman_tree; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((self->private_impl.f_call_sequence & 16u) == 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } +- if (self->private_impl.f_metadata_fourcc == 0u) { +- status = wuffs_base__make_status(wuffs_base__error__no_more_information); +- goto exit; ++ if (a_ht >= 4u) { ++ self->private_impl.f_ht_n_symbols = 40u; ++ } else if (a_ht > 0u) { ++ self->private_impl.f_ht_n_symbols = 256u; ++ } else if (self->private_impl.f_color_cache_bits == 0u) { ++ self->private_impl.f_ht_n_symbols = 280u; ++ } else { ++ self->private_impl.f_ht_n_symbols = (280u + (((uint32_t)(1u)) << self->private_impl.f_color_cache_bits)); + } +- do { +- if (self->private_impl.f_metadata_flavor == 3u) { +- while (true) { +- if (wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) != self->private_impl.f_metadata_y) { +- status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position); +- goto exit; +- } else if (a_minfo != NULL) { +- wuffs_base__more_information__set(a_minfo, +- self->private_impl.f_metadata_flavor, +- self->private_impl.f_metadata_fourcc, +- self->private_impl.f_metadata_x, +- self->private_impl.f_metadata_y, +- self->private_impl.f_metadata_z); +- } +- if (self->private_impl.f_metadata_y >= self->private_impl.f_metadata_z) { +- goto label__goto_done__break; +- } +- self->private_impl.f_metadata_y = self->private_impl.f_metadata_z; +- status = wuffs_base__make_status(wuffs_base__suspension__even_more_information); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; + } +- if (self->private_impl.f_metadata_is_zlib_compressed) { +- if (self->private_impl.f_zlib_is_dirty) { +- wuffs_base__ignore_status(wuffs_zlib__decoder__initialize(&self->private_data.f_zlib, +- sizeof (wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); +- if (self->private_impl.f_ignore_checksum) { +- wuffs_zlib__decoder__set_quirk(&self->private_data.f_zlib, 1u, 1u); +- } +- } +- self->private_impl.f_zlib_is_dirty = true; +- self->private_impl.f_ztxt_hist_pos = 0u; ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; ++ } ++ v_use_simple = (self->private_impl.f_bits & 1u); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ if (v_use_simple != 0u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- label__loop__continue:; +- while (true) { +- if (a_minfo != NULL) { +- wuffs_base__more_information__set(a_minfo, +- self->private_impl.f_metadata_flavor, +- self->private_impl.f_metadata_fourcc, +- self->private_impl.f_metadata_x, +- self->private_impl.f_metadata_y, +- self->private_impl.f_metadata_z); +- } +- if (self->private_impl.f_metadata_flavor != 4u) { +- break; +- } +- if (self->private_impl.f_metadata_is_zlib_compressed) { +- if (self->private_impl.f_chunk_type == 1346585449u) { +- { +- const bool o_0_closed_a_src = a_src->meta.closed; +- const uint8_t *o_0_io2_a_src = io2_a_src; +- wuffs_base__io_reader__limit(&io2_a_src, iop_a_src, +- ((uint64_t)(self->private_impl.f_chunk_length))); +- if (a_src) { +- size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); +- a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); +- a_src->meta.wi = n; +- } +- v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); +- { +- 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__status t_0 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, a_dst, a_src, wuffs_base__utility__empty_slice_u8()); +- v_zlib_status = t_0; +- 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; +- } +- } +- wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)(wuffs_base__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); +- io2_a_src = o_0_io2_a_src; +- if (a_src) { +- a_src->meta.closed = o_0_closed_a_src; +- a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); +- } +- } +- if (wuffs_base__status__is_ok(&v_zlib_status)) { +- self->private_impl.f_metadata_is_zlib_compressed = false; +- break; +- } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) { +- status = v_zlib_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } +- status = v_zlib_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- } else if (self->private_impl.f_chunk_type == 1951945833u) { +- { +- const bool o_1_closed_a_src = a_src->meta.closed; +- const uint8_t *o_1_io2_a_src = io2_a_src; +- wuffs_base__io_reader__limit(&io2_a_src, iop_a_src, +- ((uint64_t)(self->private_impl.f_chunk_length))); +- if (a_src) { +- size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); +- a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); +- a_src->meta.wi = n; +- } +- v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); +- { +- 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__status t_1 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, a_dst, a_src, wuffs_base__utility__empty_slice_u8()); +- v_zlib_status = t_1; +- 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; +- } +- } +- wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)(wuffs_base__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); +- io2_a_src = o_1_io2_a_src; +- if (a_src) { +- a_src->meta.closed = o_1_closed_a_src; +- a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); +- } +- } +- if (wuffs_base__status__is_ok(&v_zlib_status)) { +- self->private_impl.f_metadata_is_zlib_compressed = false; +- break; +- } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) { +- status = v_zlib_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } +- status = v_zlib_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- } else if (self->private_impl.f_chunk_type == 1951945850u) { +- if (self->private_impl.f_ztxt_ri == self->private_impl.f_ztxt_wi) { +- { +- wuffs_base__io_buffer* o_2_v_w = v_w; +- uint8_t *o_2_iop_v_w = iop_v_w; +- uint8_t *o_2_io0_v_w = io0_v_w; +- uint8_t *o_2_io1_v_w = io1_v_w; +- uint8_t *o_2_io2_v_w = io2_v_w; +- v_w = wuffs_base__io_writer__set( +- &u_w, +- &iop_v_w, +- &io0_v_w, +- &io1_v_w, +- &io2_v_w, +- wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024), +- self->private_impl.f_ztxt_hist_pos); +- { +- const bool o_3_closed_a_src = a_src->meta.closed; +- const uint8_t *o_3_io2_a_src = io2_a_src; +- wuffs_base__io_reader__limit(&io2_a_src, iop_a_src, +- ((uint64_t)(self->private_impl.f_chunk_length))); +- if (a_src) { +- size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); +- a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); +- a_src->meta.wi = n; +- } +- v_w_mark = ((uint64_t)(iop_v_w - io0_v_w)); +- v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); +- { +- u_w.meta.wi = ((size_t)(iop_v_w - u_w.data.ptr)); +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- wuffs_base__status t_2 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, v_w, a_src, wuffs_base__utility__empty_slice_u8()); +- v_zlib_status = t_2; +- iop_v_w = u_w.data.ptr + u_w.meta.wi; +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- } +- wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)(wuffs_base__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); +- v_num_written = wuffs_base__io__count_since(v_w_mark, ((uint64_t)(iop_v_w - io0_v_w))); +- io2_a_src = o_3_io2_a_src; +- if (a_src) { +- a_src->meta.closed = o_3_closed_a_src; +- a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); +- } +- } +- v_w = o_2_v_w; +- iop_v_w = o_2_iop_v_w; +- io0_v_w = o_2_io0_v_w; +- io1_v_w = o_2_io1_v_w; +- io2_v_w = o_2_io2_v_w; +- } +- if (v_num_written > 1024u) { +- status = wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_i_o); +- goto exit; +- } +- self->private_impl.f_ztxt_ri = 0u; +- self->private_impl.f_ztxt_wi = ((uint32_t)(v_num_written)); +- wuffs_base__u64__sat_add_indirect(&self->private_impl.f_ztxt_hist_pos, v_num_written); +- } +- while (self->private_impl.f_ztxt_ri < self->private_impl.f_ztxt_wi) { +- v_c2 = WUFFS_PNG__LATIN_1[self->private_data.f_dst_palette[self->private_impl.f_ztxt_ri]]; +- if (v_c2 == 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_text_chunk_not_latin_1); +- goto exit; +- } else if (v_c2 <= 127u) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); +- goto label__loop__continue; +- } +- self->private_impl.f_ztxt_ri += 1u; +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(v_c2))), iop_a_dst += 1); +- } else { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); +- goto label__loop__continue; +- } +- self->private_impl.f_ztxt_ri += 1u; +- (wuffs_base__poke_u16le__no_bounds_check(iop_a_dst, v_c2), iop_a_dst += 2); +- } +- } +- if (wuffs_base__status__is_ok(&v_zlib_status)) { +- self->private_impl.f_metadata_is_zlib_compressed = false; +- break; +- } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) { +- status = v_zlib_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } else if (v_zlib_status.repr != wuffs_base__suspension__short_write) { +- status = v_zlib_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); +- } +- } else { +- status = wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_chunk_type); +- goto exit; +- } +- } else if ((self->private_impl.f_chunk_type == 1951945833u) && (self->private_impl.f_metadata_fourcc == 1263947862u)) { +- while (true) { +- if (self->private_impl.f_chunk_length <= 0u) { +- goto label__loop__break; +- } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); +- goto label__loop__continue; +- } else if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); +- goto label__loop__continue; +- } +- self->private_impl.f_chunk_length -= 1u; +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_c), iop_a_dst += 1); +- } +- } else { +- while (true) { +- if (self->private_impl.f_chunk_length <= 0u) { +- if (self->private_impl.f_metadata_fourcc == 1263947851u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- goto label__loop__break; +- } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); +- goto label__loop__continue; +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- if (v_c == 0u) { +- self->private_impl.f_chunk_length -= 1u; +- iop_a_src += 1u; +- goto label__loop__break; +- } +- v_c2 = WUFFS_PNG__LATIN_1[v_c]; +- if (v_c2 == 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_text_chunk_not_latin_1); +- goto exit; +- } else if (v_c2 <= 127u) { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); +- goto label__loop__continue; +- } +- self->private_impl.f_chunk_length -= 1u; +- iop_a_src += 1u; +- (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(v_c2))), iop_a_dst += 1); +- } else { +- if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_write); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); +- goto label__loop__continue; +- } +- self->private_impl.f_chunk_length -= 1u; +- iop_a_src += 1u; +- (wuffs_base__poke_u16le__no_bounds_check(iop_a_dst, v_c2), iop_a_dst += 2); +- } +- } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ status = wuffs_webp__decoder__decode_huffman_tree_simple(self, a_src, a_hg, a_ht); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_webp__decoder__decode_code_length_code_lengths(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ v_status = wuffs_webp__decoder__build_code_lengths_huffman_nodes(self); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; + } ++ goto ok; + } +- label__loop__break:; +- if (self->private_impl.f_metadata_fourcc == 1263947851u) { +- self->private_impl.f_metadata_fourcc = 1263947862u; +- if (self->private_impl.f_chunk_type == 1951945833u) { +- if (self->private_impl.f_chunk_length <= 1u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length -= 2u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_3 = *iop_a_src++; +- v_c = t_3; +- } +- if (v_c == 0u) { +- self->private_impl.f_metadata_is_zlib_compressed = false; +- } else if (v_c == 1u) { +- self->private_impl.f_metadata_is_zlib_compressed = true; +- } else { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_4 = *iop_a_src++; +- v_c = t_4; +- } +- if ((v_c != 0u) && self->private_impl.f_metadata_is_zlib_compressed) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method); +- goto exit; +- } +- self->private_impl.f_metadata_fourcc -= 2u; +- while (self->private_impl.f_metadata_fourcc != 1263947862u) { +- self->private_impl.f_metadata_fourcc += 1u; +- while (true) { +- if (self->private_impl.f_chunk_length <= 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length -= 1u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_5 = *iop_a_src++; +- v_c = t_5; +- } +- if (v_c == 0u) { +- break; +- } +- } +- } +- } else if (self->private_impl.f_chunk_type == 1951945850u) { +- if (self->private_impl.f_chunk_length <= 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_impl.f_chunk_length -= 1u; +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_6 = *iop_a_src++; +- v_c = t_6; +- } +- if (v_c != 0u) { +- status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method); +- goto exit; +- } +- self->private_impl.f_metadata_is_zlib_compressed = true; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_webp__decoder__build_code_lengths(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ v_status = wuffs_webp__decoder__build_huffman_nodes(self, a_hg, a_ht); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; + } +- self->private_impl.f_call_sequence &= 239u; +- status = wuffs_base__make_status(NULL); + goto ok; + } +- } while (0); +- label__goto_done__break:; +- if (self->private_impl.f_chunk_length != 0u) { +- status = wuffs_base__make_status(wuffs_png__error__bad_chunk); +- goto exit; +- } +- self->private_data.s_do_tell_me_more[0].scratch = 4u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); +- if (self->private_data.s_do_tell_me_more[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_tell_me_more[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; + } +- iop_a_src += self->private_data.s_do_tell_me_more[0].scratch; +- self->private_impl.f_metadata_flavor = 0u; +- self->private_impl.f_metadata_fourcc = 0u; +- self->private_impl.f_metadata_x = 0u; +- self->private_impl.f_metadata_y = 0u; +- self->private_impl.f_metadata_z = 0u; +- self->private_impl.f_call_sequence &= 239u; +- status = wuffs_base__make_status(NULL); +- goto ok; + + ok: +- self->private_impl.p_do_tell_me_more[0] = 0; ++ self->private_impl.p_decode_huffman_tree = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_tell_me_more[0].v_zlib_status = v_zlib_status; ++ self->private_impl.p_decode_huffman_tree = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +- if (a_dst && a_dst->data.ptr) { +- a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); +- } + if (a_src && a_src->data.ptr) { + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +@@ -58593,563 +72047,1574 @@ wuffs_png__decoder__do_tell_me_more( + return status; + } + +-// -------- func png.decoder.history_retain_length ++// -------- func webp.decoder.decode_huffman_tree_simple + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_png__decoder__history_retain_length( +- const wuffs_png__decoder* self) { +- if (!self) { +- return 0; ++static wuffs_base__status ++wuffs_webp__decoder__decode_huffman_tree_simple( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_hg, ++ uint32_t a_ht) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_use_second_symbol = 0; ++ uint32_t v_first_symbol_n_bits = 0; ++ uint32_t v_symbol0 = 0; ++ uint32_t v_symbol1 = 0; ++ uint32_t v_base_offset = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_huffman_tree_simple; ++ if (coro_susp_point) { ++ v_use_second_symbol = self->private_data.s_decode_huffman_tree_simple.v_use_second_symbol; ++ v_first_symbol_n_bits = self->private_data.s_decode_huffman_tree_simple.v_first_symbol_n_bits; ++ v_symbol0 = self->private_data.s_decode_huffman_tree_simple.v_symbol0; ++ v_base_offset = self->private_data.s_decode_huffman_tree_simple.v_base_offset; + } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- return 0u; ++ if (self->private_impl.f_n_bits < 2u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (self->private_impl.f_n_bits >= 2u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_use_second_symbol = (self->private_impl.f_bits & 1u); ++ v_first_symbol_n_bits = ((((self->private_impl.f_bits & 2u) >> 1u) * 7u) + 1u); ++ self->private_impl.f_bits >>= 2u; ++ self->private_impl.f_n_bits -= 2u; ++ if (self->private_impl.f_n_bits < v_first_symbol_n_bits) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (self->private_impl.f_n_bits >= v_first_symbol_n_bits) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_symbol0 = (self->private_impl.f_bits & ((((uint32_t)(1u)) << v_first_symbol_n_bits) - 1u)); ++ self->private_impl.f_bits >>= v_first_symbol_n_bits; ++ self->private_impl.f_n_bits -= v_first_symbol_n_bits; ++ v_base_offset = ((uint32_t)(WUFFS_WEBP__HUFFMAN_TABLE_BASE_OFFSETS[a_ht])); ++ if (v_use_second_symbol != 0u) { ++ if (self->private_impl.f_n_bits < 8u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ if (self->private_impl.f_n_bits >= 8u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_symbol1 = (self->private_impl.f_bits & 255u); ++ self->private_impl.f_bits >>= 8u; ++ self->private_impl.f_n_bits -= 8u; ++ self->private_data.f_huffman_nodes[a_hg][(v_base_offset + 0u)] = ((uint16_t)((v_base_offset + 1u))); ++ self->private_data.f_huffman_nodes[a_hg][(v_base_offset + 1u)] = ((uint16_t)((v_symbol0 | 32768u))); ++ self->private_data.f_huffman_nodes[a_hg][(v_base_offset + 2u)] = ((uint16_t)((v_symbol1 | 32768u))); ++ } else { ++ self->private_data.f_huffman_nodes[a_hg][v_base_offset] = ((uint16_t)((v_symbol0 | 32768u))); ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_huffman_tree_simple = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_huffman_tree_simple = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_huffman_tree_simple.v_use_second_symbol = v_use_second_symbol; ++ self->private_data.s_decode_huffman_tree_simple.v_first_symbol_n_bits = v_first_symbol_n_bits; ++ self->private_data.s_decode_huffman_tree_simple.v_symbol0 = v_symbol0; ++ self->private_data.s_decode_huffman_tree_simple.v_base_offset = v_base_offset; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; + } + +-// -------- func png.decoder.workbuf_len ++// -------- func webp.decoder.decode_code_length_code_lengths + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_png__decoder__workbuf_len( +- const wuffs_png__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); ++static wuffs_base__status ++wuffs_webp__decoder__decode_code_length_code_lengths( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_n_codes = 0; ++ uint32_t v_i = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_code_length_code_lengths; ++ if (coro_susp_point) { ++ v_n_codes = self->private_data.s_decode_code_length_code_lengths.v_n_codes; ++ v_i = self->private_data.s_decode_code_length_code_lengths.v_i; + } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- return wuffs_base__utility__make_range_ii_u64(self->private_impl.f_overall_workbuf_length, self->private_impl.f_overall_workbuf_length); ++ if (self->private_impl.f_n_bits < 4u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (self->private_impl.f_n_bits >= 4u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_n_codes = ((self->private_impl.f_bits & 15u) + 4u); ++ self->private_impl.f_bits >>= 4u; ++ self->private_impl.f_n_bits -= 4u; ++ v_i = 0u; ++ while (v_i < v_n_codes) { ++ if (self->private_impl.f_n_bits < 3u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (self->private_impl.f_n_bits >= 3u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ self->private_impl.f_code_length_code_lengths[WUFFS_WEBP__CODE_LENGTH_CODE_ORDER[v_i]] = ((uint8_t)((self->private_impl.f_bits & 7u))); ++ self->private_impl.f_bits >>= 3u; ++ self->private_impl.f_n_bits -= 3u; ++ v_i += 1u; ++ } ++ while (v_i < 19u) { ++ self->private_impl.f_code_length_code_lengths[WUFFS_WEBP__CODE_LENGTH_CODE_ORDER[v_i]] = 0u; ++ v_i += 1u; ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_code_length_code_lengths = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_code_length_code_lengths = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_code_length_code_lengths.v_n_codes = v_n_codes; ++ self->private_data.s_decode_code_length_code_lengths.v_i = v_i; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; + } + +-// -------- func png.decoder.filter_and_swizzle ++// -------- func webp.decoder.build_code_lengths_huffman_nodes + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__filter_and_swizzle( +- wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf) { +- return (*self->private_impl.choosy_filter_and_swizzle)(self, a_dst, a_workbuf); ++wuffs_webp__decoder__build_code_lengths_huffman_nodes( ++ wuffs_webp__decoder* self) { ++ uint32_t v_code_bits = 0; ++ uint32_t v_code_len = 0; ++ uint32_t v_symbol = 0; ++ uint32_t v_histogram[8] = {0}; ++ uint32_t v_n_used_symbols = 0; ++ uint32_t v_last_used_symbol = 0; ++ uint32_t v_subscription_weight = 0; ++ uint32_t v_subscription_total = 0; ++ uint32_t v_curr_code = 0; ++ uint32_t v_next_codes[9] = {0}; ++ uint32_t v_n_branches = 0; ++ uint32_t v_h = 0; ++ uint32_t v_children = 0; ++ uint16_t v_node = 0; ++ ++ v_symbol = 0u; ++ while (v_symbol < 19u) { ++ v_code_len = ((uint32_t)(self->private_impl.f_code_length_code_lengths[v_symbol])); ++ if (v_code_len != 0u) { ++ v_histogram[v_code_len] += 1u; ++ v_n_used_symbols += 1u; ++ v_last_used_symbol = v_symbol; ++ } ++ v_symbol += 1u; ++ } ++ if (v_n_used_symbols < 1u) { ++ return wuffs_base__make_status(wuffs_webp__error__bad_huffman_code); ++ } else if (v_n_used_symbols == 1u) { ++ self->private_data.f_code_lengths_huffman_nodes[0u] = ((uint16_t)((v_last_used_symbol | 32768u))); ++ return wuffs_base__make_status(NULL); ++ } ++ v_subscription_weight = 16384u; ++ v_code_len = 1u; ++ while (true) { ++ v_curr_code = ((uint32_t)(((uint32_t)(v_curr_code + v_histogram[v_code_len])) << 1u)); ++ v_next_codes[(v_code_len + 1u)] = v_curr_code; ++ v_subscription_total += ((uint32_t)(v_subscription_weight * v_histogram[v_code_len])); ++ v_subscription_weight >>= 1u; ++ if (v_code_len >= 7u) { ++ break; ++ } ++ v_code_len += 1u; ++ } ++ if (v_subscription_total > 32768u) { ++ return wuffs_base__make_status(wuffs_webp__error__bad_huffman_code_over_subscribed); ++ } else if (v_subscription_total < 32768u) { ++ return wuffs_base__make_status(wuffs_webp__error__bad_huffman_code_under_subscribed); ++ } ++ self->private_data.f_code_lengths_huffman_nodes[0u] = 0u; ++ v_symbol = 0u; ++ while (v_symbol < 19u) { ++ v_code_len = ((uint32_t)(self->private_impl.f_code_length_code_lengths[v_symbol])); ++ if (v_code_len > 0u) { ++ v_code_bits = v_next_codes[v_code_len]; ++ v_next_codes[v_code_len] += 1u; ++ v_code_bits <<= (32u - v_code_len); ++ v_h = 0u; ++ while (v_code_len > 0u) { ++ v_node = self->private_data.f_code_lengths_huffman_nodes[v_h]; ++ if (v_node == 0u) { ++ v_children = ((uint32_t)(1u + ((uint32_t)(2u * v_n_branches)))); ++ v_children = wuffs_base__u32__min(v_children, 35u); ++ self->private_data.f_code_lengths_huffman_nodes[v_h] = ((uint16_t)(v_children)); ++ self->private_data.f_code_lengths_huffman_nodes[(v_children + 0u)] = 0u; ++ self->private_data.f_code_lengths_huffman_nodes[(v_children + 1u)] = 0u; ++ v_h = (v_children + (v_code_bits >> 31u)); ++ v_n_branches += 1u; ++ } else { ++ v_children = ((uint32_t)(v_node)); ++ v_h = (wuffs_base__u32__min(v_children, 35u) + (v_code_bits >> 31u)); ++ } ++ v_code_bits <<= 1u; ++ v_code_len -= 1u; ++ } ++ self->private_data.f_code_lengths_huffman_nodes[v_h] = ((uint16_t)((v_symbol | 32768u))); ++ } ++ v_symbol += 1u; ++ } ++ return wuffs_base__make_status(NULL); + } + ++// -------- func webp.decoder.build_huffman_nodes ++ + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__filter_and_swizzle__choosy_default( +- wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf) { +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint64_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_bytes_per_row0 = 0; +- uint64_t v_dst_bytes_per_row1 = 0; +- wuffs_base__slice_u8 v_dst_palette = {0}; +- wuffs_base__table_u8 v_tab = {0}; +- uint32_t v_y = 0; +- wuffs_base__slice_u8 v_dst = {0}; +- uint8_t v_filter = 0; +- wuffs_base__slice_u8 v_curr_row = {0}; +- wuffs_base__slice_u8 v_prev_row = {0}; +- +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++wuffs_webp__decoder__build_huffman_nodes( ++ wuffs_webp__decoder* self, ++ uint32_t a_hg, ++ uint32_t a_ht) { ++ uint32_t v_base_offset = 0; ++ uint32_t v_code_bits = 0; ++ uint32_t v_code_len = 0; ++ uint32_t v_symbol = 0; ++ uint32_t v_histogram[16] = {0}; ++ uint32_t v_n_used_symbols = 0; ++ uint32_t v_last_used_symbol = 0; ++ uint32_t v_subscription_weight = 0; ++ uint32_t v_subscription_total = 0; ++ uint32_t v_curr_code = 0; ++ uint32_t v_next_codes[17] = {0}; ++ uint32_t v_n_branches = 0; ++ uint32_t v_h = 0; ++ uint32_t v_children = 0; ++ uint16_t v_node = 0; ++ ++ v_base_offset = ((uint32_t)(WUFFS_WEBP__HUFFMAN_TABLE_BASE_OFFSETS[a_ht])); ++ v_symbol = 0u; ++ while (v_symbol < self->private_impl.f_ht_n_symbols) { ++ v_code_len = ((uint32_t)(((uint16_t)(self->private_data.f_code_lengths[v_symbol] & 15u)))); ++ if (v_code_len != 0u) { ++ v_histogram[v_code_len] += 1u; ++ v_n_used_symbols += 1u; ++ v_last_used_symbol = v_symbol; ++ } ++ v_symbol += 1u; ++ } ++ if (v_n_used_symbols < 1u) { ++ return wuffs_base__make_status(wuffs_webp__error__bad_huffman_code); ++ } else if (v_n_used_symbols == 1u) { ++ self->private_data.f_huffman_nodes[a_hg][v_base_offset] = ((uint16_t)((v_last_used_symbol | 32768u))); ++ return wuffs_base__make_status(NULL); + } +- v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8u))); +- v_dst_bytes_per_row0 = (((uint64_t)(self->private_impl.f_frame_rect_x0)) * v_dst_bytes_per_pixel); +- v_dst_bytes_per_row1 = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * v_dst_bytes_per_pixel); +- v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- if (v_dst_bytes_per_row1 < ((uint64_t)(v_tab.width))) { +- v_tab = wuffs_base__table_u8__subtable_ij(v_tab, +- 0u, +- 0u, +- v_dst_bytes_per_row1, +- ((uint64_t)(v_tab.height))); ++ v_subscription_weight = 16384u; ++ v_code_len = 1u; ++ while (true) { ++ v_curr_code = ((uint32_t)(((uint32_t)(v_curr_code + v_histogram[v_code_len])) << 1u)); ++ v_next_codes[(v_code_len + 1u)] = v_curr_code; ++ v_subscription_total += ((uint32_t)(v_subscription_weight * v_histogram[v_code_len])); ++ v_subscription_weight >>= 1u; ++ if (v_code_len >= 15u) { ++ break; ++ } ++ v_code_len += 1u; ++ } ++ if (v_subscription_total > 32768u) { ++ return wuffs_base__make_status(wuffs_webp__error__bad_huffman_code_over_subscribed); ++ } else if (v_subscription_total < 32768u) { ++ return wuffs_base__make_status(wuffs_webp__error__bad_huffman_code_under_subscribed); ++ } ++ self->private_data.f_huffman_nodes[a_hg][v_base_offset] = 0u; ++ v_symbol = 0u; ++ while (v_symbol < self->private_impl.f_ht_n_symbols) { ++ v_code_len = ((uint32_t)(((uint16_t)(self->private_data.f_code_lengths[v_symbol] & 15u)))); ++ if (v_code_len != 0u) { ++ v_code_bits = v_next_codes[v_code_len]; ++ v_next_codes[v_code_len] += 1u; ++ v_code_bits <<= (32u - v_code_len); ++ v_h = v_base_offset; ++ while (v_code_len > 0u) { ++ v_node = self->private_data.f_huffman_nodes[a_hg][v_h]; ++ if (v_node == 0u) { ++ v_children = ((uint32_t)(v_base_offset + ((uint32_t)(1u + ((uint32_t)(2u * v_n_branches)))))); ++ v_children = wuffs_base__u32__min(v_children, 6265u); ++ self->private_data.f_huffman_nodes[a_hg][v_h] = ((uint16_t)(v_children)); ++ self->private_data.f_huffman_nodes[a_hg][(v_children + 0u)] = 0u; ++ self->private_data.f_huffman_nodes[a_hg][(v_children + 1u)] = 0u; ++ v_h = (v_children + (v_code_bits >> 31u)); ++ v_n_branches += 1u; ++ } else { ++ v_children = ((uint32_t)(v_node)); ++ v_h = (wuffs_base__u32__min(v_children, 6265u) + (v_code_bits >> 31u)); ++ } ++ v_code_bits <<= 1u; ++ v_code_len -= 1u; ++ } ++ self->private_data.f_huffman_nodes[a_hg][v_h] = ((uint16_t)((v_symbol | 32768u))); ++ } ++ v_symbol += 1u; + } +- if (v_dst_bytes_per_row0 < ((uint64_t)(v_tab.width))) { +- v_tab = wuffs_base__table_u8__subtable_ij(v_tab, +- v_dst_bytes_per_row0, +- 0u, +- ((uint64_t)(v_tab.width)), +- ((uint64_t)(v_tab.height))); +- } else { +- v_tab = wuffs_base__table_u8__subtable_ij(v_tab, +- 0u, +- 0u, +- 0u, +- 0u); ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func webp.decoder.build_code_lengths ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__build_code_lengths( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_use_length = 0; ++ uint32_t v_length_n_bits = 0; ++ uint32_t v_length = 0; ++ uint16_t v_prev_code_length = 0; ++ uint32_t v_h = 0; ++ uint32_t v_s = 0; ++ uint32_t v_s_max = 0; ++ uint16_t v_node = 0; ++ uint32_t v_symbol = 0; ++ uint16_t v_repeat_value = 0; ++ uint32_t v_repeat_n_bits = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- v_y = self->private_impl.f_frame_rect_y0; +- while (v_y < self->private_impl.f_frame_rect_y1) { +- v_dst = wuffs_base__table_u8__row_u32(v_tab, v_y); +- if (1u > ((uint64_t)(a_workbuf.len))) { +- return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length); ++ ++ uint32_t coro_susp_point = self->private_impl.p_build_code_lengths; ++ if (coro_susp_point) { ++ v_length_n_bits = self->private_data.s_build_code_lengths.v_length_n_bits; ++ v_prev_code_length = self->private_data.s_build_code_lengths.v_prev_code_length; ++ v_s = self->private_data.s_build_code_lengths.v_s; ++ v_s_max = self->private_data.s_build_code_lengths.v_s_max; ++ v_node = self->private_data.s_build_code_lengths.v_node; ++ v_repeat_value = self->private_data.s_build_code_lengths.v_repeat_value; ++ v_repeat_n_bits = self->private_data.s_build_code_lengths.v_repeat_n_bits; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; + } +- v_filter = a_workbuf.ptr[0u]; +- a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, 1u); +- if (self->private_impl.f_pass_bytes_per_row > ((uint64_t)(a_workbuf.len))) { +- return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length); ++ v_use_length = (self->private_impl.f_bits & 1u); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ self->private_impl.f_ht_code_lengths_remaining = self->private_impl.f_ht_n_symbols; ++ if (v_use_length != 0u) { ++ if (self->private_impl.f_n_bits < 3u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (self->private_impl.f_n_bits >= 3u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_length_n_bits = (((self->private_impl.f_bits & 7u) * 2u) + 2u); ++ self->private_impl.f_bits >>= 3u; ++ self->private_impl.f_n_bits -= 3u; ++ while (self->private_impl.f_n_bits < v_length_n_bits) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ if (self->private_impl.f_n_bits >= v_length_n_bits) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_length = ((self->private_impl.f_bits & ((((uint32_t)(1u)) << v_length_n_bits) - 1u)) + 2u); ++ self->private_impl.f_bits >>= v_length_n_bits; ++ self->private_impl.f_n_bits -= v_length_n_bits; ++ if (v_length > self->private_impl.f_ht_n_symbols) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_huffman_code); ++ goto exit; ++ } ++ self->private_impl.f_ht_code_lengths_remaining = v_length; + } +- v_curr_row = wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_pass_bytes_per_row); +- a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, self->private_impl.f_pass_bytes_per_row); +- if (v_filter == 0u) { +- } else if (v_filter == 1u) { +- wuffs_png__decoder__filter_1(self, v_curr_row); +- } else if (v_filter == 2u) { +- wuffs_png__decoder__filter_2(self, v_curr_row, v_prev_row); +- } else if (v_filter == 3u) { +- wuffs_png__decoder__filter_3(self, v_curr_row, v_prev_row); +- } else if (v_filter == 4u) { +- wuffs_png__decoder__filter_4(self, v_curr_row, v_prev_row); +- } else { +- return wuffs_base__make_status(wuffs_png__error__bad_filter); ++ v_prev_code_length = 8u; ++ while (v_s < self->private_impl.f_ht_n_symbols) { ++ if (self->private_impl.f_ht_code_lengths_remaining <= 0u) { ++ while (v_s < self->private_impl.f_ht_n_symbols) { ++ self->private_data.f_code_lengths[v_s] = 0u; ++ v_s += 1u; ++ } ++ break; ++ } ++ self->private_impl.f_ht_code_lengths_remaining -= 1u; ++ v_h = 0u; ++ while (true) { ++ v_node = self->private_data.f_code_lengths_huffman_nodes[v_h]; ++ if (v_node >= 32768u) { ++ break; ++ } else if (v_node > 35u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_huffman_code); ++ goto exit; ++ } ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; ++ } ++ v_h = (((uint32_t)(v_node)) + (self->private_impl.f_bits & 1u)); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ } ++ v_symbol = ((uint32_t)(((uint16_t)(v_node & 32767u)))); ++ if (v_symbol == 0u) { ++ self->private_data.f_code_lengths[v_s] = 0u; ++ v_s += 1u; ++ continue; ++ } else if (v_symbol < 16u) { ++ v_prev_code_length = ((uint16_t)(v_symbol)); ++ self->private_data.f_code_lengths[v_s] = v_prev_code_length; ++ v_s += 1u; ++ continue; ++ } else if (v_symbol == 16u) { ++ v_repeat_value = v_prev_code_length; ++ } else { ++ v_repeat_value = 0u; ++ } ++ v_repeat_n_bits = ((uint32_t)(WUFFS_WEBP__REPEAT_N_BITS[(v_symbol & 3u)])); ++ v_s_max = ((uint32_t)(((uint32_t)(WUFFS_WEBP__REPEAT_COUNTS[(v_symbol & 3u)])) + v_s)); ++ if (self->private_impl.f_n_bits < v_repeat_n_bits) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; ++ } ++ if (self->private_impl.f_n_bits >= v_repeat_n_bits) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_s_max += (self->private_impl.f_bits & ((((uint32_t)(1u)) << v_repeat_n_bits) - 1u)); ++ self->private_impl.f_bits >>= v_repeat_n_bits; ++ self->private_impl.f_n_bits -= v_repeat_n_bits; ++ if (v_s_max > self->private_impl.f_ht_n_symbols) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_huffman_code); ++ goto exit; ++ } ++ while (v_s < v_s_max) { ++ self->private_data.f_code_lengths[v_s] = v_repeat_value; ++ v_s += 1u; ++ } + } +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, v_curr_row); +- v_prev_row = v_curr_row; +- v_y += 1u; ++ ++ goto ok; ++ ok: ++ self->private_impl.p_build_code_lengths = 0; ++ goto exit; + } +- return wuffs_base__make_status(NULL); ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_build_code_lengths = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_build_code_lengths.v_length_n_bits = v_length_n_bits; ++ self->private_data.s_build_code_lengths.v_prev_code_length = v_prev_code_length; ++ self->private_data.s_build_code_lengths.v_s = v_s; ++ self->private_data.s_build_code_lengths.v_s_max = v_s_max; ++ self->private_data.s_build_code_lengths.v_node = v_node; ++ self->private_data.s_build_code_lengths.v_repeat_value = v_repeat_value; ++ self->private_data.s_build_code_lengths.v_repeat_n_bits = v_repeat_n_bits; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; + } + +-// -------- func png.decoder.filter_and_swizzle_tricky ++// -------- func webp.decoder.decode_pixels_slow + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_png__decoder__filter_and_swizzle_tricky( +- wuffs_png__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__slice_u8 a_workbuf) { +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint64_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_bytes_per_row1 = 0; +- wuffs_base__slice_u8 v_dst_palette = {0}; +- wuffs_base__table_u8 v_tab = {0}; +- uint64_t v_src_bytes_per_pixel = 0; ++wuffs_webp__decoder__decode_pixels_slow( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_dst, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_width, ++ uint32_t a_height, ++ wuffs_base__slice_u8 a_tile_data, ++ uint32_t a_tile_size_log2) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint64_t v_p = 0; ++ uint64_t v_p_max = 0; ++ uint32_t v_tile_size_log2 = 0; ++ uint32_t v_width_in_tiles = 0; + uint32_t v_x = 0; + uint32_t v_y = 0; +- uint64_t v_i = 0; +- wuffs_base__slice_u8 v_dst = {0}; +- uint8_t v_filter = 0; +- wuffs_base__slice_u8 v_s = {0}; +- wuffs_base__slice_u8 v_curr_row = {0}; +- wuffs_base__slice_u8 v_prev_row = {0}; +- uint8_t v_bits_unpacked[8] = {0}; +- uint8_t v_bits_packed = 0; +- uint8_t v_packs_remaining = 0; +- uint8_t v_multiplier = 0; +- uint8_t v_shift = 0; ++ uint32_t v_i = 0; ++ uint32_t v_hg = 0; ++ uint32_t v_h = 0; ++ uint16_t v_node = 0; ++ uint32_t v_pixel_g = 0; ++ uint32_t v_color = 0; ++ wuffs_base__slice_u8 v_dst_pixel = {0}; ++ uint32_t v_back_ref_len_n_bits = 0; ++ uint32_t v_back_ref_len_minus_1 = 0; ++ uint32_t v_back_ref_dist_n_bits = 0; ++ uint32_t v_back_ref_dist_sym = 0; ++ uint32_t v_back_ref_dist_premap_minus_1 = 0; ++ uint32_t v_back_ref_dist_minus_1 = 0; ++ uint32_t v_dm = 0; ++ uint32_t v_dx = 0; ++ uint32_t v_dy = 0; ++ uint64_t v_p_end = 0; ++ uint64_t v_dist4 = 0; ++ uint64_t v_q = 0; ++ wuffs_base__slice_u8 v_color_cache_pixels = {0}; ++ uint64_t v_color_cache_p = 0; ++ uint32_t v_color_cache_shift = 0; + +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); +- } +- v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8u))); +- v_dst_bytes_per_row1 = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * v_dst_bytes_per_pixel); +- v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- v_src_bytes_per_pixel = 1u; +- if (self->private_impl.f_depth >= 8u) { +- v_src_bytes_per_pixel = (((uint64_t)(WUFFS_PNG__NUM_CHANNELS[self->private_impl.f_color_type])) * ((uint64_t)((self->private_impl.f_depth >> 3u)))); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- if (self->private_impl.f_chunk_type_array[0u] == 73u) { +- v_y = ((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][5u])); +- } else { +- v_y = self->private_impl.f_frame_rect_y0; ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_pixels_slow; ++ if (coro_susp_point) { ++ v_p = self->private_data.s_decode_pixels_slow.v_p; ++ v_p_max = self->private_data.s_decode_pixels_slow.v_p_max; ++ v_tile_size_log2 = self->private_data.s_decode_pixels_slow.v_tile_size_log2; ++ v_width_in_tiles = self->private_data.s_decode_pixels_slow.v_width_in_tiles; ++ v_x = self->private_data.s_decode_pixels_slow.v_x; ++ v_y = self->private_data.s_decode_pixels_slow.v_y; ++ v_hg = self->private_data.s_decode_pixels_slow.v_hg; ++ v_node = self->private_data.s_decode_pixels_slow.v_node; ++ v_color = self->private_data.s_decode_pixels_slow.v_color; ++ v_back_ref_len_n_bits = self->private_data.s_decode_pixels_slow.v_back_ref_len_n_bits; ++ v_back_ref_len_minus_1 = self->private_data.s_decode_pixels_slow.v_back_ref_len_minus_1; ++ v_back_ref_dist_n_bits = self->private_data.s_decode_pixels_slow.v_back_ref_dist_n_bits; ++ v_back_ref_dist_premap_minus_1 = self->private_data.s_decode_pixels_slow.v_back_ref_dist_premap_minus_1; ++ v_color_cache_p = self->private_data.s_decode_pixels_slow.v_color_cache_p; + } +- while (v_y < self->private_impl.f_frame_rect_y1) { +- v_dst = wuffs_base__table_u8__row_u32(v_tab, v_y); +- if (v_dst_bytes_per_row1 < ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row1); +- } +- if (1u > ((uint64_t)(a_workbuf.len))) { +- return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length); +- } +- v_filter = a_workbuf.ptr[0u]; +- a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, 1u); +- if (self->private_impl.f_pass_bytes_per_row > ((uint64_t)(a_workbuf.len))) { +- return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length); +- } +- v_curr_row = wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_pass_bytes_per_row); +- a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, self->private_impl.f_pass_bytes_per_row); +- if (v_filter == 0u) { +- } else if (v_filter == 1u) { +- wuffs_png__decoder__filter_1(self, v_curr_row); +- } else if (v_filter == 2u) { +- wuffs_png__decoder__filter_2(self, v_curr_row, v_prev_row); +- } else if (v_filter == 3u) { +- wuffs_png__decoder__filter_3(self, v_curr_row, v_prev_row); +- } else if (v_filter == 4u) { +- wuffs_png__decoder__filter_4(self, v_curr_row, v_prev_row); +- } else { +- return wuffs_base__make_status(wuffs_png__error__bad_filter); ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ v_p_max = ((uint64_t)((4u * a_width * a_height))); ++ if (((uint64_t)(a_dst.len)) < v_p_max) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_dst_buffer); ++ goto exit; + } +- v_s = v_curr_row; +- if (self->private_impl.f_chunk_type_array[0u] == 73u) { +- v_x = ((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][2u])); ++ if (a_tile_size_log2 != 0u) { ++ v_tile_size_log2 = a_tile_size_log2; ++ v_width_in_tiles = ((a_width + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2); + } else { +- v_x = self->private_impl.f_frame_rect_x0; ++ v_tile_size_log2 = 31u; ++ v_width_in_tiles = 1u; + } +- if (self->private_impl.f_depth == 8u) { +- while (v_x < self->private_impl.f_frame_rect_x1) { +- v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel); +- if (v_i <= ((uint64_t)(v_dst.len))) { +- if (self->private_impl.f_color_type == 4u) { +- if (2u <= ((uint64_t)(v_s.len))) { +- v_bits_unpacked[0u] = v_s.ptr[0u]; +- v_bits_unpacked[1u] = v_s.ptr[0u]; +- v_bits_unpacked[2u] = v_s.ptr[0u]; +- v_bits_unpacked[3u] = v_s.ptr[1u]; +- v_s = wuffs_base__slice_u8__subslice_i(v_s, 2u); +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4)); +- } +- } else if (((uint32_t)(self->private_impl.f_remap_transparency)) != 0u) { +- if (self->private_impl.f_color_type == 0u) { +- if (1u <= ((uint64_t)(v_s.len))) { +- v_bits_unpacked[0u] = v_s.ptr[0u]; +- v_bits_unpacked[1u] = v_s.ptr[0u]; +- v_bits_unpacked[2u] = v_s.ptr[0u]; +- v_bits_unpacked[3u] = 255u; +- v_s = wuffs_base__slice_u8__subslice_i(v_s, 1u); +- if (((uint32_t)(self->private_impl.f_remap_transparency)) == ((((uint32_t)(v_bits_unpacked[0u])) << 0u) | +- (((uint32_t)(v_bits_unpacked[1u])) << 8u) | +- (((uint32_t)(v_bits_unpacked[2u])) << 16u) | +- (((uint32_t)(v_bits_unpacked[3u])) << 24u))) { +- v_bits_unpacked[0u] = 0u; +- v_bits_unpacked[1u] = 0u; +- v_bits_unpacked[2u] = 0u; +- v_bits_unpacked[3u] = 0u; +- } +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4)); ++ while (v_p < v_p_max) { ++ v_i = ((uint32_t)(((uint32_t)(((uint32_t)(((uint32_t)((v_y >> v_tile_size_log2) * v_width_in_tiles)) + (v_x >> v_tile_size_log2))) * 4u)) + 1u)); ++ if (((uint64_t)(v_i)) < ((uint64_t)(a_tile_data.len))) { ++ v_hg = ((uint32_t)(a_tile_data.ptr[((uint64_t)(v_i))])); ++ } ++ v_h = ((uint32_t)(WUFFS_WEBP__HUFFMAN_TABLE_BASE_OFFSETS[0u])); ++ while (true) { ++ v_node = self->private_data.f_huffman_nodes[v_hg][v_h]; ++ if (v_node >= 32768u) { ++ break; ++ } else if (v_node > 6265u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_huffman_code); ++ goto exit; ++ } ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; ++ } ++ v_h = (((uint32_t)(v_node)) + (self->private_impl.f_bits & 1u)); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ } ++ v_pixel_g = ((uint32_t)(((uint16_t)(v_node & 32767u)))); ++ if (v_pixel_g < 256u) { ++ v_color = (v_pixel_g << 8u); ++ v_h = ((uint32_t)(WUFFS_WEBP__HUFFMAN_TABLE_BASE_OFFSETS[1u])); ++ while (true) { ++ v_node = self->private_data.f_huffman_nodes[v_hg][v_h]; ++ if (v_node >= 32768u) { ++ break; ++ } ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } +- } else { +- if (3u <= ((uint64_t)(v_s.len))) { +- v_bits_unpacked[0u] = v_s.ptr[2u]; +- v_bits_unpacked[1u] = v_s.ptr[1u]; +- v_bits_unpacked[2u] = v_s.ptr[0u]; +- v_bits_unpacked[3u] = 255u; +- v_s = wuffs_base__slice_u8__subslice_i(v_s, 3u); +- if (((uint32_t)(self->private_impl.f_remap_transparency)) == ((((uint32_t)(v_bits_unpacked[0u])) << 0u) | +- (((uint32_t)(v_bits_unpacked[1u])) << 8u) | +- (((uint32_t)(v_bits_unpacked[2u])) << 16u) | +- (((uint32_t)(v_bits_unpacked[3u])) << 24u))) { +- v_bits_unpacked[0u] = 0u; +- v_bits_unpacked[1u] = 0u; +- v_bits_unpacked[2u] = 0u; +- v_bits_unpacked[3u] = 0u; +- } +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4)); ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; ++ } ++ v_h = ((((uint32_t)(v_node)) & 4095u) + (self->private_impl.f_bits & 1u)); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ } ++ v_color |= (((uint32_t)(((uint16_t)(v_node & 255u)))) << 16u); ++ v_h = ((uint32_t)(WUFFS_WEBP__HUFFMAN_TABLE_BASE_OFFSETS[2u])); ++ while (true) { ++ v_node = self->private_data.f_huffman_nodes[v_hg][v_h]; ++ if (v_node >= 32768u) { ++ break; ++ } ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; + } +- } else if (v_src_bytes_per_pixel <= ((uint64_t)(v_s.len))) { +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__slice_u8__subslice_j(v_s, v_src_bytes_per_pixel)); +- v_s = wuffs_base__slice_u8__subslice_i(v_s, v_src_bytes_per_pixel); ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; + } ++ v_h = ((((uint32_t)(v_node)) & 4095u) + (self->private_impl.f_bits & 1u)); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; + } +- v_x += (((uint32_t)(1u)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0u]); +- } +- } else if (self->private_impl.f_depth < 8u) { +- v_multiplier = 1u; +- if (self->private_impl.f_color_type == 0u) { +- v_multiplier = WUFFS_PNG__LOW_BIT_DEPTH_MULTIPLIERS[self->private_impl.f_depth]; +- } +- v_shift = ((8u - self->private_impl.f_depth) & 7u); +- v_packs_remaining = 0u; +- while (v_x < self->private_impl.f_frame_rect_x1) { +- v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel); +- if (v_i <= ((uint64_t)(v_dst.len))) { +- if ((v_packs_remaining == 0u) && (1u <= ((uint64_t)(v_s.len)))) { +- v_packs_remaining = WUFFS_PNG__LOW_BIT_DEPTH_NUM_PACKS[self->private_impl.f_depth]; +- v_bits_packed = v_s.ptr[0u]; +- v_s = wuffs_base__slice_u8__subslice_i(v_s, 1u); ++ v_color |= (((uint32_t)(((uint16_t)(v_node & 255u)))) << 0u); ++ v_h = ((uint32_t)(WUFFS_WEBP__HUFFMAN_TABLE_BASE_OFFSETS[3u])); ++ while (true) { ++ v_node = self->private_data.f_huffman_nodes[v_hg][v_h]; ++ if (v_node >= 32768u) { ++ break; + } +- v_bits_unpacked[0u] = ((uint8_t)((v_bits_packed >> v_shift) * v_multiplier)); +- v_bits_packed = ((uint8_t)(v_bits_packed << self->private_impl.f_depth)); +- v_packs_remaining = ((uint8_t)(v_packs_remaining - 1u)); +- if (((uint32_t)(self->private_impl.f_remap_transparency)) != 0u) { +- v_bits_unpacked[1u] = v_bits_unpacked[0u]; +- v_bits_unpacked[2u] = v_bits_unpacked[0u]; +- v_bits_unpacked[3u] = 255u; +- if (((uint32_t)(self->private_impl.f_remap_transparency)) == ((((uint32_t)(v_bits_unpacked[0u])) << 0u) | +- (((uint32_t)(v_bits_unpacked[1u])) << 8u) | +- (((uint32_t)(v_bits_unpacked[2u])) << 16u) | +- (((uint32_t)(v_bits_unpacked[3u])) << 24u))) { +- v_bits_unpacked[0u] = 0u; +- v_bits_unpacked[1u] = 0u; +- v_bits_unpacked[2u] = 0u; +- v_bits_unpacked[3u] = 0u; ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; + } +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4)); +- } else { +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 1)); ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; + } ++ v_h = ((((uint32_t)(v_node)) & 4095u) + (self->private_impl.f_bits & 1u)); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; + } +- v_x += (((uint32_t)(1u)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0u]); +- } +- } else { +- while (v_x < self->private_impl.f_frame_rect_x1) { +- v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel); +- if (v_i <= ((uint64_t)(v_dst.len))) { +- if (self->private_impl.f_color_type == 0u) { +- if (2u <= ((uint64_t)(v_s.len))) { +- v_bits_unpacked[0u] = v_s.ptr[1u]; +- v_bits_unpacked[1u] = v_s.ptr[0u]; +- v_bits_unpacked[2u] = v_s.ptr[1u]; +- v_bits_unpacked[3u] = v_s.ptr[0u]; +- v_bits_unpacked[4u] = v_s.ptr[1u]; +- v_bits_unpacked[5u] = v_s.ptr[0u]; +- v_bits_unpacked[6u] = 255u; +- v_bits_unpacked[7u] = 255u; +- v_s = wuffs_base__slice_u8__subslice_i(v_s, 2u); +- if (self->private_impl.f_remap_transparency == ((((uint64_t)(v_bits_unpacked[0u])) << 0u) | +- (((uint64_t)(v_bits_unpacked[1u])) << 8u) | +- (((uint64_t)(v_bits_unpacked[2u])) << 16u) | +- (((uint64_t)(v_bits_unpacked[3u])) << 24u) | +- (((uint64_t)(v_bits_unpacked[4u])) << 32u) | +- (((uint64_t)(v_bits_unpacked[5u])) << 40u) | +- (((uint64_t)(v_bits_unpacked[6u])) << 48u) | +- (((uint64_t)(v_bits_unpacked[7u])) << 56u))) { +- v_bits_unpacked[0u] = 0u; +- v_bits_unpacked[1u] = 0u; +- v_bits_unpacked[2u] = 0u; +- v_bits_unpacked[3u] = 0u; +- v_bits_unpacked[4u] = 0u; +- v_bits_unpacked[5u] = 0u; +- v_bits_unpacked[6u] = 0u; +- v_bits_unpacked[7u] = 0u; ++ v_color |= (((uint32_t)(((uint16_t)(v_node & 255u)))) << 24u); ++ } else if (v_pixel_g < 280u) { ++ if (v_pixel_g < 260u) { ++ v_back_ref_len_minus_1 = (v_pixel_g - 256u); ++ } else { ++ v_back_ref_len_n_bits = ((v_pixel_g - 258u) >> 1u); ++ v_back_ref_len_minus_1 = ((((uint32_t)(2u)) + (v_pixel_g & 1u)) << v_back_ref_len_n_bits); ++ while (self->private_impl.f_n_bits < v_back_ref_len_n_bits) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; + } +- } else if (self->private_impl.f_color_type == 2u) { +- if (6u <= ((uint64_t)(v_s.len))) { +- v_bits_unpacked[0u] = v_s.ptr[5u]; +- v_bits_unpacked[1u] = v_s.ptr[4u]; +- v_bits_unpacked[2u] = v_s.ptr[3u]; +- v_bits_unpacked[3u] = v_s.ptr[2u]; +- v_bits_unpacked[4u] = v_s.ptr[1u]; +- v_bits_unpacked[5u] = v_s.ptr[0u]; +- v_bits_unpacked[6u] = 255u; +- v_bits_unpacked[7u] = 255u; +- v_s = wuffs_base__slice_u8__subslice_i(v_s, 6u); +- if (self->private_impl.f_remap_transparency == ((((uint64_t)(v_bits_unpacked[0u])) << 0u) | +- (((uint64_t)(v_bits_unpacked[1u])) << 8u) | +- (((uint64_t)(v_bits_unpacked[2u])) << 16u) | +- (((uint64_t)(v_bits_unpacked[3u])) << 24u) | +- (((uint64_t)(v_bits_unpacked[4u])) << 32u) | +- (((uint64_t)(v_bits_unpacked[5u])) << 40u) | +- (((uint64_t)(v_bits_unpacked[6u])) << 48u) | +- (((uint64_t)(v_bits_unpacked[7u])) << 56u))) { +- v_bits_unpacked[0u] = 0u; +- v_bits_unpacked[1u] = 0u; +- v_bits_unpacked[2u] = 0u; +- v_bits_unpacked[3u] = 0u; +- v_bits_unpacked[4u] = 0u; +- v_bits_unpacked[5u] = 0u; +- v_bits_unpacked[6u] = 0u; +- v_bits_unpacked[7u] = 0u; ++ if (self->private_impl.f_n_bits >= v_back_ref_len_n_bits) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_back_ref_len_minus_1 += (self->private_impl.f_bits & ((((uint32_t)(1u)) << v_back_ref_len_n_bits) - 1u)); ++ self->private_impl.f_bits >>= v_back_ref_len_n_bits; ++ self->private_impl.f_n_bits -= v_back_ref_len_n_bits; ++ } ++ v_h = ((uint32_t)(WUFFS_WEBP__HUFFMAN_TABLE_BASE_OFFSETS[4u])); ++ while (true) { ++ v_node = self->private_data.f_huffman_nodes[v_hg][v_h]; ++ if (v_node >= 32768u) { ++ break; ++ } ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; + } +- } else if (self->private_impl.f_color_type == 4u) { +- if (4u <= ((uint64_t)(v_s.len))) { +- v_bits_unpacked[0u] = v_s.ptr[1u]; +- v_bits_unpacked[1u] = v_s.ptr[0u]; +- v_bits_unpacked[2u] = v_s.ptr[1u]; +- v_bits_unpacked[3u] = v_s.ptr[0u]; +- v_bits_unpacked[4u] = v_s.ptr[1u]; +- v_bits_unpacked[5u] = v_s.ptr[0u]; +- v_bits_unpacked[6u] = v_s.ptr[3u]; +- v_bits_unpacked[7u] = v_s.ptr[2u]; +- v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; ++ } ++ v_h = ((((uint32_t)(v_node)) & 4095u) + (self->private_impl.f_bits & 1u)); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ } ++ v_back_ref_dist_sym = ((uint32_t)(((uint16_t)(v_node & 32767u)))); ++ if (v_back_ref_dist_sym < 4u) { ++ v_back_ref_dist_premap_minus_1 = v_back_ref_dist_sym; ++ } else if (v_back_ref_dist_sym < 40u) { ++ v_back_ref_dist_n_bits = ((v_back_ref_dist_sym - 2u) >> 1u); ++ v_back_ref_dist_premap_minus_1 = ((((uint32_t)(2u)) + (v_back_ref_dist_sym & 1u)) << v_back_ref_dist_n_bits); ++ while (self->private_impl.f_n_bits < v_back_ref_dist_n_bits) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; + } +- } else { +- if (8u <= ((uint64_t)(v_s.len))) { +- v_bits_unpacked[0u] = v_s.ptr[5u]; +- v_bits_unpacked[1u] = v_s.ptr[4u]; +- v_bits_unpacked[2u] = v_s.ptr[3u]; +- v_bits_unpacked[3u] = v_s.ptr[2u]; +- v_bits_unpacked[4u] = v_s.ptr[1u]; +- v_bits_unpacked[5u] = v_s.ptr[0u]; +- v_bits_unpacked[6u] = v_s.ptr[7u]; +- v_bits_unpacked[7u] = v_s.ptr[6u]; +- v_s = wuffs_base__slice_u8__subslice_i(v_s, 8u); ++ if (self->private_impl.f_n_bits >= v_back_ref_dist_n_bits) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; + } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; + } +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 8)); ++ v_back_ref_dist_premap_minus_1 += (self->private_impl.f_bits & ((((uint32_t)(1u)) << v_back_ref_dist_n_bits) - 1u)); ++ self->private_impl.f_bits >>= v_back_ref_dist_n_bits; ++ self->private_impl.f_n_bits -= v_back_ref_dist_n_bits; + } +- v_x += (((uint32_t)(1u)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0u]); ++ if (v_back_ref_dist_premap_minus_1 >= 120u) { ++ v_back_ref_dist_minus_1 = (v_back_ref_dist_premap_minus_1 - 120u); ++ } else { ++ v_dm = ((uint32_t)(WUFFS_WEBP__DISTANCE_MAP[v_back_ref_dist_premap_minus_1])); ++ v_dy = (v_dm >> 4u); ++ v_dx = ((uint32_t)(7u - (v_dm & 15u))); ++ v_back_ref_dist_minus_1 = ((uint32_t)((a_width * v_dy) + v_dx)); ++ } ++ v_p_end = (v_p + ((uint64_t)(((v_back_ref_len_minus_1 + 1u) * 4u)))); ++ v_dist4 = ((((uint64_t)(v_back_ref_dist_minus_1)) * 4u) + 4u); ++ if ((v_p_end > v_p_max) || (v_p_end > ((uint64_t)(a_dst.len))) || (v_p < v_dist4)) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_back_reference); ++ goto exit; ++ } ++ v_q = (v_p - v_dist4); ++ while ((v_q < v_p) && (v_p < v_p_end)) { ++ a_dst.ptr[v_p] = a_dst.ptr[v_q]; ++ v_p += 1u; ++ v_q += 1u; ++ } ++ v_x += (v_back_ref_len_minus_1 + 1u); ++ while (v_x >= a_width) { ++ v_x -= a_width; ++ v_y += 1u; ++ } ++ continue; ++ } else { ++ if ((v_color_cache_p > v_p) || (v_p > ((uint64_t)(a_dst.len)))) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_dst_buffer); ++ goto exit; ++ } ++ v_color_cache_pixels = wuffs_base__slice_u8__subslice_ij(a_dst, v_color_cache_p, v_p); ++ v_color_cache_p = v_p; ++ v_color_cache_shift = ((32u - self->private_impl.f_color_cache_bits) & 31u); ++ while (((uint64_t)(v_color_cache_pixels.len)) >= 4u) { ++ v_color = wuffs_base__peek_u32le__no_bounds_check(v_color_cache_pixels.ptr); ++ self->private_data.f_color_cache[((((uint32_t)(v_color * 506832829u)) >> v_color_cache_shift) & 2047u)] = v_color; ++ v_color_cache_pixels = wuffs_base__slice_u8__subslice_i(v_color_cache_pixels, 4u); ++ } ++ v_color = self->private_data.f_color_cache[((v_pixel_g - 280u) & 2047u)]; ++ } ++ if (v_p > ((uint64_t)(a_dst.len))) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_dst_buffer); ++ goto exit; ++ } ++ v_dst_pixel = wuffs_base__slice_u8__subslice_i(a_dst, v_p); ++ if (((uint64_t)(v_dst_pixel.len)) < 4u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_dst_buffer); ++ goto exit; ++ } ++ wuffs_base__poke_u32le__no_bounds_check(v_dst_pixel.ptr, v_color); ++ v_p += 4u; ++ v_x += 1u; ++ if (v_x == a_width) { ++ v_x = 0u; ++ v_y += 1u; + } + } +- v_prev_row = v_curr_row; +- v_y += (((uint32_t)(1u)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][3u]); +- } +- return wuffs_base__make_status(NULL); +-} + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG) ++ goto ok; ++ ok: ++ self->private_impl.p_decode_pixels_slow = 0; ++ goto exit; ++ } + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_pixels_slow = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_pixels_slow.v_p = v_p; ++ self->private_data.s_decode_pixels_slow.v_p_max = v_p_max; ++ self->private_data.s_decode_pixels_slow.v_tile_size_log2 = v_tile_size_log2; ++ self->private_data.s_decode_pixels_slow.v_width_in_tiles = v_width_in_tiles; ++ self->private_data.s_decode_pixels_slow.v_x = v_x; ++ self->private_data.s_decode_pixels_slow.v_y = v_y; ++ self->private_data.s_decode_pixels_slow.v_hg = v_hg; ++ self->private_data.s_decode_pixels_slow.v_node = v_node; ++ self->private_data.s_decode_pixels_slow.v_color = v_color; ++ self->private_data.s_decode_pixels_slow.v_back_ref_len_n_bits = v_back_ref_len_n_bits; ++ self->private_data.s_decode_pixels_slow.v_back_ref_len_minus_1 = v_back_ref_len_minus_1; ++ self->private_data.s_decode_pixels_slow.v_back_ref_dist_n_bits = v_back_ref_dist_n_bits; ++ self->private_data.s_decode_pixels_slow.v_back_ref_dist_premap_minus_1 = v_back_ref_dist_premap_minus_1; ++ self->private_data.s_decode_pixels_slow.v_color_cache_p = v_color_cache_p; + +-// ---------------- Status Codes Implementations ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } + +-const char wuffs_tga__error__bad_header[] = "#tga: bad header"; +-const char wuffs_tga__error__bad_run_length_encoding[] = "#tga: bad run length encoding"; +-const char wuffs_tga__error__truncated_input[] = "#tga: truncated input"; +-const char wuffs_tga__error__unsupported_tga_file[] = "#tga: unsupported TGA file"; ++ return status; ++} + +-// ---------------- Private Consts ++// -------- func webp.decoder.apply_transform_predictor + +-// ---------------- Private Initializer Prototypes ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_webp__decoder__apply_transform_predictor( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_pix, ++ wuffs_base__slice_u8 a_tile_data) { ++ uint64_t v_w4 = 0; ++ wuffs_base__slice_u8 v_prev_row = {0}; ++ wuffs_base__slice_u8 v_curr_row = {0}; ++ uint32_t v_tile_size_log2 = 0; ++ uint32_t v_tiles_per_row = 0; ++ uint32_t v_mask = 0; ++ uint32_t v_y = 0; ++ uint32_t v_x = 0; ++ uint64_t v_t = 0; ++ wuffs_base__slice_u8 v_tile_data = {0}; ++ uint8_t v_mode = 0; ++ uint32_t v_l0 = 0; ++ uint32_t v_l1 = 0; ++ uint32_t v_l2 = 0; ++ uint32_t v_l3 = 0; ++ uint32_t v_c0 = 0; ++ uint32_t v_c1 = 0; ++ uint32_t v_c2 = 0; ++ uint32_t v_c3 = 0; ++ uint32_t v_t0 = 0; ++ uint32_t v_t1 = 0; ++ uint32_t v_t2 = 0; ++ uint32_t v_t3 = 0; ++ uint32_t v_sum_l = 0; ++ uint32_t v_sum_t = 0; ++ ++ if ((self->private_impl.f_width <= 0u) || (self->private_impl.f_height <= 0u)) { ++ return wuffs_base__make_empty_struct(); ++ } ++ v_w4 = ((uint64_t)((self->private_impl.f_width * 4u))); ++ v_curr_row = wuffs_base__utility__empty_slice_u8(); ++ if (v_w4 <= ((uint64_t)(a_pix.len))) { ++ v_curr_row = wuffs_base__slice_u8__subslice_j(a_pix, v_w4); ++ } ++ if (((uint64_t)(v_curr_row.len)) >= 4u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[3u] += 255u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } ++ while (((uint64_t)(v_curr_row.len)) >= 8u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += v_curr_row.ptr[0u]; ++ v_curr_row.ptr[5u] += v_curr_row.ptr[1u]; ++ v_curr_row.ptr[6u] += v_curr_row.ptr[2u]; ++ v_curr_row.ptr[7u] += v_curr_row.ptr[3u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_curr_row = wuffs_base__slice_u8__subslice_i(v_curr_row, 4u); ++ } ++ v_tile_size_log2 = ((uint32_t)(self->private_impl.f_transform_tile_size_log2[0u])); ++ v_tiles_per_row = ((self->private_impl.f_width + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2); ++ v_mask = ((((uint32_t)(1u)) << v_tile_size_log2) - 1u); ++ v_y = 1u; ++ while (v_y < self->private_impl.f_height) { ++ v_t = ((uint64_t)((4u * (v_y >> v_tile_size_log2) * v_tiles_per_row))); ++ v_tile_data = wuffs_base__utility__empty_slice_u8(); ++ if (v_t <= ((uint64_t)(a_tile_data.len))) { ++ v_tile_data = wuffs_base__slice_u8__subslice_i(a_tile_data, v_t); ++ if (((uint64_t)(v_tile_data.len)) >= 4u) { ++ v_mode = ((uint8_t)(v_tile_data.ptr[1u] & 15u)); ++ v_tile_data = wuffs_base__slice_u8__subslice_i(v_tile_data, 4u); ++ } ++ } ++ if (v_w4 <= ((uint64_t)(a_pix.len))) { ++ v_prev_row = a_pix; ++ a_pix = wuffs_base__slice_u8__subslice_i(a_pix, v_w4); ++ v_curr_row = a_pix; ++ } ++ if ((((uint64_t)(v_prev_row.len)) >= 4u) && (((uint64_t)(v_curr_row.len)) >= 4u)) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[0u] += v_prev_row.ptr[0u]; ++ v_curr_row.ptr[1u] += v_prev_row.ptr[1u]; ++ v_curr_row.ptr[2u] += v_prev_row.ptr[2u]; ++ v_curr_row.ptr[3u] += v_prev_row.ptr[3u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } ++ v_x = 1u; ++ while (v_x < self->private_impl.f_width) { ++ if (((v_x & v_mask) == 0u) && (((uint64_t)(v_tile_data.len)) >= 4u)) { ++ v_mode = ((uint8_t)(v_tile_data.ptr[1u] & 15u)); ++ v_tile_data = wuffs_base__slice_u8__subslice_i(v_tile_data, 4u); ++ } ++ if ((((uint64_t)(v_prev_row.len)) < 12u) || (((uint64_t)(v_curr_row.len)) < 8u)) { ++ break; ++ } ++ if (v_mode == 0u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[7u] += 255u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 1u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += v_curr_row.ptr[0u]; ++ v_curr_row.ptr[5u] += v_curr_row.ptr[1u]; ++ v_curr_row.ptr[6u] += v_curr_row.ptr[2u]; ++ v_curr_row.ptr[7u] += v_curr_row.ptr[3u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 2u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += v_prev_row.ptr[4u]; ++ v_curr_row.ptr[5u] += v_prev_row.ptr[5u]; ++ v_curr_row.ptr[6u] += v_prev_row.ptr[6u]; ++ v_curr_row.ptr[7u] += v_prev_row.ptr[7u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 3u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += v_prev_row.ptr[8u]; ++ v_curr_row.ptr[5u] += v_prev_row.ptr[9u]; ++ v_curr_row.ptr[6u] += v_prev_row.ptr[10u]; ++ v_curr_row.ptr[7u] += v_prev_row.ptr[11u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 4u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += v_prev_row.ptr[0u]; ++ v_curr_row.ptr[5u] += v_prev_row.ptr[1u]; ++ v_curr_row.ptr[6u] += v_prev_row.ptr[2u]; ++ v_curr_row.ptr[7u] += v_prev_row.ptr[3u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 5u) { ++ v_l0 = ((((uint32_t)(v_curr_row.ptr[0u])) + ((uint32_t)(v_prev_row.ptr[8u]))) / 2u); ++ v_l1 = ((((uint32_t)(v_curr_row.ptr[1u])) + ((uint32_t)(v_prev_row.ptr[9u]))) / 2u); ++ v_l2 = ((((uint32_t)(v_curr_row.ptr[2u])) + ((uint32_t)(v_prev_row.ptr[10u]))) / 2u); ++ v_l3 = ((((uint32_t)(v_curr_row.ptr[3u])) + ((uint32_t)(v_prev_row.ptr[11u]))) / 2u); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += ((uint8_t)(((v_l0 + ((uint32_t)(v_prev_row.ptr[4u]))) / 2u))); ++ v_curr_row.ptr[5u] += ((uint8_t)(((v_l1 + ((uint32_t)(v_prev_row.ptr[5u]))) / 2u))); ++ v_curr_row.ptr[6u] += ((uint8_t)(((v_l2 + ((uint32_t)(v_prev_row.ptr[6u]))) / 2u))); ++ v_curr_row.ptr[7u] += ((uint8_t)(((v_l3 + ((uint32_t)(v_prev_row.ptr[7u]))) / 2u))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 6u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += ((uint8_t)(((((uint32_t)(v_curr_row.ptr[0u])) + ((uint32_t)(v_prev_row.ptr[0u]))) / 2u))); ++ v_curr_row.ptr[5u] += ((uint8_t)(((((uint32_t)(v_curr_row.ptr[1u])) + ((uint32_t)(v_prev_row.ptr[1u]))) / 2u))); ++ v_curr_row.ptr[6u] += ((uint8_t)(((((uint32_t)(v_curr_row.ptr[2u])) + ((uint32_t)(v_prev_row.ptr[2u]))) / 2u))); ++ v_curr_row.ptr[7u] += ((uint8_t)(((((uint32_t)(v_curr_row.ptr[3u])) + ((uint32_t)(v_prev_row.ptr[3u]))) / 2u))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 7u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += ((uint8_t)(((((uint32_t)(v_curr_row.ptr[0u])) + ((uint32_t)(v_prev_row.ptr[4u]))) / 2u))); ++ v_curr_row.ptr[5u] += ((uint8_t)(((((uint32_t)(v_curr_row.ptr[1u])) + ((uint32_t)(v_prev_row.ptr[5u]))) / 2u))); ++ v_curr_row.ptr[6u] += ((uint8_t)(((((uint32_t)(v_curr_row.ptr[2u])) + ((uint32_t)(v_prev_row.ptr[6u]))) / 2u))); ++ v_curr_row.ptr[7u] += ((uint8_t)(((((uint32_t)(v_curr_row.ptr[3u])) + ((uint32_t)(v_prev_row.ptr[7u]))) / 2u))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 8u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += ((uint8_t)(((((uint32_t)(v_prev_row.ptr[0u])) + ((uint32_t)(v_prev_row.ptr[4u]))) / 2u))); ++ v_curr_row.ptr[5u] += ((uint8_t)(((((uint32_t)(v_prev_row.ptr[1u])) + ((uint32_t)(v_prev_row.ptr[5u]))) / 2u))); ++ v_curr_row.ptr[6u] += ((uint8_t)(((((uint32_t)(v_prev_row.ptr[2u])) + ((uint32_t)(v_prev_row.ptr[6u]))) / 2u))); ++ v_curr_row.ptr[7u] += ((uint8_t)(((((uint32_t)(v_prev_row.ptr[3u])) + ((uint32_t)(v_prev_row.ptr[7u]))) / 2u))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 9u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += ((uint8_t)(((((uint32_t)(v_prev_row.ptr[4u])) + ((uint32_t)(v_prev_row.ptr[8u]))) / 2u))); ++ v_curr_row.ptr[5u] += ((uint8_t)(((((uint32_t)(v_prev_row.ptr[5u])) + ((uint32_t)(v_prev_row.ptr[9u]))) / 2u))); ++ v_curr_row.ptr[6u] += ((uint8_t)(((((uint32_t)(v_prev_row.ptr[6u])) + ((uint32_t)(v_prev_row.ptr[10u]))) / 2u))); ++ v_curr_row.ptr[7u] += ((uint8_t)(((((uint32_t)(v_prev_row.ptr[7u])) + ((uint32_t)(v_prev_row.ptr[11u]))) / 2u))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 10u) { ++ v_l0 = ((((uint32_t)(v_curr_row.ptr[0u])) + ((uint32_t)(v_prev_row.ptr[0u]))) / 2u); ++ v_l1 = ((((uint32_t)(v_curr_row.ptr[1u])) + ((uint32_t)(v_prev_row.ptr[1u]))) / 2u); ++ v_l2 = ((((uint32_t)(v_curr_row.ptr[2u])) + ((uint32_t)(v_prev_row.ptr[2u]))) / 2u); ++ v_l3 = ((((uint32_t)(v_curr_row.ptr[3u])) + ((uint32_t)(v_prev_row.ptr[3u]))) / 2u); ++ v_t0 = ((((uint32_t)(v_prev_row.ptr[4u])) + ((uint32_t)(v_prev_row.ptr[8u]))) / 2u); ++ v_t1 = ((((uint32_t)(v_prev_row.ptr[5u])) + ((uint32_t)(v_prev_row.ptr[9u]))) / 2u); ++ v_t2 = ((((uint32_t)(v_prev_row.ptr[6u])) + ((uint32_t)(v_prev_row.ptr[10u]))) / 2u); ++ v_t3 = ((((uint32_t)(v_prev_row.ptr[7u])) + ((uint32_t)(v_prev_row.ptr[11u]))) / 2u); ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += ((uint8_t)(((v_l0 + v_t0) / 2u))); ++ v_curr_row.ptr[5u] += ((uint8_t)(((v_l1 + v_t1) / 2u))); ++ v_curr_row.ptr[6u] += ((uint8_t)(((v_l2 + v_t2) / 2u))); ++ v_curr_row.ptr[7u] += ((uint8_t)(((v_l3 + v_t3) / 2u))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 11u) { ++ v_l0 = ((uint32_t)(v_curr_row.ptr[0u])); ++ v_l1 = ((uint32_t)(v_curr_row.ptr[1u])); ++ v_l2 = ((uint32_t)(v_curr_row.ptr[2u])); ++ v_l3 = ((uint32_t)(v_curr_row.ptr[3u])); ++ v_c0 = ((uint32_t)(v_prev_row.ptr[0u])); ++ v_c1 = ((uint32_t)(v_prev_row.ptr[1u])); ++ v_c2 = ((uint32_t)(v_prev_row.ptr[2u])); ++ v_c3 = ((uint32_t)(v_prev_row.ptr[3u])); ++ v_t0 = ((uint32_t)(v_prev_row.ptr[4u])); ++ v_t1 = ((uint32_t)(v_prev_row.ptr[5u])); ++ v_t2 = ((uint32_t)(v_prev_row.ptr[6u])); ++ v_t3 = ((uint32_t)(v_prev_row.ptr[7u])); ++ v_sum_l = (wuffs_webp__decoder__absolute_difference(self, v_c0, v_t0) + ++ wuffs_webp__decoder__absolute_difference(self, v_c1, v_t1) + ++ wuffs_webp__decoder__absolute_difference(self, v_c2, v_t2) + ++ wuffs_webp__decoder__absolute_difference(self, v_c3, v_t3)); ++ v_sum_t = (wuffs_webp__decoder__absolute_difference(self, v_c0, v_l0) + ++ wuffs_webp__decoder__absolute_difference(self, v_c1, v_l1) + ++ wuffs_webp__decoder__absolute_difference(self, v_c2, v_l2) + ++ wuffs_webp__decoder__absolute_difference(self, v_c3, v_l3)); ++ if (v_sum_l < v_sum_t) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += ((uint8_t)(v_l0)); ++ v_curr_row.ptr[5u] += ((uint8_t)(v_l1)); ++ v_curr_row.ptr[6u] += ((uint8_t)(v_l2)); ++ v_curr_row.ptr[7u] += ((uint8_t)(v_l3)); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += ((uint8_t)(v_t0)); ++ v_curr_row.ptr[5u] += ((uint8_t)(v_t1)); ++ v_curr_row.ptr[6u] += ((uint8_t)(v_t2)); ++ v_curr_row.ptr[7u] += ((uint8_t)(v_t3)); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } ++ } else if (v_mode == 12u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += wuffs_webp__decoder__mode12(self, v_curr_row.ptr[0u], v_prev_row.ptr[4u], v_prev_row.ptr[0u]); ++ v_curr_row.ptr[5u] += wuffs_webp__decoder__mode12(self, v_curr_row.ptr[1u], v_prev_row.ptr[5u], v_prev_row.ptr[1u]); ++ v_curr_row.ptr[6u] += wuffs_webp__decoder__mode12(self, v_curr_row.ptr[2u], v_prev_row.ptr[6u], v_prev_row.ptr[2u]); ++ v_curr_row.ptr[7u] += wuffs_webp__decoder__mode12(self, v_curr_row.ptr[3u], v_prev_row.ptr[7u], v_prev_row.ptr[3u]); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else if (v_mode == 13u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_curr_row.ptr[4u] += wuffs_webp__decoder__mode13(self, v_curr_row.ptr[0u], v_prev_row.ptr[4u], v_prev_row.ptr[0u]); ++ v_curr_row.ptr[5u] += wuffs_webp__decoder__mode13(self, v_curr_row.ptr[1u], v_prev_row.ptr[5u], v_prev_row.ptr[1u]); ++ v_curr_row.ptr[6u] += wuffs_webp__decoder__mode13(self, v_curr_row.ptr[2u], v_prev_row.ptr[6u], v_prev_row.ptr[2u]); ++ v_curr_row.ptr[7u] += wuffs_webp__decoder__mode13(self, v_curr_row.ptr[3u], v_prev_row.ptr[7u], v_prev_row.ptr[3u]); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } ++ v_curr_row = wuffs_base__slice_u8__subslice_i(v_curr_row, 4u); ++ v_prev_row = wuffs_base__slice_u8__subslice_i(v_prev_row, 4u); ++ v_x += 1u; ++ } ++ v_y += 1u; ++ } ++ return wuffs_base__make_empty_struct(); ++} + +-// ---------------- Private Function Prototypes ++// -------- func webp.decoder.absolute_difference + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_tga__decoder__do_decode_image_config( +- wuffs_tga__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); ++static uint32_t ++wuffs_webp__decoder__absolute_difference( ++ const wuffs_webp__decoder* self, ++ uint32_t a_a, ++ uint32_t a_b) { ++ if (a_a < a_b) { ++ return (a_b - a_a); ++ } ++ return (a_a - a_b); ++} + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_tga__decoder__do_decode_frame_config( +- wuffs_tga__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); ++// -------- func webp.decoder.mode12 + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_tga__decoder__do_decode_frame( +- wuffs_tga__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); ++static uint8_t ++wuffs_webp__decoder__mode12( ++ const wuffs_webp__decoder* self, ++ uint8_t a_l, ++ uint8_t a_t, ++ uint8_t a_tl) { ++ uint32_t v_v = 0; + +-// ---------------- VTables ++ v_v = ((uint32_t)((((uint32_t)(a_l)) + ((uint32_t)(a_t))) - ((uint32_t)(a_tl)))); ++ if (v_v < 256u) { ++ return ((uint8_t)(v_v)); ++ } else if (v_v < 512u) { ++ return 255u; ++ } ++ return 0u; ++} + +-const wuffs_base__image_decoder__func_ptrs +-wuffs_tga__decoder__func_ptrs_for__wuffs_base__image_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__pixel_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__pixel_blend, +- wuffs_base__slice_u8, +- wuffs_base__decode_frame_options*))(&wuffs_tga__decoder__decode_frame), +- (wuffs_base__status(*)(void*, +- wuffs_base__frame_config*, +- wuffs_base__io_buffer*))(&wuffs_tga__decoder__decode_frame_config), +- (wuffs_base__status(*)(void*, +- wuffs_base__image_config*, +- wuffs_base__io_buffer*))(&wuffs_tga__decoder__decode_image_config), +- (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_tga__decoder__frame_dirty_rect), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_tga__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_tga__decoder__history_retain_length), +- (uint32_t(*)(const void*))(&wuffs_tga__decoder__num_animation_loops), +- (uint64_t(*)(const void*))(&wuffs_tga__decoder__num_decoded_frame_configs), +- (uint64_t(*)(const void*))(&wuffs_tga__decoder__num_decoded_frames), +- (wuffs_base__status(*)(void*, +- uint64_t, +- uint64_t))(&wuffs_tga__decoder__restart_frame), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_tga__decoder__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- uint32_t, +- bool))(&wuffs_tga__decoder__set_report_metadata), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__more_information*, +- wuffs_base__io_buffer*))(&wuffs_tga__decoder__tell_me_more), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_tga__decoder__workbuf_len), +-}; ++// -------- func webp.decoder.mode13 + +-// ---------------- Initializer Implementations ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_webp__decoder__mode13( ++ const wuffs_webp__decoder* self, ++ uint8_t a_l, ++ uint8_t a_t, ++ uint8_t a_tl) { ++ uint32_t v_x = 0; ++ uint32_t v_y = 0; ++ uint32_t v_z = 0; ++ uint32_t v_v = 0; + +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_tga__decoder__initialize( +- wuffs_tga__decoder* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ v_x = ((((uint32_t)(a_l)) + ((uint32_t)(a_t))) / 2u); ++ v_y = ((uint32_t)(a_tl)); ++ v_z = ((uint32_t)(v_x - v_y)); ++ v_v = ((uint32_t)(v_x + wuffs_base__utility__sign_extend_rshift_u32(((uint32_t)(v_z + (v_z >> 31u))), 1u))); ++ if (v_v < 256u) { ++ return ((uint8_t)(v_v)); ++ } else if (v_v < 512u) { ++ return 255u; + } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ return 0u; ++} ++ ++// -------- func webp.decoder.apply_transform_cross_color ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_webp__decoder__apply_transform_cross_color( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_pix, ++ wuffs_base__slice_u8 a_tile_data) { ++ uint32_t v_tile_size_log2 = 0; ++ uint32_t v_tiles_per_row = 0; ++ uint32_t v_mask = 0; ++ uint32_t v_y = 0; ++ uint32_t v_x = 0; ++ uint64_t v_t = 0; ++ wuffs_base__slice_u8 v_tile_data = {0}; ++ uint32_t v_g2r = 0; ++ uint32_t v_g2b = 0; ++ uint32_t v_r2b = 0; ++ uint8_t v_b = 0; ++ uint8_t v_g = 0; ++ uint8_t v_r = 0; ++ ++ v_tile_size_log2 = ((uint32_t)(self->private_impl.f_transform_tile_size_log2[1u])); ++ v_tiles_per_row = ((self->private_impl.f_width + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2); ++ v_mask = ((((uint32_t)(1u)) << v_tile_size_log2) - 1u); ++ v_y = 0u; ++ while (v_y < self->private_impl.f_height) { ++ v_t = ((uint64_t)((4u * (v_y >> v_tile_size_log2) * v_tiles_per_row))); ++ v_tile_data = wuffs_base__utility__empty_slice_u8(); ++ if (v_t <= ((uint64_t)(a_tile_data.len))) { ++ v_tile_data = wuffs_base__slice_u8__subslice_i(a_tile_data, v_t); ++ } ++ v_x = 0u; ++ while (v_x < self->private_impl.f_width) { ++ if (((v_x & v_mask) == 0u) && (((uint64_t)(v_tile_data.len)) >= 4u)) { ++ v_g2r = wuffs_base__utility__sign_extend_convert_u8_u32(v_tile_data.ptr[0u]); ++ v_g2b = wuffs_base__utility__sign_extend_convert_u8_u32(v_tile_data.ptr[1u]); ++ v_r2b = wuffs_base__utility__sign_extend_convert_u8_u32(v_tile_data.ptr[2u]); ++ v_tile_data = wuffs_base__slice_u8__subslice_i(v_tile_data, 4u); ++ } ++ if (((uint64_t)(a_pix.len)) >= 4u) { ++ v_b = a_pix.ptr[0u]; ++ v_g = a_pix.ptr[1u]; ++ v_r = a_pix.ptr[2u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_r += ((uint8_t)((((uint32_t)(wuffs_base__utility__sign_extend_convert_u8_u32(v_g) * v_g2r)) >> 5u))); ++ v_b += ((uint8_t)((((uint32_t)(wuffs_base__utility__sign_extend_convert_u8_u32(v_g) * v_g2b)) >> 5u))); ++ v_b += ((uint8_t)((((uint32_t)(wuffs_base__utility__sign_extend_convert_u8_u32(v_r) * v_r2b)) >> 5u))); ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ a_pix.ptr[0u] = v_b; ++ a_pix.ptr[2u] = v_r; ++ a_pix = wuffs_base__slice_u8__subslice_i(a_pix, 4u); ++ } ++ v_x += 1u; ++ } ++ v_y += 1u; + } ++ return wuffs_base__make_empty_struct(); ++} ++ ++// -------- func webp.decoder.apply_transform_subtract_green ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_webp__decoder__apply_transform_subtract_green( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_pix) { ++ wuffs_base__slice_u8 v_p = {0}; ++ uint8_t v_g = 0; + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) ++ { ++ wuffs_base__slice_u8 i_slice_p = a_pix; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 4; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 4) * 4)); ++ while (v_p.ptr < i_end0_p) { ++ v_g = v_p.ptr[1u]; ++#if defined(__GNUC__) + #pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#pragma GCC diagnostic ignored "-Wconversion" + #endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); +- } +-#if !defined(__clang__) && defined(__GNUC__) ++ v_p.ptr[0u] += v_g; ++ v_p.ptr[2u] += v_g; ++#if defined(__GNUC__) + #pragma GCC diagnostic pop + #endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; +- } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ v_p.ptr += 4; + } ++ v_p.len = 0; + } +- +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = +- wuffs_base__image_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = +- (const void*)(&wuffs_tga__decoder__func_ptrs_for__wuffs_base__image_decoder); +- return wuffs_base__make_status(NULL); ++ return wuffs_base__make_empty_struct(); + } + +-wuffs_tga__decoder* +-wuffs_tga__decoder__alloc(void) { +- wuffs_tga__decoder* x = +- (wuffs_tga__decoder*)(calloc(sizeof(wuffs_tga__decoder), 1)); +- if (!x) { +- return NULL; ++// -------- func webp.decoder.apply_transform_color_indexing ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_webp__decoder__apply_transform_color_indexing( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_pix) { ++ uint32_t v_tile_size_log2 = 0; ++ uint32_t v_bits_per_pixel = 0; ++ uint32_t v_x_mask = 0; ++ uint32_t v_s_mask = 0; ++ uint64_t v_src_index = 0; ++ uint32_t v_y = 0; ++ uint64_t v_di = 0; ++ uint64_t v_dj = 0; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint32_t v_x = 0; ++ uint32_t v_s = 0; ++ uint32_t v_p = 0; ++ uint8_t v_p0 = 0; ++ uint8_t v_p1 = 0; ++ uint8_t v_p2 = 0; ++ uint8_t v_p3 = 0; ++ ++ v_tile_size_log2 = ((uint32_t)(self->private_impl.f_transform_tile_size_log2[3u])); ++ if (v_tile_size_log2 == 0u) { ++ { ++ wuffs_base__slice_u8 i_slice_dst = a_pix; ++ v_dst.ptr = i_slice_dst.ptr; ++ v_dst.len = 4; ++ const uint8_t* i_end0_dst = wuffs_private_impl__ptr_u8_plus_len(v_dst.ptr, (((i_slice_dst.len - (size_t)(v_dst.ptr - i_slice_dst.ptr)) / 4) * 4)); ++ while (v_dst.ptr < i_end0_dst) { ++ v_p = (((uint32_t)(v_dst.ptr[1u])) * 4u); ++ v_p0 = self->private_data.f_palette[(v_p + 0u)]; ++ v_p1 = self->private_data.f_palette[(v_p + 1u)]; ++ v_p2 = self->private_data.f_palette[(v_p + 2u)]; ++ v_p3 = self->private_data.f_palette[(v_p + 3u)]; ++ v_dst.ptr[0u] = v_p0; ++ v_dst.ptr[1u] = v_p1; ++ v_dst.ptr[2u] = v_p2; ++ v_dst.ptr[3u] = v_p3; ++ v_dst.ptr += 4; ++ } ++ v_dst.len = 0; ++ } ++ return wuffs_base__make_empty_struct(); + } +- if (wuffs_tga__decoder__initialize( +- x, sizeof(wuffs_tga__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; ++ v_bits_per_pixel = (((uint32_t)(8u)) >> v_tile_size_log2); ++ v_x_mask = ((((uint32_t)(1u)) << v_tile_size_log2) - 1u); ++ v_s_mask = ((((uint32_t)(1u)) << v_bits_per_pixel) - 1u); ++ v_src_index = ((uint64_t)((self->private_impl.f_workbuf_offset_for_color_indexing + 1u))); ++ v_y = 0u; ++ while (v_y < self->private_impl.f_height) { ++ v_di = ((uint64_t)((4u * (v_y + 0u) * self->private_impl.f_width))); ++ v_dj = ((uint64_t)((4u * (v_y + 1u) * self->private_impl.f_width))); ++ if ((v_di > v_dj) || (v_dj > ((uint64_t)(a_pix.len)))) { ++ break; ++ } ++ v_dst = wuffs_base__slice_u8__subslice_ij(a_pix, v_di, v_dj); ++ v_x = 0u; ++ while (((uint64_t)(v_dst.len)) >= 4u) { ++ if (((v_x & v_x_mask) == 0u) && (v_src_index < ((uint64_t)(a_pix.len)))) { ++ v_s = ((uint32_t)(a_pix.ptr[v_src_index])); ++ v_src_index += 4u; ++ } ++ v_p = ((v_s & v_s_mask) * 4u); ++ v_s >>= v_bits_per_pixel; ++ v_p0 = self->private_data.f_palette[(v_p + 0u)]; ++ v_p1 = self->private_data.f_palette[(v_p + 1u)]; ++ v_p2 = self->private_data.f_palette[(v_p + 2u)]; ++ v_p3 = self->private_data.f_palette[(v_p + 3u)]; ++ v_dst.ptr[0u] = v_p0; ++ v_dst.ptr[1u] = v_p1; ++ v_dst.ptr[2u] = v_p2; ++ v_dst.ptr[3u] = v_p3; ++ v_dst = wuffs_base__slice_u8__subslice_i(v_dst, 4u); ++ v_x += 1u; ++ } ++ v_y += 1u; + } +- return x; +-} +- +-size_t +-sizeof__wuffs_tga__decoder(void) { +- return sizeof(wuffs_tga__decoder); ++ return wuffs_base__make_empty_struct(); + } + +-// ---------------- Function Implementations +- +-// -------- func tga.decoder.get_quirk ++// -------- func webp.decoder.get_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_tga__decoder__get_quirk( +- const wuffs_tga__decoder* self, ++wuffs_webp__decoder__get_quirk( ++ const wuffs_webp__decoder* self, + uint32_t a_key) { + if (!self) { + return 0; +@@ -59162,12 +73627,12 @@ wuffs_tga__decoder__get_quirk( + return 0u; + } + +-// -------- func tga.decoder.set_quirk ++// -------- func webp.decoder.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__set_quirk( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__set_quirk( ++ wuffs_webp__decoder* self, + uint32_t a_key, + uint64_t a_value) { + if (!self) { +@@ -59183,12 +73648,12 @@ wuffs_tga__decoder__set_quirk( + return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func tga.decoder.decode_image_config ++// -------- func webp.decoder.decode_image_config + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__decode_image_config( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__decode_image_config( ++ wuffs_webp__decoder* self, + wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { + if (!self) { +@@ -59214,17 +73679,17 @@ wuffs_tga__decoder__decode_image_config( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_image_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_tga__decoder__do_decode_image_config(self, a_dst, a_src); ++ wuffs_base__status t_0 = wuffs_webp__decoder__do_decode_image_config(self, a_dst, a_src); + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_tga__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_webp__error__truncated_input); + goto exit; + } + status = v_status; +@@ -59232,13 +73697,13 @@ wuffs_tga__decoder__decode_image_config( + } + + ok: +- self->private_impl.p_decode_image_config[0] = 0; ++ self->private_impl.p_decode_image_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; + + goto exit; +@@ -59249,19 +73714,19 @@ wuffs_tga__decoder__decode_image_config( + return status; + } + +-// -------- func tga.decoder.do_decode_image_config ++// -------- func webp.decoder.do_decode_image_config + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_tga__decoder__do_decode_image_config( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__do_decode_image_config( ++ wuffs_webp__decoder* self, + wuffs_base__image_config* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); + +- uint32_t v_c = 0; +- uint32_t v_c5 = 0; +- uint32_t v_i = 0; ++ uint32_t v_c32 = 0; ++ uint64_t v_r_mark = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -59274,10 +73739,7 @@ wuffs_tga__decoder__do_decode_image_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config[0]; +- if (coro_susp_point) { +- v_i = self->private_data.s_do_decode_image_config[0].v_i; +- } ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +@@ -59287,411 +73749,446 @@ wuffs_tga__decoder__do_decode_image_config( + } + { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- self->private_impl.f_header_id_length = t_0; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- self->private_impl.f_header_color_map_type = t_1; +- } +- if (self->private_impl.f_header_color_map_type > 1u) { +- status = wuffs_base__make_status(wuffs_tga__error__bad_header); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_2 = *iop_a_src++; +- self->private_impl.f_header_image_type = t_2; +- } +- if ((self->private_impl.f_header_image_type == 1u) || +- (self->private_impl.f_header_image_type == 2u) || +- (self->private_impl.f_header_image_type == 3u) || +- (self->private_impl.f_header_image_type == 9u) || +- (self->private_impl.f_header_image_type == 10u) || +- (self->private_impl.f_header_image_type == 11u)) { +- } else { +- status = wuffs_base__make_status(wuffs_tga__error__bad_header); +- goto exit; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); +- uint16_t t_3; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_3 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); +- iop_a_src += 2; ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; + *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; +- if (num_bits_3 == 8) { +- t_3 = ((uint16_t)(*scratch)); ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch)); + break; + } +- num_bits_3 += 8u; +- *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; + } + } +- self->private_impl.f_header_color_map_first_entry_index = t_3; ++ v_c32 = t_0; ++ } ++ if (v_c32 != 1179011410u) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_header); ++ goto exit; + } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); +- uint16_t t_4; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_4 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); +- iop_a_src += 2; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ self->private_data.s_do_decode_image_config.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56)); ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; + *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4; +- if (num_bits_4 == 8) { +- t_4 = ((uint16_t)(*scratch)); ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch)); + break; + } +- num_bits_4 += 8u; +- *scratch |= ((uint64_t)(num_bits_4)) << 56; ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; + } + } +- self->private_impl.f_header_color_map_length = t_4; ++ self->private_impl.f_riff_chunk_length = t_1; + } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_5 = *iop_a_src++; +- self->private_impl.f_header_color_map_entry_size = t_5; ++ if ((self->private_impl.f_riff_chunk_length & 1u) != 0u) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_header); ++ goto exit; + } +- if (self->private_impl.f_header_color_map_type != 0u) { +- if ((self->private_impl.f_header_color_map_first_entry_index != 0u) || (self->private_impl.f_header_color_map_length > 256u)) { +- status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file); +- goto exit; +- } else if ((self->private_impl.f_header_color_map_entry_size != 15u) && +- (self->private_impl.f_header_color_map_entry_size != 16u) && +- (self->private_impl.f_header_color_map_entry_size != 24u) && +- (self->private_impl.f_header_color_map_entry_size != 32u)) { +- status = wuffs_base__make_status(wuffs_tga__error__bad_header); +- goto exit; ++ while (true) { ++ { ++ const bool o_0_closed_a_src = a_src->meta.closed; ++ const uint8_t* o_0_io2_a_src = io2_a_src; ++ wuffs_private_impl__io_reader__limit(&io2_a_src, iop_a_src, ++ ((uint64_t)(self->private_impl.f_riff_chunk_length))); ++ if (a_src) { ++ size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); ++ a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); ++ a_src->meta.wi = n; ++ } ++ v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_2 = wuffs_webp__decoder__do_decode_image_config_limited(self, a_src); ++ v_status = t_2; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_riff_chunk_length, ((uint32_t)(wuffs_private_impl__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); ++ io2_a_src = o_0_io2_a_src; ++ if (a_src) { ++ a_src->meta.closed = o_0_closed_a_src; ++ a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); ++ } + } +- } else { +- if ((self->private_impl.f_header_color_map_first_entry_index != 0u) || (self->private_impl.f_header_color_map_length != 0u) || (self->private_impl.f_header_color_map_entry_size != 0u)) { +- status = wuffs_base__make_status(wuffs_tga__error__bad_header); ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } else if ( ! wuffs_base__status__is_suspension(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } else if ((v_status.repr == wuffs_base__suspension__short_read) && (self->private_impl.f_riff_chunk_length == 0u)) { ++ status = wuffs_base__make_status(wuffs_webp__error__short_chunk); + goto exit; + } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); + } +- self->private_data.s_do_decode_image_config[0].scratch = 4u; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); +- if (self->private_data.s_do_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; ++ self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); ++ if (a_dst != NULL) { ++ wuffs_base__image_config__set( ++ a_dst, ++ self->private_impl.f_pixfmt, ++ 0u, ++ self->private_impl.f_width, ++ self->private_impl.f_height, ++ self->private_impl.f_frame_config_io_position, ++ false); + } +- iop_a_src += self->private_data.s_do_decode_image_config[0].scratch; ++ self->private_impl.f_call_sequence = 32u; ++ ++ ok: ++ self->private_impl.p_do_decode_image_config = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func webp.decoder.do_decode_image_config_limited ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__do_decode_image_config_limited( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_c32 = 0; ++ uint64_t v_r_mark = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_image_config_limited; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); +- uint32_t t_6; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_6 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ self->private_data.s_do_decode_image_config_limited.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56)); ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config_limited.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; + *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6; +- if (num_bits_6 == 8) { +- t_6 = ((uint32_t)(*scratch)); ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch)); + break; + } +- num_bits_6 += 8u; +- *scratch |= ((uint64_t)(num_bits_6)) << 56; ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; + } + } +- self->private_impl.f_width = t_6; ++ v_c32 = t_0; ++ } ++ if (v_c32 != 1346520407u) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_header); ++ goto exit; + } + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); +- uint32_t t_7; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_7 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; + } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ self->private_data.s_do_decode_image_config_limited.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); + while (true) { + if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { + status = wuffs_base__make_status(wuffs_base__suspension__short_read); + goto suspend; + } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56)); ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config_limited.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); + *scratch <<= 8; + *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7; +- if (num_bits_7 == 8) { +- t_7 = ((uint32_t)(*scratch)); ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch)); + break; + } +- num_bits_7 += 8u; +- *scratch |= ((uint64_t)(num_bits_7)) << 56; ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; + } + } +- self->private_impl.f_height = t_7; +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_8 = *iop_a_src++; +- self->private_impl.f_header_pixel_depth = t_8; ++ v_c32 = t_1; + } +- if ((self->private_impl.f_header_pixel_depth != 1u) && +- (self->private_impl.f_header_pixel_depth != 8u) && +- (self->private_impl.f_header_pixel_depth != 15u) && +- (self->private_impl.f_header_pixel_depth != 16u) && +- (self->private_impl.f_header_pixel_depth != 24u) && +- (self->private_impl.f_header_pixel_depth != 32u)) { +- status = wuffs_base__make_status(wuffs_tga__error__bad_header); ++ if (v_c32 == 540561494u) { ++ status = wuffs_base__make_status(wuffs_webp__error__unsupported_webp_file); + goto exit; +- } +- if ((self->private_impl.f_header_image_type | 8u) == 9u) { +- self->private_impl.f_scratch_bytes_per_pixel = 1u; +- self->private_impl.f_src_bytes_per_pixel = 1u; +- self->private_impl.f_src_pixfmt = 2164523016u; +- self->private_impl.f_opaque = ((self->private_impl.f_header_color_map_entry_size == 15u) || (self->private_impl.f_header_color_map_entry_size == 24u)); +- } else if ((self->private_impl.f_header_image_type | 8u) == 10u) { +- if ((self->private_impl.f_header_pixel_depth == 15u) || (self->private_impl.f_header_pixel_depth == 16u)) { +- self->private_impl.f_scratch_bytes_per_pixel = 4u; +- self->private_impl.f_src_bytes_per_pixel = 0u; +- self->private_impl.f_src_pixfmt = 2164295816u; +- } else if (self->private_impl.f_header_pixel_depth == 24u) { +- self->private_impl.f_scratch_bytes_per_pixel = 3u; +- self->private_impl.f_src_bytes_per_pixel = 3u; +- self->private_impl.f_src_pixfmt = 2147485832u; +- self->private_impl.f_opaque = true; +- } else if (self->private_impl.f_header_pixel_depth == 32u) { +- self->private_impl.f_scratch_bytes_per_pixel = 4u; +- self->private_impl.f_src_bytes_per_pixel = 4u; +- self->private_impl.f_src_pixfmt = 2164295816u; +- } else { +- status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file); +- goto exit; ++ } else if (v_c32 == 1278758998u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ uint32_t t_2; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config_limited.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config_limited.scratch; ++ uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2; ++ if (num_bits_2 == 24) { ++ t_2 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_2 += 8u; ++ *scratch |= ((uint64_t)(num_bits_2)) << 56; ++ } ++ } ++ self->private_impl.f_sub_chunk_length = t_2; + } +- } else { +- if (self->private_impl.f_header_pixel_depth == 8u) { +- self->private_impl.f_scratch_bytes_per_pixel = 1u; +- self->private_impl.f_src_bytes_per_pixel = 1u; +- self->private_impl.f_src_pixfmt = 536870920u; +- self->private_impl.f_opaque = true; +- } else { +- status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file); ++ if (self->private_impl.f_sub_chunk_length < 4u) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_header); + goto exit; + } +- } +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_9 = *iop_a_src++; +- self->private_impl.f_header_image_descriptor = t_9; +- } +- if ((self->private_impl.f_header_image_descriptor & 16u) != 0u) { +- status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file); +- goto exit; +- } +- self->private_data.s_do_decode_image_config[0].scratch = ((uint32_t)(self->private_impl.f_header_id_length)); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); +- if (self->private_data.s_do_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_image_config[0].scratch; +- if (self->private_impl.f_header_color_map_type != 0u) { +- while (v_i < ((uint32_t)(self->private_impl.f_header_color_map_length))) { +- if (self->private_impl.f_header_color_map_entry_size == 24u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17); +- uint32_t t_10; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) { +- t_10 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src))); +- iop_a_src += 3; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10; +- if (num_bits_10 == 16) { +- t_10 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_10 += 8u; +- *scratch |= ((uint64_t)(num_bits_10)) << 56; +- } +- } +- v_c = t_10; ++ self->private_impl.f_sub_chunk_has_padding = ((self->private_impl.f_sub_chunk_length & 1u) != 0u); ++ while (true) { ++ { ++ const bool o_0_closed_a_src = a_src->meta.closed; ++ const uint8_t* o_0_io2_a_src = io2_a_src; ++ wuffs_private_impl__io_reader__limit(&io2_a_src, iop_a_src, ++ ((uint64_t)(self->private_impl.f_sub_chunk_length))); ++ if (a_src) { ++ size_t n = ((size_t)(io2_a_src - a_src->data.ptr)); ++ a_src->meta.closed = a_src->meta.closed && (a_src->meta.wi <= n); ++ a_src->meta.wi = n; + } +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 0u)] = ((uint8_t)((v_c >> 0u))); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 1u)] = ((uint8_t)((v_c >> 8u))); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 2u)] = ((uint8_t)((v_c >> 16u))); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 3u)] = 255u; +- } else if (self->private_impl.f_header_color_map_entry_size == 32u) { ++ v_r_mark = ((uint64_t)(iop_a_src - io0_a_src)); + { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19); +- uint32_t t_11; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { +- t_11 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); +- iop_a_src += 4; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11; +- if (num_bits_11 == 24) { +- t_11 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_11 += 8u; +- *scratch |= ((uint64_t)(num_bits_11)) << 56; +- } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- v_c = t_11; +- } +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 0u)] = ((uint8_t)((v_c >> 0u))); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 1u)] = ((uint8_t)((v_c >> 8u))); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 2u)] = ((uint8_t)((v_c >> 16u))); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 3u)] = ((uint8_t)((v_c >> 24u))); +- } else { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21); +- uint32_t t_12; +- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { +- t_12 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2; +- } else { +- self->private_data.s_do_decode_image_config[0].scratch = 0; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22); +- while (true) { +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint64_t* scratch = &self->private_data.s_do_decode_image_config[0].scratch; +- uint32_t num_bits_12 = ((uint32_t)(*scratch >> 56)); +- *scratch <<= 8; +- *scratch >>= 8; +- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_12; +- if (num_bits_12 == 8) { +- t_12 = ((uint32_t)(*scratch)); +- break; +- } +- num_bits_12 += 8u; +- *scratch |= ((uint64_t)(num_bits_12)) << 56; +- } ++ wuffs_base__status t_3 = wuffs_webp__decoder__do_decode_image_config_limited_vp8l(self, a_src); ++ v_status = t_3; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; + } +- v_c = t_12; + } +- v_c5 = (31u & (v_c >> 0u)); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 0u)] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- v_c5 = (31u & (v_c >> 5u)); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 1u)] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- v_c5 = (31u & (v_c >> 10u)); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 2u)] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- self->private_data.f_src_palette[(((v_i & 255u) * 4u) + 3u)] = 255u; ++ wuffs_private_impl__u32__sat_sub_indirect(&self->private_impl.f_sub_chunk_length, ((uint32_t)(wuffs_private_impl__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)))))); ++ io2_a_src = o_0_io2_a_src; ++ if (a_src) { ++ a_src->meta.closed = o_0_closed_a_src; ++ a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr)); ++ } ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } else if ( ! wuffs_base__status__is_suspension(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } else if ((v_status.repr == wuffs_base__suspension__short_read) && (self->private_impl.f_sub_chunk_length == 0u)) { ++ status = wuffs_base__make_status(wuffs_webp__error__short_chunk); ++ goto exit; + } +- v_i += 1u; ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); + } +- while (v_i < 256u) { +- self->private_data.f_src_palette[((v_i * 4u) + 0u)] = 0u; +- self->private_data.f_src_palette[((v_i * 4u) + 1u)] = 0u; +- self->private_data.f_src_palette[((v_i * 4u) + 2u)] = 0u; +- self->private_data.f_src_palette[((v_i * 4u) + 3u)] = 255u; +- v_i += 1u; ++ } else if (v_c32 == 1480085590u) { ++ status = wuffs_base__make_status(wuffs_webp__error__unsupported_webp_file); ++ goto exit; ++ } else { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_header); ++ goto exit; ++ } ++ ++ ok: ++ self->private_impl.p_do_decode_image_config_limited = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_image_config_limited = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func webp.decoder.do_decode_image_config_limited_vp8l ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__do_decode_image_config_limited_vp8l( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_c32 = 0; ++ uint32_t v_transform_size = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_image_config_limited_vp8l; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; + } ++ uint32_t t_0 = *iop_a_src++; ++ v_c32 = t_0; + } +- self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- if (a_dst != NULL) { +- wuffs_base__image_config__set( +- a_dst, +- self->private_impl.f_src_pixfmt, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height, +- self->private_impl.f_frame_config_io_position, +- self->private_impl.f_opaque); ++ if (v_c32 != 47u) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_header); ++ goto exit; + } +- self->private_impl.f_call_sequence = 32u; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_decode_image_config_limited_vp8l.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_decode_image_config_limited_vp8l.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 24) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ v_c32 = t_1; ++ } ++ self->private_impl.f_width = ((v_c32 & 16383u) + 1u); ++ v_c32 >>= 14u; ++ self->private_impl.f_height = ((v_c32 & 16383u) + 1u); ++ v_c32 >>= 14u; ++ self->private_impl.f_pixfmt = 2415954056u; ++ if ((v_c32 & 1u) != 0u) { ++ self->private_impl.f_pixfmt = 2164295816u; ++ } ++ v_c32 >>= 1u; ++ if (v_c32 != 0u) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_header); ++ goto exit; ++ } ++ v_transform_size = (4u * ((self->private_impl.f_width + 3u) >> 2u) * ((self->private_impl.f_height + 3u) >> 2u)); ++ self->private_impl.f_workbuf_offset_for_transform[0u] = ((4u * self->private_impl.f_width * self->private_impl.f_height) + (0u * v_transform_size)); ++ self->private_impl.f_workbuf_offset_for_transform[1u] = ((4u * self->private_impl.f_width * self->private_impl.f_height) + (1u * v_transform_size)); ++ self->private_impl.f_workbuf_offset_for_transform[2u] = ((4u * self->private_impl.f_width * self->private_impl.f_height) + (2u * v_transform_size)); ++ self->private_impl.f_workbuf_offset_for_transform[3u] = ((4u * self->private_impl.f_width * self->private_impl.f_height) + (3u * v_transform_size)); + + goto ok; + ok: +- self->private_impl.p_do_decode_image_config[0] = 0; ++ self->private_impl.p_do_decode_image_config_limited_vp8l = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_decode_image_config[0].v_i = v_i; ++ self->private_impl.p_do_decode_image_config_limited_vp8l = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +@@ -59702,12 +74199,12 @@ wuffs_tga__decoder__do_decode_image_config( + return status; + } + +-// -------- func tga.decoder.decode_frame_config ++// -------- func webp.decoder.decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__decode_frame_config( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__decode_frame_config( ++ wuffs_webp__decoder* self, + wuffs_base__frame_config* a_dst, + wuffs_base__io_buffer* a_src) { + if (!self) { +@@ -59733,17 +74230,17 @@ wuffs_tga__decoder__decode_frame_config( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_tga__decoder__do_decode_frame_config(self, a_dst, a_src); ++ wuffs_base__status t_0 = wuffs_webp__decoder__do_decode_frame_config(self, a_dst, a_src); + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_tga__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_webp__error__truncated_input); + goto exit; + } + status = v_status; +@@ -59751,13 +74248,13 @@ wuffs_tga__decoder__decode_frame_config( + } + + ok: +- self->private_impl.p_decode_frame_config[0] = 0; ++ self->private_impl.p_decode_frame_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; + + goto exit; +@@ -59768,12 +74265,12 @@ wuffs_tga__decoder__decode_frame_config( + return status; + } + +-// -------- func tga.decoder.do_decode_frame_config ++// -------- func webp.decoder.do_decode_frame_config + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_tga__decoder__do_decode_frame_config( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__do_decode_frame_config( ++ wuffs_webp__decoder* self, + wuffs_base__frame_config* a_dst, + wuffs_base__io_buffer* a_src) { + wuffs_base__status status = wuffs_base__make_status(NULL); +@@ -59789,7 +74286,7 @@ wuffs_tga__decoder__do_decode_frame_config( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config[0]; ++ uint32_t coro_susp_point = self->private_impl.p_do_decode_frame_config; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +@@ -59799,7 +74296,7 @@ wuffs_tga__decoder__do_decode_frame_config( + a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_tga__decoder__do_decode_image_config(self, NULL, a_src); ++ status = wuffs_webp__decoder__do_decode_image_config(self, NULL, a_src); + if (a_src) { + iop_a_src = a_src->data.ptr + a_src->meta.ri; + } +@@ -59831,20 +74328,20 @@ wuffs_tga__decoder__do_decode_frame_config( + 0u, + self->private_impl.f_frame_config_io_position, + 0u, +- self->private_impl.f_opaque, + false, +- 4278190080u); ++ false, ++ 0u); + } + self->private_impl.f_call_sequence = 64u; + + ok: +- self->private_impl.p_do_decode_frame_config[0] = 0; ++ self->private_impl.p_do_decode_frame_config = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.p_do_decode_frame_config = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +@@ -59855,12 +74352,12 @@ wuffs_tga__decoder__do_decode_frame_config( + return status; + } + +-// -------- func tga.decoder.decode_frame ++// -------- func webp.decoder.decode_frame + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__decode_frame( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__decode_frame( ++ wuffs_webp__decoder* self, + wuffs_base__pixel_buffer* a_dst, + wuffs_base__io_buffer* a_src, + wuffs_base__pixel_blend a_blend, +@@ -59889,13 +74386,13 @@ wuffs_tga__decoder__decode_frame( + + wuffs_base__status v_status = wuffs_base__make_status(NULL); + +- uint32_t coro_susp_point = self->private_impl.p_decode_frame[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_frame; + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + + while (true) { + { +- wuffs_base__status t_0 = wuffs_tga__decoder__do_decode_frame(self, ++ wuffs_base__status t_0 = wuffs_webp__decoder__do_decode_frame(self, + a_dst, + a_src, + a_blend, +@@ -59904,64 +74401,627 @@ wuffs_tga__decoder__decode_frame( + v_status = t_0; + } + if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_tga__error__truncated_input); ++ status = wuffs_base__make_status(wuffs_webp__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ } ++ return status; ++} ++ ++// -------- func webp.decoder.do_decode_frame ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__do_decode_frame( ++ wuffs_webp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__pixel_blend a_blend, ++ wuffs_base__slice_u8 a_workbuf, ++ wuffs_base__decode_frame_options* a_opts) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_has_more = 0; ++ uint32_t v_width = 0; ++ wuffs_base__slice_u8 v_dst = {0}; ++ wuffs_base__slice_u8 v_tile_data = {0}; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ wuffs_base__slice_u8 v_pix = {0}; ++ uint32_t v_which = 0; ++ uint32_t v_transform_type = 0; ++ uint64_t v_ti = 0; ++ uint64_t v_tj = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_do_decode_frame; ++ if (coro_susp_point) { ++ v_width = self->private_data.s_do_decode_frame.v_width; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_call_sequence == 64u) { ++ } else if (self->private_impl.f_call_sequence < 64u) { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_webp__decoder__do_decode_frame_config(self, NULL, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } else { ++ status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ goto ok; ++ } ++ self->private_impl.f_seen_transform[0u] = false; ++ self->private_impl.f_seen_transform[1u] = false; ++ self->private_impl.f_seen_transform[2u] = false; ++ self->private_impl.f_seen_transform[3u] = false; ++ self->private_impl.f_n_transforms = 0u; ++ while (true) { ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; ++ } ++ v_has_more = (self->private_impl.f_bits & 1u); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ if (v_has_more == 0u) { ++ break; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_webp__decoder__decode_transform(self, a_src, a_workbuf); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ } ++ v_width = self->private_impl.f_width; ++ if (self->private_impl.f_seen_transform[3u]) { ++ v_width = self->private_impl.f_color_indexing_width; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_webp__decoder__decode_color_cache_parameters(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_overall_color_cache_bits = self->private_impl.f_color_cache_bits; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ status = wuffs_webp__decoder__decode_hg_table(self, a_src, v_width, a_workbuf); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ self->private_impl.f_color_cache_bits = self->private_impl.f_overall_color_cache_bits; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ status = wuffs_webp__decoder__decode_huffman_groups(self, a_src, self->private_impl.f_overall_n_huffman_groups); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ while (true) { ++ if ((((uint64_t)(self->private_impl.f_workbuf_offset_for_color_indexing)) > ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u]))) || ++ (((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])) > ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u]))) || ++ (((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u])) > ((uint64_t)(a_workbuf.len))) || ++ (((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])) > ((uint64_t)(a_workbuf.len)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; ++ } ++ v_dst = wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_color_indexing)), ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u]))); ++ v_tile_data = wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])), ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u]))); ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_1 = wuffs_webp__decoder__decode_pixels(self, ++ v_dst, ++ a_src, ++ v_width, ++ self->private_impl.f_height, ++ v_tile_data, ++ self->private_impl.f_overall_tile_size_log2); ++ v_status = t_1; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); ++ } ++ if (((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])) > ((uint64_t)(a_workbuf.len))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; ++ } ++ v_pix = wuffs_base__slice_u8__subslice_j(a_workbuf, ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u]))); ++ v_which = self->private_impl.f_n_transforms; ++ while (v_which > 0u) { ++ v_which -= 1u; ++ v_transform_type = ((uint32_t)(self->private_impl.f_transform_type[v_which])); ++ v_tile_data = wuffs_base__utility__empty_slice_u8(); ++ if (v_transform_type < 2u) { ++ v_ti = ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[(v_transform_type + 1u)])); ++ v_tj = ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[(v_transform_type + 2u)])); ++ if ((v_ti <= v_tj) && (v_tj <= ((uint64_t)(a_workbuf.len)))) { ++ v_tile_data = wuffs_base__slice_u8__subslice_ij(a_workbuf, v_ti, v_tj); ++ } ++ } ++ if (v_transform_type == 0u) { ++ wuffs_webp__decoder__apply_transform_predictor(self, v_pix, v_tile_data); ++ } else if (v_transform_type == 1u) { ++ wuffs_webp__decoder__apply_transform_cross_color(self, v_pix, v_tile_data); ++ } else if (v_transform_type == 2u) { ++ wuffs_webp__decoder__apply_transform_subtract_green(self, v_pix); ++ } else { ++ wuffs_webp__decoder__apply_transform_color_indexing(self, v_pix); ++ v_width = self->private_impl.f_width; ++ } ++ } ++ v_status = wuffs_webp__decoder__swizzle(self, a_dst, v_pix, a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = v_status; ++ if (wuffs_base__status__is_error(&status)) { ++ goto exit; ++ } else if (wuffs_base__status__is_suspension(&status)) { ++ status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ goto exit; ++ } ++ goto ok; ++ } ++ self->private_impl.f_call_sequence = 96u; ++ ++ ok: ++ self->private_impl.p_do_decode_frame = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_decode_frame = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_decode_frame.v_width = v_width; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func webp.decoder.decode_transform ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_transform( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint8_t v_c8 = 0; ++ uint32_t v_transform_type = 0; ++ uint32_t v_tile_size_log2 = 0; ++ wuffs_base__slice_u8 v_p = {0}; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_transform; ++ if (coro_susp_point) { ++ v_transform_type = self->private_data.s_decode_transform.v_transform_type; ++ v_tile_size_log2 = self->private_data.s_decode_transform.v_tile_size_log2; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_n_bits < 2u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (self->private_impl.f_n_bits >= 2u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_transform_type = (self->private_impl.f_bits & 3u); ++ self->private_impl.f_bits >>= 2u; ++ self->private_impl.f_n_bits -= 2u; ++ if (self->private_impl.f_seen_transform[v_transform_type] || (self->private_impl.f_n_transforms >= 4u)) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_transform); ++ goto exit; ++ } else if (self->private_impl.f_seen_transform[3u]) { ++ status = wuffs_base__make_status(wuffs_webp__error__unsupported_transform_after_color_indexing_transform); ++ goto exit; ++ } ++ self->private_impl.f_seen_transform[v_transform_type] = true; ++ self->private_impl.f_transform_type[self->private_impl.f_n_transforms] = ((uint8_t)(v_transform_type)); ++ self->private_impl.f_n_transforms += 1u; ++ if (v_transform_type < 2u) { ++ if (self->private_impl.f_n_bits < 3u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (self->private_impl.f_n_bits >= 3u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_tile_size_log2 = ((self->private_impl.f_bits & 7u) + 2u); ++ self->private_impl.f_transform_tile_size_log2[v_transform_type] = ((uint8_t)(v_tile_size_log2)); ++ self->private_impl.f_bits >>= 3u; ++ self->private_impl.f_n_bits -= 3u; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_webp__decoder__decode_color_cache_parameters(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_webp__decoder__decode_huffman_groups(self, a_src, 1u); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ while (true) { ++ if ((((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[(v_transform_type + 1u)])) > ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[(v_transform_type + 2u)]))) || (((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[(v_transform_type + 2u)])) > ((uint64_t)(a_workbuf.len)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; ++ } ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_2 = wuffs_webp__decoder__decode_pixels(self, ++ wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[(v_transform_type + 1u)])), ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[(v_transform_type + 2u)]))), ++ a_src, ++ ((self->private_impl.f_width + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2), ++ ((self->private_impl.f_height + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2), ++ wuffs_base__utility__empty_slice_u8(), ++ 0u); ++ v_status = t_2; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ } ++ } else if (v_transform_type == 2u) { ++ } else { ++ if (self->private_impl.f_n_bits < 8u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ if (self->private_impl.f_n_bits >= 8u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ self->private_impl.f_color_indexing_palette_size = ((self->private_impl.f_bits & 255u) + 1u); ++ self->private_impl.f_bits >>= 8u; ++ self->private_impl.f_n_bits -= 8u; ++ if (self->private_impl.f_color_indexing_palette_size <= 2u) { ++ self->private_impl.f_color_indexing_width = ((self->private_impl.f_width + 7u) / 8u); ++ self->private_impl.f_transform_tile_size_log2[3u] = 3u; ++ } else if (self->private_impl.f_color_indexing_palette_size <= 4u) { ++ self->private_impl.f_color_indexing_width = ((self->private_impl.f_width + 3u) / 4u); ++ self->private_impl.f_transform_tile_size_log2[3u] = 2u; ++ } else if (self->private_impl.f_color_indexing_palette_size <= 16u) { ++ self->private_impl.f_color_indexing_width = ((self->private_impl.f_width + 1u) / 2u); ++ self->private_impl.f_transform_tile_size_log2[3u] = 1u; ++ } else { ++ self->private_impl.f_color_indexing_width = self->private_impl.f_width; ++ self->private_impl.f_transform_tile_size_log2[3u] = 0u; ++ } ++ if (self->private_impl.f_width >= self->private_impl.f_color_indexing_width) { ++ self->private_impl.f_workbuf_offset_for_color_indexing = (4u * (self->private_impl.f_width - self->private_impl.f_color_indexing_width) * self->private_impl.f_height); ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ status = wuffs_webp__decoder__decode_color_cache_parameters(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ status = wuffs_webp__decoder__decode_huffman_groups(self, a_src, 1u); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ status = wuffs_webp__decoder__decode_pixels(self, ++ wuffs_base__make_slice_u8(self->private_data.f_palette, (4u * self->private_impl.f_color_indexing_palette_size)), ++ a_src, ++ self->private_impl.f_color_indexing_palette_size, ++ 1u, ++ wuffs_base__utility__empty_slice_u8(), ++ 0u); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; ++ } ++ wuffs_private_impl__bulk_memset(&self->private_data.f_palette[(4u * self->private_impl.f_color_indexing_palette_size)], (1024u - (4u * self->private_impl.f_color_indexing_palette_size)), 0u); ++ v_p = wuffs_base__make_slice_u8(self->private_data.f_palette, (4u * self->private_impl.f_color_indexing_palette_size)); ++ while (((uint64_t)(v_p.len)) >= 8u) { ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_p.ptr[4u] += v_p.ptr[0u]; ++ v_p.ptr[5u] += v_p.ptr[1u]; ++ v_p.ptr[6u] += v_p.ptr[2u]; ++ v_p.ptr[7u] += v_p.ptr[3u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ v_p = wuffs_base__slice_u8__subslice_i(v_p, 4u); ++ } ++ } ++ ++ ok: ++ self->private_impl.p_decode_transform = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_transform = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_transform.v_transform_type = v_transform_type; ++ self->private_data.s_decode_transform.v_tile_size_log2 = v_tile_size_log2; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ ++ return status; ++} ++ ++// -------- func webp.decoder.decode_color_cache_parameters ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_color_cache_parameters( ++ wuffs_webp__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint8_t v_c8 = 0; ++ uint32_t v_use_color_cache = 0; ++ uint32_t v_color_cache_bits = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_color_cache_parameters; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; ++ } ++ v_use_color_cache = (self->private_impl.f_bits & 1u); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ self->private_impl.f_color_cache_bits = 0u; ++ if (v_use_color_cache != 0u) { ++ if (self->private_impl.f_n_bits < 4u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (self->private_impl.f_n_bits >= 4u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); ++ goto exit; ++ } ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; ++ } ++ v_color_cache_bits = (self->private_impl.f_bits & 15u); ++ self->private_impl.f_bits >>= 4u; ++ self->private_impl.f_n_bits -= 4u; ++ if ((v_color_cache_bits < 1u) || (11u < v_color_cache_bits)) { ++ status = wuffs_base__make_status(wuffs_webp__error__bad_color_cache); + goto exit; + } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ self->private_impl.f_color_cache_bits = v_color_cache_bits; + } + ++ goto ok; + ok: +- self->private_impl.p_decode_frame[0] = 0; ++ self->private_impl.p_decode_color_cache_parameters = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++ self->private_impl.p_decode_color_cache_parameters = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + + goto exit; + exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } ++ + return status; + } + +-// -------- func tga.decoder.do_decode_frame ++// -------- func webp.decoder.decode_hg_table + + WUFFS_BASE__GENERATED_C_CODE + static wuffs_base__status +-wuffs_tga__decoder__do_decode_frame( +- wuffs_tga__decoder* self, +- wuffs_base__pixel_buffer* a_dst, ++wuffs_webp__decoder__decode_hg_table( ++ wuffs_webp__decoder* self, + wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { ++ uint32_t a_width, ++ wuffs_base__slice_u8 a_workbuf) { + wuffs_base__status status = wuffs_base__make_status(NULL); + + wuffs_base__status v_status = wuffs_base__make_status(NULL); +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint64_t v_dst_bytes_per_pixel = 0; +- uint32_t v_dst_x = 0; +- uint32_t v_dst_y = 0; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_dst_palette = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint64_t v_dst_start = 0; +- wuffs_base__slice_u8 v_src_palette = {0}; +- uint64_t v_mark = 0; +- uint64_t v_num_pixels64 = 0; +- uint32_t v_num_pixels32 = 0; +- uint32_t v_lit_length = 0; +- uint32_t v_run_length = 0; +- uint64_t v_num_dst_bytes = 0; +- uint32_t v_num_src_bytes = 0; +- uint32_t v_c = 0; +- uint32_t v_c5 = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_use_hg_table = 0; ++ uint32_t v_tile_size_log2 = 0; ++ wuffs_base__slice_u8 v_hg_pixels = {0}; ++ uint64_t v_n = 0; ++ wuffs_base__slice_u8 v_p = {0}; ++ uint32_t v_hg_plus_1 = 0; + + const uint8_t* iop_a_src = NULL; + const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +@@ -59974,276 +75034,155 @@ wuffs_tga__decoder__do_decode_frame( + io2_a_src = io0_a_src + a_src->meta.wi; + } + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame[0]; ++ uint32_t coro_susp_point = self->private_impl.p_decode_hg_table; + if (coro_susp_point) { +- v_dst_bytes_per_pixel = self->private_data.s_do_decode_frame[0].v_dst_bytes_per_pixel; +- v_dst_x = self->private_data.s_do_decode_frame[0].v_dst_x; +- v_dst_y = self->private_data.s_do_decode_frame[0].v_dst_y; +- v_mark = self->private_data.s_do_decode_frame[0].v_mark; +- v_num_pixels32 = self->private_data.s_do_decode_frame[0].v_num_pixels32; +- v_lit_length = self->private_data.s_do_decode_frame[0].v_lit_length; +- v_run_length = self->private_data.s_do_decode_frame[0].v_run_length; +- v_num_dst_bytes = self->private_data.s_do_decode_frame[0].v_num_dst_bytes; ++ v_tile_size_log2 = self->private_data.s_decode_hg_table.v_tile_size_log2; + } + switch (coro_susp_point) { + WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if (self->private_impl.f_call_sequence == 64u) { +- } else if (self->private_impl.f_call_sequence < 64u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ if (self->private_impl.f_n_bits < 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; + } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_tga__decoder__do_decode_frame_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ self->private_impl.f_bits = ((uint32_t)(v_c8)); ++ self->private_impl.f_n_bits = 8u; ++ } ++ v_use_hg_table = (self->private_impl.f_bits & 1u); ++ self->private_impl.f_bits >>= 1u; ++ self->private_impl.f_n_bits -= 1u; ++ if (v_use_hg_table == 0u) { ++ self->private_impl.f_overall_n_huffman_groups = 1u; ++ self->private_impl.f_overall_tile_size_log2 = 0u; ++ if ((((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])) > ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u]))) || (((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u])) > ((uint64_t)(a_workbuf.len)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; + } +- if (status.repr) { +- goto suspend; ++ v_hg_pixels = wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])), ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u]))); ++ if (((uint64_t)(v_hg_pixels.len)) >= 4u) { ++ v_hg_pixels.ptr[0u] = 0u; ++ v_hg_pixels.ptr[1u] = 0u; ++ v_hg_pixels.ptr[2u] = 0u; ++ v_hg_pixels.ptr[3u] = 0u; + } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); ++ status = wuffs_base__make_status(NULL); + goto ok; + } +- if (self->private_impl.f_header_color_map_type != 0u) { +- v_src_palette = wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024); +- } +- v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, +- wuffs_base__pixel_buffer__pixel_format(a_dst), +- wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)), +- wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt), +- v_src_palette, +- a_blend); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); ++ if (self->private_impl.f_n_bits < 3u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (self->private_impl.f_n_bits >= 3u) { ++ status = wuffs_base__make_status(wuffs_webp__error__internal_error_inconsistent_n_bits); + goto exit; + } +- goto ok; ++ self->private_impl.f_bits |= (((uint32_t)(v_c8)) << self->private_impl.f_n_bits); ++ self->private_impl.f_n_bits += 8u; + } +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_option); +- goto exit; ++ v_tile_size_log2 = ((self->private_impl.f_bits & 7u) + 2u); ++ self->private_impl.f_bits >>= 3u; ++ self->private_impl.f_n_bits -= 3u; ++ self->private_impl.f_overall_tile_size_log2 = v_tile_size_log2; ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8u))); +- if ((self->private_impl.f_header_image_descriptor & 32u) == 0u) { +- v_dst_y = ((uint32_t)(self->private_impl.f_height - 1u)); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ status = wuffs_webp__decoder__decode_color_cache_parameters(self, a_src); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; + } +- if ((self->private_impl.f_header_image_type & 8u) == 0u) { +- v_lit_length = self->private_impl.f_width; ++ if (status.repr) { ++ goto suspend; ++ } ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ status = wuffs_webp__decoder__decode_huffman_groups(self, a_src, 1u); ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ if (status.repr) { ++ goto suspend; + } +- label__resume__continue:; + while (true) { +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)); +- while (v_dst_y < self->private_impl.f_height) { +- v_dst = wuffs_base__table_u8__row_u32(v_tab, v_dst_y); +- v_dst_start = (((uint64_t)(v_dst_x)) * v_dst_bytes_per_pixel); +- if (v_dst_start <= ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_start); +- } else { +- v_dst = wuffs_base__utility__empty_slice_u8(); +- } +- while (v_dst_x < self->private_impl.f_width) { +- if (self->private_impl.f_src_bytes_per_pixel > 0u) { +- if (v_lit_length > 0u) { +- v_mark = ((uint64_t)(iop_a_src - io0_a_src)); +- v_num_pixels64 = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(self->private_impl.f_src_bytes_per_pixel))); +- v_num_pixels32 = ((uint32_t)(wuffs_base__u64__min(v_num_pixels64, ((uint64_t)(v_lit_length))))); +- v_num_dst_bytes = (((uint64_t)(v_num_pixels32)) * v_dst_bytes_per_pixel); +- v_num_src_bytes = (v_num_pixels32 * self->private_impl.f_src_bytes_per_pixel); +- self->private_data.s_do_decode_frame[0].scratch = v_num_src_bytes; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (self->private_data.s_do_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) { +- self->private_data.s_do_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src)); +- iop_a_src = io2_a_src; +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- iop_a_src += self->private_data.s_do_decode_frame[0].scratch; +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); +- if (v_num_dst_bytes <= ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_num_dst_bytes); +- } else { +- v_dst = wuffs_base__utility__empty_slice_u8(); +- } +- v_dst_x += v_num_pixels32; +- v_lit_length = (((uint32_t)(v_lit_length - v_num_pixels32)) & 65535u); +- if (v_lit_length > 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); +- goto label__resume__continue; +- } +- } else if (v_run_length > 0u) { +- v_run_length -= 1u; +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_scratch_bytes_per_pixel)); +- if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel); +- } +- v_dst_x += 1u; +- } else { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); +- goto label__resume__continue; +- } +- if (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) < 128u) { +- v_lit_length = (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) + 1u); +- iop_a_src += 1u; +- if ((v_lit_length + v_dst_x) > self->private_impl.f_width) { +- status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding); +- goto exit; +- } +- } else { +- if (self->private_impl.f_src_bytes_per_pixel == 1u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); +- goto label__resume__continue; +- } +- v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127u) + 1u); +- iop_a_src += 1u; +- self->private_data.f_scratch[0u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- } else if (self->private_impl.f_src_bytes_per_pixel == 3u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); +- goto label__resume__continue; +- } +- v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127u) + 1u); +- iop_a_src += 1u; +- self->private_data.f_scratch[0u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- self->private_data.f_scratch[1u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- self->private_data.f_scratch[2u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- } else { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 5u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7); +- goto label__resume__continue; +- } +- v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127u) + 1u); +- iop_a_src += 1u; +- self->private_data.f_scratch[0u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- self->private_data.f_scratch[1u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- self->private_data.f_scratch[2u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- self->private_data.f_scratch[3u] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- } +- if ((v_run_length + v_dst_x) > self->private_impl.f_width) { +- status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding); +- goto exit; +- } +- } +- } +- } else { +- if (v_lit_length > 0u) { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 2u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8); +- goto label__resume__continue; +- } +- v_c = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2u; +- v_c5 = (31u & (v_c >> 0u)); +- self->private_data.f_scratch[0u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- v_c5 = (31u & (v_c >> 5u)); +- self->private_data.f_scratch[1u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- v_c5 = (31u & (v_c >> 10u)); +- self->private_data.f_scratch[2u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- self->private_data.f_scratch[3u] = 255u; +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, 4)); +- if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel); +- } +- v_dst_x += 1u; +- v_lit_length -= 1u; +- } else if (v_run_length > 0u) { +- v_run_length -= 1u; +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_scratch_bytes_per_pixel)); +- if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel); +- } +- v_dst_x += 1u; +- } else { +- if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); +- goto label__resume__continue; +- } +- if (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) < 128u) { +- v_lit_length = (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) + 1u); +- iop_a_src += 1u; +- if ((v_lit_length + v_dst_x) > self->private_impl.f_width) { +- status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding); +- goto exit; +- } +- } else { +- if (((uint64_t)(io2_a_src - iop_a_src)) < 3u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); +- goto label__resume__continue; +- } +- v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127u) + 1u); +- iop_a_src += 1u; +- v_c = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); +- iop_a_src += 2u; +- v_c5 = (31u & (v_c >> 0u)); +- self->private_data.f_scratch[0u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- v_c5 = (31u & (v_c >> 5u)); +- self->private_data.f_scratch[1u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- v_c5 = (31u & (v_c >> 10u)); +- self->private_data.f_scratch[2u] = ((uint8_t)(((v_c5 << 3u) | (v_c5 >> 2u)))); +- self->private_data.f_scratch[3u] = 255u; +- if ((v_run_length + v_dst_x) > self->private_impl.f_width) { +- status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding); +- goto exit; +- } +- } +- } +- } +- } +- v_dst_x = 0u; +- if ((self->private_impl.f_header_image_descriptor & 32u) == 0u) { +- v_dst_y -= 1u; +- } else { +- v_dst_y += 1u; ++ if ((((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])) > ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u]))) || (((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u])) > ((uint64_t)(a_workbuf.len)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; ++ } ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- if ((self->private_impl.f_header_image_type & 8u) == 0u) { +- v_lit_length = self->private_impl.f_width; ++ wuffs_base__status t_2 = wuffs_webp__decoder__decode_pixels(self, ++ wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])), ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u]))), ++ a_src, ++ ((a_width + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2), ++ ((self->private_impl.f_height + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2), ++ wuffs_base__utility__empty_slice_u8(), ++ 0u); ++ v_status = t_2; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; + } + } +- break; ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ } ++ self->private_impl.f_overall_n_huffman_groups = 1u; ++ if ((((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])) > ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u]))) || (((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u])) > ((uint64_t)(a_workbuf.len)))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; ++ } ++ v_hg_pixels = wuffs_base__slice_u8__subslice_ij(a_workbuf, ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[0u])), ++ ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[1u]))); ++ v_n = ((uint64_t)((((a_width + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2) * ((self->private_impl.f_height + ((((uint32_t)(1u)) << v_tile_size_log2) - 1u)) >> v_tile_size_log2) * 4u))); ++ if (v_n > ((uint64_t)(v_hg_pixels.len))) { ++ status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); ++ goto exit; ++ } ++ v_p = wuffs_base__slice_u8__subslice_j(v_hg_pixels, v_n); ++ while (((uint64_t)(v_p.len)) >= 4u) { ++ if (v_p.ptr[2u] != 0u) { ++ status = wuffs_base__make_status(wuffs_webp__error__unsupported_number_of_huffman_groups); ++ goto exit; ++ } ++ v_hg_plus_1 = (((uint32_t)(v_p.ptr[1u])) + 1u); ++ if (self->private_impl.f_overall_n_huffman_groups < v_hg_plus_1) { ++ self->private_impl.f_overall_n_huffman_groups = v_hg_plus_1; ++ } ++ v_p = wuffs_base__slice_u8__subslice_i(v_p, 4u); + } +- self->private_impl.f_call_sequence = 96u; + + ok: +- self->private_impl.p_do_decode_frame[0] = 0; ++ self->private_impl.p_decode_hg_table = 0; + goto exit; + } + + goto suspend; + suspend: +- self->private_impl.p_do_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_decode_frame[0].v_dst_bytes_per_pixel = v_dst_bytes_per_pixel; +- self->private_data.s_do_decode_frame[0].v_dst_x = v_dst_x; +- self->private_data.s_do_decode_frame[0].v_dst_y = v_dst_y; +- self->private_data.s_do_decode_frame[0].v_mark = v_mark; +- self->private_data.s_do_decode_frame[0].v_num_pixels32 = v_num_pixels32; +- self->private_data.s_do_decode_frame[0].v_lit_length = v_lit_length; +- self->private_data.s_do_decode_frame[0].v_run_length = v_run_length; +- self->private_data.s_do_decode_frame[0].v_num_dst_bytes = v_num_dst_bytes; ++ self->private_impl.p_decode_hg_table = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_hg_table.v_tile_size_log2 = v_tile_size_log2; + + goto exit; + exit: +@@ -60254,12 +75193,117 @@ wuffs_tga__decoder__do_decode_frame( + return status; + } + +-// -------- func tga.decoder.frame_dirty_rect ++// -------- func webp.decoder.decode_pixels ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__decode_pixels( ++ wuffs_webp__decoder* self, ++ wuffs_base__slice_u8 a_dst, ++ wuffs_base__io_buffer* a_src, ++ uint32_t a_width, ++ uint32_t a_height, ++ wuffs_base__slice_u8 a_tile_data, ++ uint32_t a_tile_size_log2) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ uint32_t v_i = 0; ++ uint32_t v_n = 0; ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_pixels; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ v_i = 0u; ++ v_n = (((uint32_t)(1u)) << self->private_impl.f_color_cache_bits); ++ while (v_i < v_n) { ++ self->private_data.f_color_cache[v_i] = 0u; ++ v_i += 1u; ++ } ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ status = wuffs_webp__decoder__decode_pixels_slow(self, ++ a_dst, ++ a_src, ++ a_width, ++ a_height, ++ a_tile_data, ++ a_tile_size_log2); ++ if (status.repr) { ++ goto suspend; ++ } ++ ++ goto ok; ++ ok: ++ self->private_impl.p_decode_pixels = 0; ++ goto exit; ++ } ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_pixels = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ ++ goto exit; ++ exit: ++ return status; ++} ++ ++// -------- func webp.decoder.swizzle ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_webp__decoder__swizzle( ++ wuffs_webp__decoder* self, ++ wuffs_base__pixel_buffer* a_dst, ++ wuffs_base__slice_u8 a_src, ++ wuffs_base__pixel_blend a_blend) { ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ wuffs_base__pixel_format v_dst_pixfmt = {0}; ++ uint32_t v_dst_bits_per_pixel = 0; ++ uint32_t v_dst_bytes_per_pixel = 0; ++ uint64_t v_dst_bytes_per_row = 0; ++ wuffs_base__slice_u8 v_dst_palette = {0}; ++ wuffs_base__table_u8 v_tab = {0}; ++ uint64_t v_src_bytes_per_row = 0; ++ wuffs_base__slice_u8 v_dst = {0}; ++ uint32_t v_y = 0; ++ ++ v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, ++ wuffs_base__pixel_buffer__pixel_format(a_dst), ++ wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_palette, 1024)), ++ wuffs_base__utility__make_pixel_format(self->private_impl.f_pixfmt), ++ wuffs_base__utility__empty_slice_u8(), ++ a_blend); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ return wuffs_private_impl__status__ensure_not_a_suspension(v_status); ++ } ++ v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); ++ v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); ++ if ((v_dst_bits_per_pixel & 7u) != 0u) { ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); ++ } ++ v_dst_bytes_per_pixel = (v_dst_bits_per_pixel / 8u); ++ v_dst_bytes_per_row = ((uint64_t)((self->private_impl.f_width * v_dst_bytes_per_pixel))); ++ v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_palette, 1024)); ++ v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); ++ v_src_bytes_per_row = ((uint64_t)((self->private_impl.f_width * 4u))); ++ while (v_src_bytes_per_row <= ((uint64_t)(a_src.len))) { ++ v_dst = wuffs_private_impl__table_u8__row_u32(v_tab, v_y); ++ if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) { ++ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row); ++ } ++ wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__slice_u8__subslice_j(a_src, v_src_bytes_per_row)); ++ a_src = wuffs_base__slice_u8__subslice_i(a_src, v_src_bytes_per_row); ++ v_y += 1u; ++ } ++ return wuffs_base__make_status(NULL); ++} ++ ++// -------- func webp.decoder.frame_dirty_rect + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_tga__decoder__frame_dirty_rect( +- const wuffs_tga__decoder* self) { ++wuffs_webp__decoder__frame_dirty_rect( ++ const wuffs_webp__decoder* self) { + if (!self) { + return wuffs_base__utility__empty_rect_ie_u32(); + } +@@ -60275,12 +75319,12 @@ wuffs_tga__decoder__frame_dirty_rect( + self->private_impl.f_height); + } + +-// -------- func tga.decoder.num_animation_loops ++// -------- func webp.decoder.num_animation_loops + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_tga__decoder__num_animation_loops( +- const wuffs_tga__decoder* self) { ++wuffs_webp__decoder__num_animation_loops( ++ const wuffs_webp__decoder* self) { + if (!self) { + return 0; + } +@@ -60292,12 +75336,12 @@ wuffs_tga__decoder__num_animation_loops( + return 0u; + } + +-// -------- func tga.decoder.num_decoded_frame_configs ++// -------- func webp.decoder.num_decoded_frame_configs + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_tga__decoder__num_decoded_frame_configs( +- const wuffs_tga__decoder* self) { ++wuffs_webp__decoder__num_decoded_frame_configs( ++ const wuffs_webp__decoder* self) { + if (!self) { + return 0; + } +@@ -60312,12 +75356,12 @@ wuffs_tga__decoder__num_decoded_frame_configs( + return 0u; + } + +-// -------- func tga.decoder.num_decoded_frames ++// -------- func webp.decoder.num_decoded_frames + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_tga__decoder__num_decoded_frames( +- const wuffs_tga__decoder* self) { ++wuffs_webp__decoder__num_decoded_frames( ++ const wuffs_webp__decoder* self) { + if (!self) { + return 0; + } +@@ -60332,12 +75376,12 @@ wuffs_tga__decoder__num_decoded_frames( + return 0u; + } + +-// -------- func tga.decoder.restart_frame ++// -------- func webp.decoder.restart_frame + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__restart_frame( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__restart_frame( ++ wuffs_webp__decoder* self, + uint64_t a_index, + uint64_t a_io_position) { + if (!self) { +@@ -60353,31 +75397,30 @@ wuffs_tga__decoder__restart_frame( + if (self->private_impl.f_call_sequence < 32u) { + return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); + } +- if (a_index != 0u) { ++ if ((a_index != 0u) || (a_io_position != self->private_impl.f_frame_config_io_position)) { + return wuffs_base__make_status(wuffs_base__error__bad_argument); + } + self->private_impl.f_call_sequence = 40u; +- self->private_impl.f_frame_config_io_position = a_io_position; + return wuffs_base__make_status(NULL); + } + +-// -------- func tga.decoder.set_report_metadata ++// -------- func webp.decoder.set_report_metadata + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_tga__decoder__set_report_metadata( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__set_report_metadata( ++ wuffs_webp__decoder* self, + uint32_t a_fourcc, + bool a_report) { + return wuffs_base__make_empty_struct(); + } + +-// -------- func tga.decoder.tell_me_more ++// -------- func webp.decoder.tell_me_more + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_tga__decoder__tell_me_more( +- wuffs_tga__decoder* self, ++wuffs_webp__decoder__tell_me_more( ++ wuffs_webp__decoder* self, + wuffs_base__io_buffer* a_dst, + wuffs_base__more_information* a_minfo, + wuffs_base__io_buffer* a_src) { +@@ -60415,29 +75458,12 @@ wuffs_tga__decoder__tell_me_more( + return status; + } + +-// -------- func tga.decoder.history_retain_length +- +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_tga__decoder__history_retain_length( +- const wuffs_tga__decoder* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; +- } +- +- return 0u; +-} +- +-// -------- func tga.decoder.workbuf_len ++// -------- func webp.decoder.workbuf_len + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_tga__decoder__workbuf_len( +- const wuffs_tga__decoder* self) { ++wuffs_webp__decoder__workbuf_len( ++ const wuffs_webp__decoder* self) { + if (!self) { + return wuffs_base__utility__empty_range_ii_u64(); + } +@@ -60446,92 +75472,66 @@ wuffs_tga__decoder__workbuf_len( + return wuffs_base__utility__empty_range_ii_u64(); + } + +- return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++ return wuffs_base__utility__make_range_ii_u64(((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[3u])), ((uint64_t)(self->private_impl.f_workbuf_offset_for_transform[3u]))); + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WEBP) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH32) + + // ---------------- Status Codes Implementations + +-const char wuffs_wbmp__error__bad_header[] = "#wbmp: bad header"; +-const char wuffs_wbmp__error__truncated_input[] = "#wbmp: truncated input"; +- + // ---------------- Private Consts + +-// ---------------- Private Initializer Prototypes ++#define WUFFS_XXHASH32__XXH_PRIME32_1 2654435761u + +-// ---------------- Private Function Prototypes ++#define WUFFS_XXHASH32__XXH_PRIME32_2 2246822519u + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_wbmp__decoder__do_decode_image_config( +- wuffs_wbmp__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src); ++#define WUFFS_XXHASH32__XXH_PRIME32_3 3266489917u + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_wbmp__decoder__do_decode_frame_config( +- wuffs_wbmp__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src); ++#define WUFFS_XXHASH32__XXH_PRIME32_4 668265263u ++ ++#define WUFFS_XXHASH32__XXH_PRIME32_5 374761393u ++ ++#define WUFFS_XXHASH32__INITIAL_V0 606290984u ++ ++#define WUFFS_XXHASH32__INITIAL_V1 2246822519u ++ ++#define WUFFS_XXHASH32__INITIAL_V2 0u ++ ++#define WUFFS_XXHASH32__INITIAL_V3 1640531535u ++ ++// ---------------- Private Initializer Prototypes ++ ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_wbmp__decoder__do_decode_frame( +- wuffs_wbmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts); ++static wuffs_base__empty_struct ++wuffs_xxhash32__hasher__up( ++ wuffs_xxhash32__hasher* self, ++ wuffs_base__slice_u8 a_x); + + // ---------------- VTables + +-const wuffs_base__image_decoder__func_ptrs +-wuffs_wbmp__decoder__func_ptrs_for__wuffs_base__image_decoder = { +- (wuffs_base__status(*)(void*, +- wuffs_base__pixel_buffer*, +- wuffs_base__io_buffer*, +- wuffs_base__pixel_blend, +- wuffs_base__slice_u8, +- wuffs_base__decode_frame_options*))(&wuffs_wbmp__decoder__decode_frame), +- (wuffs_base__status(*)(void*, +- wuffs_base__frame_config*, +- wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__decode_frame_config), +- (wuffs_base__status(*)(void*, +- wuffs_base__image_config*, +- wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__decode_image_config), +- (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_wbmp__decoder__frame_dirty_rect), ++const wuffs_base__hasher_u32__func_ptrs ++wuffs_xxhash32__hasher__func_ptrs_for__wuffs_base__hasher_u32 = { ++ (uint32_t(*)(const void*))(&wuffs_xxhash32__hasher__checksum_u32), + (uint64_t(*)(const void*, +- uint32_t))(&wuffs_wbmp__decoder__get_quirk), +- (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__history_retain_length), +- (uint32_t(*)(const void*))(&wuffs_wbmp__decoder__num_animation_loops), +- (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__num_decoded_frame_configs), +- (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__num_decoded_frames), +- (wuffs_base__status(*)(void*, +- uint64_t, +- uint64_t))(&wuffs_wbmp__decoder__restart_frame), ++ uint32_t))(&wuffs_xxhash32__hasher__get_quirk), + (wuffs_base__status(*)(void*, + uint32_t, +- uint64_t))(&wuffs_wbmp__decoder__set_quirk), ++ uint64_t))(&wuffs_xxhash32__hasher__set_quirk), + (wuffs_base__empty_struct(*)(void*, +- uint32_t, +- bool))(&wuffs_wbmp__decoder__set_report_metadata), +- (wuffs_base__status(*)(void*, +- wuffs_base__io_buffer*, +- wuffs_base__more_information*, +- wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__tell_me_more), +- (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_wbmp__decoder__workbuf_len), ++ wuffs_base__slice_u8))(&wuffs_xxhash32__hasher__update), ++ (uint32_t(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_xxhash32__hasher__update_u32), + }; + + // ---------------- Initializer Implementations + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_wbmp__decoder__initialize( +- wuffs_wbmp__decoder* self, ++wuffs_xxhash32__hasher__initialize( ++ wuffs_xxhash32__hasher* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options){ +@@ -60569,22 +75569,22 @@ wuffs_wbmp__decoder__initialize( + } + + self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name = +- wuffs_base__image_decoder__vtable_name; +- self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers = +- (const void*)(&wuffs_wbmp__decoder__func_ptrs_for__wuffs_base__image_decoder); ++ self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name = ++ wuffs_base__hasher_u32__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers = ++ (const void*)(&wuffs_xxhash32__hasher__func_ptrs_for__wuffs_base__hasher_u32); + return wuffs_base__make_status(NULL); + } + +-wuffs_wbmp__decoder* +-wuffs_wbmp__decoder__alloc(void) { +- wuffs_wbmp__decoder* x = +- (wuffs_wbmp__decoder*)(calloc(sizeof(wuffs_wbmp__decoder), 1)); ++wuffs_xxhash32__hasher* ++wuffs_xxhash32__hasher__alloc(void) { ++ wuffs_xxhash32__hasher* x = ++ (wuffs_xxhash32__hasher*)(calloc(1, sizeof(wuffs_xxhash32__hasher))); + if (!x) { + return NULL; + } +- if (wuffs_wbmp__decoder__initialize( +- x, sizeof(wuffs_wbmp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ if (wuffs_xxhash32__hasher__initialize( ++ x, sizeof(wuffs_xxhash32__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { + free(x); + return NULL; + } +@@ -60592,18 +75592,18 @@ wuffs_wbmp__decoder__alloc(void) { + } + + size_t +-sizeof__wuffs_wbmp__decoder(void) { +- return sizeof(wuffs_wbmp__decoder); ++sizeof__wuffs_xxhash32__hasher(void) { ++ return sizeof(wuffs_xxhash32__hasher); + } + + // ---------------- Function Implementations + +-// -------- func wbmp.decoder.get_quirk ++// -------- func xxhash32.hasher.get_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_wbmp__decoder__get_quirk( +- const wuffs_wbmp__decoder* self, ++wuffs_xxhash32__hasher__get_quirk( ++ const wuffs_xxhash32__hasher* self, + uint32_t a_key) { + if (!self) { + return 0; +@@ -60616,12 +75616,12 @@ wuffs_wbmp__decoder__get_quirk( + return 0u; + } + +-// -------- func wbmp.decoder.set_quirk ++// -------- func xxhash32.hasher.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__set_quirk( +- wuffs_wbmp__decoder* self, ++wuffs_xxhash32__hasher__set_quirk( ++ wuffs_xxhash32__hasher* self, + uint32_t a_key, + uint64_t a_value) { + if (!self) { +@@ -60637,627 +75637,387 @@ wuffs_wbmp__decoder__set_quirk( + return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func wbmp.decoder.decode_image_config ++// -------- func xxhash32.hasher.update + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__decode_image_config( +- wuffs_wbmp__decoder* self, +- wuffs_base__image_config* a_dst, +- wuffs_base__io_buffer* a_src) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct ++wuffs_xxhash32__hasher__update( ++ wuffs_xxhash32__hasher* self, ++ wuffs_base__slice_u8 a_x) { + if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ return wuffs_base__make_empty_struct(); + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 1)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_wbmp__decoder__do_decode_image_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_wbmp__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } +- +- ok: +- self->private_impl.p_decode_image_config[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; +- +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_empty_struct(); + } +- return status; +-} +- +-// -------- func wbmp.decoder.do_decode_image_config +- +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_wbmp__decoder__do_decode_image_config( +- wuffs_wbmp__decoder* self, +- wuffs_base__image_config* 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_i = 0; +- uint32_t v_p = 0; +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++ wuffs_base__slice_u8 v_remaining = {0}; + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_image_config[0]; +- if (coro_susp_point) { +- v_i = self->private_data.s_do_decode_image_config[0].v_i; +- v_p = self->private_data.s_do_decode_image_config[0].v_p; ++ if ((self->private_impl.f_length_modulo_u32 == 0u) && ! self->private_impl.f_length_overflows_u32) { ++ self->private_impl.f_v0 = 606290984u; ++ self->private_impl.f_v1 = 2246822519u; ++ self->private_impl.f_v2 = 0u; ++ self->private_impl.f_v3 = 1640531535u; + } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- if (self->private_impl.f_call_sequence != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- goto exit; +- } +- v_i = 0u; +- while (v_i < 2u) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_0 = *iop_a_src++; +- v_c = t_0; +- } +- if (v_c != 0u) { +- status = wuffs_base__make_status(wuffs_wbmp__error__bad_header); +- goto exit; +- } +- v_i += 1u; +- } +- v_i = 0u; +- while (v_i < 2u) { +- v_p = 0u; +- while (true) { +- { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); +- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- goto suspend; +- } +- uint8_t t_1 = *iop_a_src++; +- v_c = t_1; +- } +- v_p |= ((uint32_t)((v_c & 127u))); +- if ((v_c >> 7u) == 0u) { +- break; +- } else if (v_p > 131071u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_image_dimension); +- goto exit; +- } +- v_p <<= 7u; +- } +- if (v_i == 0u) { +- self->private_impl.f_width = v_p; +- } else { +- self->private_impl.f_height = v_p; +- } +- v_i += 1u; +- } +- self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))); +- if (a_dst != NULL) { +- wuffs_base__image_config__set( +- a_dst, +- 2198077448u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height, +- self->private_impl.f_frame_config_io_position, +- true); ++ while (((uint64_t)(a_x.len)) > 0u) { ++ v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0u); ++ if (((uint64_t)(a_x.len)) > 16777216u) { ++ v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 16777216u); ++ a_x = wuffs_base__slice_u8__subslice_j(a_x, 16777216u); + } +- self->private_impl.f_call_sequence = 32u; +- +- goto ok; +- ok: +- self->private_impl.p_do_decode_image_config[0] = 0; +- goto exit; +- } +- +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_decode_image_config[0].v_i = v_i; +- self->private_data.s_do_decode_image_config[0].v_p = v_p; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ wuffs_xxhash32__hasher__up(self, a_x); ++ a_x = v_remaining; + } +- +- return status; ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func wbmp.decoder.decode_frame_config ++// -------- func xxhash32.hasher.update_u32 + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__decode_frame_config( +- wuffs_wbmp__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_xxhash32__hasher__update_u32( ++ wuffs_xxhash32__hasher* self, ++ wuffs_base__slice_u8 a_x) { + if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ return 0; + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 2)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); +- } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; +- +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_wbmp__decoder__do_decode_frame_config(self, a_dst, a_src); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_wbmp__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } +- +- ok: +- self->private_impl.p_decode_frame_config[0] = 0; +- goto exit; ++ return 0; + } + +- goto suspend; +- suspend: +- self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0; +- +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; ++ wuffs_xxhash32__hasher__update(self, a_x); ++ return wuffs_xxhash32__hasher__checksum_u32(self); + } + +-// -------- func wbmp.decoder.do_decode_frame_config ++// -------- func xxhash32.hasher.up + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_wbmp__decoder__do_decode_frame_config( +- wuffs_wbmp__decoder* self, +- wuffs_base__frame_config* a_dst, +- wuffs_base__io_buffer* a_src) { +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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_do_decode_frame_config[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++static wuffs_base__empty_struct ++wuffs_xxhash32__hasher__up( ++ wuffs_xxhash32__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint32_t v_new_lmu = 0; ++ uint32_t v_buf_u32 = 0; ++ uint32_t v_buf_len = 0; ++ uint32_t v_v0 = 0; ++ uint32_t v_v1 = 0; ++ uint32_t v_v2 = 0; ++ uint32_t v_v3 = 0; ++ wuffs_base__slice_u8 v_p = {0}; + +- if (self->private_impl.f_call_sequence == 32u) { +- } else if (self->private_impl.f_call_sequence < 32u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_wbmp__decoder__do_decode_image_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } else if (self->private_impl.f_call_sequence == 40u) { +- if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) { +- status = wuffs_base__make_status(wuffs_base__error__bad_restart); +- goto exit; +- } +- } else if (self->private_impl.f_call_sequence == 64u) { +- self->private_impl.f_call_sequence = 96u; +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; ++ v_new_lmu = ((uint32_t)(self->private_impl.f_length_modulo_u32 + ((uint32_t)(((uint64_t)(a_x.len)))))); ++ self->private_impl.f_length_overflows_u32 = ((v_new_lmu < self->private_impl.f_length_modulo_u32) || self->private_impl.f_length_overflows_u32); ++ self->private_impl.f_length_modulo_u32 = v_new_lmu; ++ while (true) { ++ if (self->private_impl.f_buf_len >= 16u) { ++ v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[0u])) | ++ (((uint32_t)(self->private_impl.f_buf_data[1u])) << 8u) | ++ (((uint32_t)(self->private_impl.f_buf_data[2u])) << 16u) | ++ (((uint32_t)(self->private_impl.f_buf_data[3u])) << 24u)); ++ v_v0 = ((uint32_t)(self->private_impl.f_v0 + ((uint32_t)(v_buf_u32 * 2246822519u)))); ++ v_v0 = (((uint32_t)(v_v0 << 13u)) | (v_v0 >> 19u)); ++ self->private_impl.f_v0 = ((uint32_t)(v_v0 * 2654435761u)); ++ v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[4u])) | ++ (((uint32_t)(self->private_impl.f_buf_data[5u])) << 8u) | ++ (((uint32_t)(self->private_impl.f_buf_data[6u])) << 16u) | ++ (((uint32_t)(self->private_impl.f_buf_data[7u])) << 24u)); ++ v_v1 = ((uint32_t)(self->private_impl.f_v1 + ((uint32_t)(v_buf_u32 * 2246822519u)))); ++ v_v1 = (((uint32_t)(v_v1 << 13u)) | (v_v1 >> 19u)); ++ self->private_impl.f_v1 = ((uint32_t)(v_v1 * 2654435761u)); ++ v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[8u])) | ++ (((uint32_t)(self->private_impl.f_buf_data[9u])) << 8u) | ++ (((uint32_t)(self->private_impl.f_buf_data[10u])) << 16u) | ++ (((uint32_t)(self->private_impl.f_buf_data[11u])) << 24u)); ++ v_v2 = ((uint32_t)(self->private_impl.f_v2 + ((uint32_t)(v_buf_u32 * 2246822519u)))); ++ v_v2 = (((uint32_t)(v_v2 << 13u)) | (v_v2 >> 19u)); ++ self->private_impl.f_v2 = ((uint32_t)(v_v2 * 2654435761u)); ++ v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[12u])) | ++ (((uint32_t)(self->private_impl.f_buf_data[13u])) << 8u) | ++ (((uint32_t)(self->private_impl.f_buf_data[14u])) << 16u) | ++ (((uint32_t)(self->private_impl.f_buf_data[15u])) << 24u)); ++ v_v3 = ((uint32_t)(self->private_impl.f_v3 + ((uint32_t)(v_buf_u32 * 2246822519u)))); ++ v_v3 = (((uint32_t)(v_v3 << 13u)) | (v_v3 >> 19u)); ++ self->private_impl.f_v3 = ((uint32_t)(v_v3 * 2654435761u)); ++ self->private_impl.f_buf_len = 0u; ++ break; + } +- if (a_dst != NULL) { +- wuffs_base__frame_config__set( +- a_dst, +- wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height), +- ((wuffs_base__flicks)(0u)), +- 0u, +- self->private_impl.f_frame_config_io_position, +- 0u, +- true, +- false, +- 4278190080u); ++ if (((uint64_t)(a_x.len)) <= 0u) { ++ return wuffs_base__make_empty_struct(); + } +- self->private_impl.f_call_sequence = 64u; +- +- ok: +- self->private_impl.p_do_decode_frame_config[0] = 0; +- goto exit; ++ self->private_impl.f_buf_data[self->private_impl.f_buf_len] = a_x.ptr[0u]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ self->private_impl.f_buf_len += 1u; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); + } +- +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ v_buf_len = ((uint32_t)(((uint8_t)(self->private_impl.f_buf_len & 15u)))); ++ v_v0 = self->private_impl.f_v0; ++ v_v1 = self->private_impl.f_v1; ++ v_v2 = self->private_impl.f_v2; ++ v_v3 = self->private_impl.f_v3; ++ { ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 16; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 16) * 16)); ++ while (v_p.ptr < i_end0_p) { ++ v_buf_u32 = (((uint32_t)(v_p.ptr[0u])) | ++ (((uint32_t)(v_p.ptr[1u])) << 8u) | ++ (((uint32_t)(v_p.ptr[2u])) << 16u) | ++ (((uint32_t)(v_p.ptr[3u])) << 24u)); ++ v_v0 = ((uint32_t)(v_v0 + ((uint32_t)(v_buf_u32 * 2246822519u)))); ++ v_v0 = (((uint32_t)(v_v0 << 13u)) | (v_v0 >> 19u)); ++ v_v0 = ((uint32_t)(v_v0 * 2654435761u)); ++ v_buf_u32 = (((uint32_t)(v_p.ptr[4u])) | ++ (((uint32_t)(v_p.ptr[5u])) << 8u) | ++ (((uint32_t)(v_p.ptr[6u])) << 16u) | ++ (((uint32_t)(v_p.ptr[7u])) << 24u)); ++ v_v1 = ((uint32_t)(v_v1 + ((uint32_t)(v_buf_u32 * 2246822519u)))); ++ v_v1 = (((uint32_t)(v_v1 << 13u)) | (v_v1 >> 19u)); ++ v_v1 = ((uint32_t)(v_v1 * 2654435761u)); ++ v_buf_u32 = (((uint32_t)(v_p.ptr[8u])) | ++ (((uint32_t)(v_p.ptr[9u])) << 8u) | ++ (((uint32_t)(v_p.ptr[10u])) << 16u) | ++ (((uint32_t)(v_p.ptr[11u])) << 24u)); ++ v_v2 = ((uint32_t)(v_v2 + ((uint32_t)(v_buf_u32 * 2246822519u)))); ++ v_v2 = (((uint32_t)(v_v2 << 13u)) | (v_v2 >> 19u)); ++ v_v2 = ((uint32_t)(v_v2 * 2654435761u)); ++ v_buf_u32 = (((uint32_t)(v_p.ptr[12u])) | ++ (((uint32_t)(v_p.ptr[13u])) << 8u) | ++ (((uint32_t)(v_p.ptr[14u])) << 16u) | ++ (((uint32_t)(v_p.ptr[15u])) << 24u)); ++ v_v3 = ((uint32_t)(v_v3 + ((uint32_t)(v_buf_u32 * 2246822519u)))); ++ v_v3 = (((uint32_t)(v_v3 << 13u)) | (v_v3 >> 19u)); ++ v_v3 = ((uint32_t)(v_v3 * 2654435761u)); ++ v_p.ptr += 16; ++ } ++ v_p.len = 1; ++ const uint8_t* i_end1_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end1_p) { ++ self->private_impl.f_buf_data[v_buf_len] = v_p.ptr[0u]; ++ v_buf_len = ((v_buf_len + 1u) & 15u); ++ v_p.ptr += 1; ++ } ++ v_p.len = 0; + } +- +- return status; ++ self->private_impl.f_buf_len = ((uint8_t)(v_buf_len)); ++ self->private_impl.f_v0 = v_v0; ++ self->private_impl.f_v1 = v_v1; ++ self->private_impl.f_v2 = v_v2; ++ self->private_impl.f_v3 = v_v3; ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func wbmp.decoder.decode_frame ++// -------- func xxhash32.hasher.checksum_u32 + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__decode_frame( +- wuffs_wbmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { ++WUFFS_BASE__MAYBE_STATIC uint32_t ++wuffs_xxhash32__hasher__checksum_u32( ++ const wuffs_xxhash32__hasher* self) { + if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ return 0; + } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return 0; ++ } ++ ++ uint32_t v_ret = 0; ++ uint32_t v_i = 0; ++ uint32_t v_n = 0; ++ uint32_t v_buf_u32 = 0; ++ ++ if ((self->private_impl.f_length_modulo_u32 >= 16u) || self->private_impl.f_length_overflows_u32) { ++ v_ret += (((uint32_t)(self->private_impl.f_v0 << 1u)) | (self->private_impl.f_v0 >> 31u)); ++ v_ret += (((uint32_t)(self->private_impl.f_v1 << 7u)) | (self->private_impl.f_v1 >> 25u)); ++ v_ret += (((uint32_t)(self->private_impl.f_v2 << 12u)) | (self->private_impl.f_v2 >> 20u)); ++ v_ret += (((uint32_t)(self->private_impl.f_v3 << 18u)) | (self->private_impl.f_v3 >> 14u)); ++ v_ret += self->private_impl.f_length_modulo_u32; ++ } else { ++ v_ret += 374761393u; ++ v_ret += self->private_impl.f_length_modulo_u32; ++ } ++ v_n = 16u; ++ v_n = wuffs_base__u32__min(v_n, ((uint32_t)(self->private_impl.f_buf_len))); ++ if (4u <= v_n) { ++ v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[0u])) | ++ (((uint32_t)(self->private_impl.f_buf_data[1u])) << 8u) | ++ (((uint32_t)(self->private_impl.f_buf_data[2u])) << 16u) | ++ (((uint32_t)(self->private_impl.f_buf_data[3u])) << 24u)); ++ v_ret += ((uint32_t)(v_buf_u32 * 3266489917u)); ++ v_ret = (((uint32_t)(v_ret << 17u)) | (v_ret >> 15u)); ++ v_ret *= 668265263u; ++ v_i = 4u; ++ } ++ if (8u <= v_n) { ++ v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[4u])) | ++ (((uint32_t)(self->private_impl.f_buf_data[5u])) << 8u) | ++ (((uint32_t)(self->private_impl.f_buf_data[6u])) << 16u) | ++ (((uint32_t)(self->private_impl.f_buf_data[7u])) << 24u)); ++ v_ret += ((uint32_t)(v_buf_u32 * 3266489917u)); ++ v_ret = (((uint32_t)(v_ret << 17u)) | (v_ret >> 15u)); ++ v_ret *= 668265263u; ++ v_i = 8u; + } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ if (12u <= v_n) { ++ v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[8u])) | ++ (((uint32_t)(self->private_impl.f_buf_data[9u])) << 8u) | ++ (((uint32_t)(self->private_impl.f_buf_data[10u])) << 16u) | ++ (((uint32_t)(self->private_impl.f_buf_data[11u])) << 24u)); ++ v_ret += ((uint32_t)(v_buf_u32 * 3266489917u)); ++ v_ret = (((uint32_t)(v_ret << 17u)) | (v_ret >> 15u)); ++ v_ret *= 668265263u; ++ v_i = 12u; + } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 3)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ while (v_i < v_n) { ++ v_ret += ((uint32_t)(((uint32_t)(self->private_impl.f_buf_data[v_i])) * 374761393u)); ++ v_ret = (((uint32_t)(v_ret << 11u)) | (v_ret >> 21u)); ++ v_ret *= 2654435761u; ++ v_i += 1u; + } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); +- +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- +- uint32_t coro_susp_point = self->private_impl.p_decode_frame[0]; +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ v_ret ^= (v_ret >> 15u); ++ v_ret *= 2246822519u; ++ v_ret ^= (v_ret >> 13u); ++ v_ret *= 3266489917u; ++ v_ret ^= (v_ret >> 16u); ++ return v_ret; ++} + +- while (true) { +- { +- wuffs_base__status t_0 = wuffs_wbmp__decoder__do_decode_frame(self, +- a_dst, +- a_src, +- a_blend, +- a_workbuf, +- a_opts); +- v_status = t_0; +- } +- if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { +- status = wuffs_base__make_status(wuffs_wbmp__error__truncated_input); +- goto exit; +- } +- status = v_status; +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); +- } ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH32) + +- ok: +- self->private_impl.p_decode_frame[0] = 0; +- goto exit; +- } ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH64) + +- goto suspend; +- suspend: +- self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0; ++// ---------------- Status Codes Implementations + +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- } +- return status; +-} ++// ---------------- Private Consts + +-// -------- func wbmp.decoder.do_decode_frame ++#define WUFFS_XXHASH64__XXH_PRIME64_1 11400714785074694791u + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__status +-wuffs_wbmp__decoder__do_decode_frame( +- wuffs_wbmp__decoder* self, +- wuffs_base__pixel_buffer* a_dst, +- wuffs_base__io_buffer* a_src, +- wuffs_base__pixel_blend a_blend, +- wuffs_base__slice_u8 a_workbuf, +- wuffs_base__decode_frame_options* a_opts) { +- wuffs_base__status status = wuffs_base__make_status(NULL); ++#define WUFFS_XXHASH64__XXH_PRIME64_2 14029467366897019727u + +- wuffs_base__status v_status = wuffs_base__make_status(NULL); +- wuffs_base__pixel_format v_dst_pixfmt = {0}; +- uint32_t v_dst_bits_per_pixel = 0; +- uint64_t v_dst_bytes_per_pixel = 0; +- uint64_t v_dst_x_in_bytes = 0; +- uint32_t v_dst_x = 0; +- uint32_t v_dst_y = 0; +- wuffs_base__table_u8 v_tab = {0}; +- wuffs_base__slice_u8 v_dst = {0}; +- uint8_t v_src[1] = {0}; +- uint8_t v_c = 0; ++#define WUFFS_XXHASH64__XXH_PRIME64_3 1609587929392839161u + +- const uint8_t* iop_a_src = NULL; +- const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; +- if (a_src && a_src->data.ptr) { +- 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; +- } ++#define WUFFS_XXHASH64__XXH_PRIME64_4 9650029242287828579u + +- uint32_t coro_susp_point = self->private_impl.p_do_decode_frame[0]; +- if (coro_susp_point) { +- v_dst_bytes_per_pixel = self->private_data.s_do_decode_frame[0].v_dst_bytes_per_pixel; +- v_dst_x = self->private_data.s_do_decode_frame[0].v_dst_x; +- v_dst_y = self->private_data.s_do_decode_frame[0].v_dst_y; +- memcpy(v_src, self->private_data.s_do_decode_frame[0].v_src, sizeof(v_src)); +- v_c = self->private_data.s_do_decode_frame[0].v_c; +- } +- switch (coro_susp_point) { +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++#define WUFFS_XXHASH64__XXH_PRIME64_5 2870177450012600261u + +- if (self->private_impl.f_call_sequence == 64u) { +- } else if (self->private_impl.f_call_sequence < 64u) { +- if (a_src) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); +- status = wuffs_wbmp__decoder__do_decode_frame_config(self, NULL, a_src); +- if (a_src) { +- iop_a_src = a_src->data.ptr + a_src->meta.ri; +- } +- if (status.repr) { +- goto suspend; +- } +- } else { +- status = wuffs_base__make_status(wuffs_base__note__end_of_data); +- goto ok; +- } +- v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler, +- wuffs_base__pixel_buffer__pixel_format(a_dst), +- wuffs_base__pixel_buffer__palette(a_dst), +- wuffs_base__utility__make_pixel_format(536870920u), +- wuffs_base__utility__empty_slice_u8(), +- a_blend); +- if ( ! wuffs_base__status__is_ok(&v_status)) { +- status = v_status; +- if (wuffs_base__status__is_error(&status)) { +- goto exit; +- } else if (wuffs_base__status__is_suspension(&status)) { +- status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension); +- goto exit; +- } +- goto ok; +- } +- v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst); +- v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt); +- if ((v_dst_bits_per_pixel & 7u) != 0u) { +- status = wuffs_base__make_status(wuffs_base__error__unsupported_option); +- goto exit; +- } +- v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8u))); +- if (self->private_impl.f_width > 0u) { +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- while (v_dst_y < self->private_impl.f_height) { +- v_dst = wuffs_base__table_u8__row_u32(v_tab, v_dst_y); +- v_dst_x = 0u; +- while (v_dst_x < self->private_impl.f_width) { +- if ((v_dst_x & 7u) == 0u) { +- while (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { +- status = wuffs_base__make_status(wuffs_base__suspension__short_read); +- WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); +- v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0u); +- v_dst = wuffs_base__table_u8__row_u32(v_tab, v_dst_y); +- v_dst_x_in_bytes = (((uint64_t)(v_dst_x)) * v_dst_bytes_per_pixel); +- if (v_dst_x_in_bytes <= ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_x_in_bytes); +- } +- } +- v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src); +- iop_a_src += 1u; +- } +- if ((v_c & 128u) == 0u) { +- v_src[0u] = 0u; +- } else { +- v_src[0u] = 255u; +- } +- v_c = ((uint8_t)((((uint32_t)(v_c)) << 1u))); +- wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, wuffs_base__utility__empty_slice_u8(), wuffs_base__make_slice_u8(v_src, 1)); +- if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) { +- v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel); +- } +- v_dst_x += 1u; +- } +- v_dst_y += 1u; +- } +- } +- self->private_impl.f_call_sequence = 96u; ++#define WUFFS_XXHASH64__INITIAL_V0 6983438078262162902u + +- ok: +- self->private_impl.p_do_decode_frame[0] = 0; +- goto exit; +- } ++#define WUFFS_XXHASH64__INITIAL_V1 14029467366897019727u + +- goto suspend; +- suspend: +- self->private_impl.p_do_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; +- self->private_data.s_do_decode_frame[0].v_dst_bytes_per_pixel = v_dst_bytes_per_pixel; +- self->private_data.s_do_decode_frame[0].v_dst_x = v_dst_x; +- self->private_data.s_do_decode_frame[0].v_dst_y = v_dst_y; +- memcpy(self->private_data.s_do_decode_frame[0].v_src, v_src, sizeof(v_src)); +- self->private_data.s_do_decode_frame[0].v_c = v_c; ++#define WUFFS_XXHASH64__INITIAL_V2 0u + +- goto exit; +- exit: +- if (a_src && a_src->data.ptr) { +- a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); +- } ++#define WUFFS_XXHASH64__INITIAL_V3 7046029288634856825u + +- return status; +-} ++// ---------------- Private Initializer Prototypes + +-// -------- func wbmp.decoder.frame_dirty_rect ++// ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 +-wuffs_wbmp__decoder__frame_dirty_rect( +- const wuffs_wbmp__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_rect_ie_u32(); +- } ++static wuffs_base__empty_struct ++wuffs_xxhash64__hasher__up( ++ wuffs_xxhash64__hasher* self, ++ wuffs_base__slice_u8 a_x); + +- return wuffs_base__utility__make_rect_ie_u32( +- 0u, +- 0u, +- self->private_impl.f_width, +- self->private_impl.f_height); +-} ++// ---------------- VTables + +-// -------- func wbmp.decoder.num_animation_loops ++const wuffs_base__hasher_u64__func_ptrs ++wuffs_xxhash64__hasher__func_ptrs_for__wuffs_base__hasher_u64 = { ++ (uint64_t(*)(const void*))(&wuffs_xxhash64__hasher__checksum_u64), ++ (uint64_t(*)(const void*, ++ uint32_t))(&wuffs_xxhash64__hasher__get_quirk), ++ (wuffs_base__status(*)(void*, ++ uint32_t, ++ uint64_t))(&wuffs_xxhash64__hasher__set_quirk), ++ (wuffs_base__empty_struct(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_xxhash64__hasher__update), ++ (uint64_t(*)(void*, ++ wuffs_base__slice_u8))(&wuffs_xxhash64__hasher__update_u64), ++}; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_wbmp__decoder__num_animation_loops( +- const wuffs_wbmp__decoder* self) { ++// ---------------- Initializer Implementations ++ ++wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT ++wuffs_xxhash64__hasher__initialize( ++ wuffs_xxhash64__hasher* self, ++ size_t sizeof_star_self, ++ uint64_t wuffs_version, ++ uint32_t options){ + if (!self) { +- return 0; ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ if (sizeof(*self) != sizeof_star_self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ } ++ if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || ++ (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { ++ return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); + } + +- return 0u; +-} ++ if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { ++ // The whole point of this if-check is to detect an uninitialized *self. ++ // We disable the warning on GCC. Clang-5.0 does not have this warning. ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" ++#endif ++ if (self->private_impl.magic != 0) { ++ return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ } ++#if !defined(__clang__) && defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ } else { ++ if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { ++ memset(self, 0, sizeof(*self)); ++ options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ } else { ++ memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ } ++ } + +-// -------- func wbmp.decoder.num_decoded_frame_configs ++ self->private_impl.magic = WUFFS_BASE__MAGIC; ++ self->private_impl.vtable_for__wuffs_base__hasher_u64.vtable_name = ++ wuffs_base__hasher_u64__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__hasher_u64.function_pointers = ++ (const void*)(&wuffs_xxhash64__hasher__func_ptrs_for__wuffs_base__hasher_u64); ++ return wuffs_base__make_status(NULL); ++} + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_wbmp__decoder__num_decoded_frame_configs( +- const wuffs_wbmp__decoder* self) { +- if (!self) { +- return 0; ++wuffs_xxhash64__hasher* ++wuffs_xxhash64__hasher__alloc(void) { ++ wuffs_xxhash64__hasher* x = ++ (wuffs_xxhash64__hasher*)(calloc(1, sizeof(wuffs_xxhash64__hasher))); ++ if (!x) { ++ return NULL; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ if (wuffs_xxhash64__hasher__initialize( ++ x, sizeof(wuffs_xxhash64__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ free(x); ++ return NULL; + } ++ return x; ++} + +- if (self->private_impl.f_call_sequence > 32u) { +- return 1u; +- } +- return 0u; ++size_t ++sizeof__wuffs_xxhash64__hasher(void) { ++ return sizeof(wuffs_xxhash64__hasher); + } + +-// -------- func wbmp.decoder.num_decoded_frames ++// ---------------- Function Implementations ++ ++// -------- func xxhash64.hasher.get_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_wbmp__decoder__num_decoded_frames( +- const wuffs_wbmp__decoder* self) { ++wuffs_xxhash64__hasher__get_quirk( ++ const wuffs_xxhash64__hasher* self, ++ uint32_t a_key) { + if (!self) { + return 0; + } +@@ -61266,20 +76026,17 @@ wuffs_wbmp__decoder__num_decoded_frames( + return 0; + } + +- if (self->private_impl.f_call_sequence > 64u) { +- return 1u; +- } + return 0u; + } + +-// -------- func wbmp.decoder.restart_frame ++// -------- func xxhash64.hasher.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__restart_frame( +- wuffs_wbmp__decoder* self, +- uint64_t a_index, +- uint64_t a_io_position) { ++wuffs_xxhash64__hasher__set_quirk( ++ wuffs_xxhash64__hasher* self, ++ uint32_t a_key, ++ uint64_t a_value) { + if (!self) { + return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } +@@ -61290,77 +76047,206 @@ wuffs_wbmp__decoder__restart_frame( + : wuffs_base__error__initialize_not_called); + } + +- if (self->private_impl.f_call_sequence < 32u) { +- return wuffs_base__make_status(wuffs_base__error__bad_call_sequence); +- } +- if (a_index != 0u) { +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- self->private_impl.f_call_sequence = 40u; +- self->private_impl.f_frame_config_io_position = a_io_position; +- return wuffs_base__make_status(NULL); ++ return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func wbmp.decoder.set_report_metadata ++// -------- func xxhash64.hasher.update + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_wbmp__decoder__set_report_metadata( +- wuffs_wbmp__decoder* self, +- uint32_t a_fourcc, +- bool a_report) { ++wuffs_xxhash64__hasher__update( ++ wuffs_xxhash64__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ if (!self) { ++ return wuffs_base__make_empty_struct(); ++ } ++ if (self->private_impl.magic != WUFFS_BASE__MAGIC) { ++ return wuffs_base__make_empty_struct(); ++ } ++ ++ if ((self->private_impl.f_length_modulo_u64 == 0u) && ! self->private_impl.f_length_overflows_u64) { ++ self->private_impl.f_v0 = 6983438078262162902u; ++ self->private_impl.f_v1 = 14029467366897019727u; ++ self->private_impl.f_v2 = 0u; ++ self->private_impl.f_v3 = 7046029288634856825u; ++ } ++ wuffs_xxhash64__hasher__up(self, a_x); + return wuffs_base__make_empty_struct(); + } + +-// -------- func wbmp.decoder.tell_me_more ++// -------- func xxhash64.hasher.update_u64 + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_wbmp__decoder__tell_me_more( +- wuffs_wbmp__decoder* self, +- wuffs_base__io_buffer* a_dst, +- wuffs_base__more_information* a_minfo, +- wuffs_base__io_buffer* a_src) { ++WUFFS_BASE__MAYBE_STATIC uint64_t ++wuffs_xxhash64__hasher__update_u64( ++ wuffs_xxhash64__hasher* self, ++ wuffs_base__slice_u8 a_x) { + if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); ++ return 0; + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- if (!a_dst || !a_src) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__bad_argument); +- } +- if ((self->private_impl.active_coroutine != 0) && +- (self->private_impl.active_coroutine != 4)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; +- return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ return 0; + } +- self->private_impl.active_coroutine = 0; +- wuffs_base__status status = wuffs_base__make_status(NULL); + +- status = wuffs_base__make_status(wuffs_base__error__no_more_information); +- goto exit; ++ wuffs_xxhash64__hasher__update(self, a_x); ++ return wuffs_xxhash64__hasher__checksum_u64(self); ++} + +- goto ok; +- ok: +- goto exit; +- exit: +- if (wuffs_base__status__is_error(&status)) { +- self->private_impl.magic = WUFFS_BASE__DISABLED; ++// -------- func xxhash64.hasher.up ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__empty_struct ++wuffs_xxhash64__hasher__up( ++ wuffs_xxhash64__hasher* self, ++ wuffs_base__slice_u8 a_x) { ++ uint64_t v_new_lmu = 0; ++ uint64_t v_buf_u64 = 0; ++ uint32_t v_buf_len = 0; ++ uint64_t v_v0 = 0; ++ uint64_t v_v1 = 0; ++ uint64_t v_v2 = 0; ++ uint64_t v_v3 = 0; ++ wuffs_base__slice_u8 v_p = {0}; ++ ++ v_new_lmu = ((uint64_t)(self->private_impl.f_length_modulo_u64 + ((uint64_t)(a_x.len)))); ++ self->private_impl.f_length_overflows_u64 = ((v_new_lmu < self->private_impl.f_length_modulo_u64) || self->private_impl.f_length_overflows_u64); ++ self->private_impl.f_length_modulo_u64 = v_new_lmu; ++ while (true) { ++ if (self->private_impl.f_buf_len >= 32u) { ++ v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[0u])) | ++ (((uint64_t)(self->private_impl.f_buf_data[1u])) << 8u) | ++ (((uint64_t)(self->private_impl.f_buf_data[2u])) << 16u) | ++ (((uint64_t)(self->private_impl.f_buf_data[3u])) << 24u) | ++ (((uint64_t)(self->private_impl.f_buf_data[4u])) << 32u) | ++ (((uint64_t)(self->private_impl.f_buf_data[5u])) << 40u) | ++ (((uint64_t)(self->private_impl.f_buf_data[6u])) << 48u) | ++ (((uint64_t)(self->private_impl.f_buf_data[7u])) << 56u)); ++ v_v0 = ((uint64_t)(self->private_impl.f_v0 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); ++ v_v0 = (((uint64_t)(v_v0 << 31u)) | (v_v0 >> 33u)); ++ self->private_impl.f_v0 = ((uint64_t)(v_v0 * 11400714785074694791u)); ++ v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[8u])) | ++ (((uint64_t)(self->private_impl.f_buf_data[9u])) << 8u) | ++ (((uint64_t)(self->private_impl.f_buf_data[10u])) << 16u) | ++ (((uint64_t)(self->private_impl.f_buf_data[11u])) << 24u) | ++ (((uint64_t)(self->private_impl.f_buf_data[12u])) << 32u) | ++ (((uint64_t)(self->private_impl.f_buf_data[13u])) << 40u) | ++ (((uint64_t)(self->private_impl.f_buf_data[14u])) << 48u) | ++ (((uint64_t)(self->private_impl.f_buf_data[15u])) << 56u)); ++ v_v1 = ((uint64_t)(self->private_impl.f_v1 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); ++ v_v1 = (((uint64_t)(v_v1 << 31u)) | (v_v1 >> 33u)); ++ self->private_impl.f_v1 = ((uint64_t)(v_v1 * 11400714785074694791u)); ++ v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[16u])) | ++ (((uint64_t)(self->private_impl.f_buf_data[17u])) << 8u) | ++ (((uint64_t)(self->private_impl.f_buf_data[18u])) << 16u) | ++ (((uint64_t)(self->private_impl.f_buf_data[19u])) << 24u) | ++ (((uint64_t)(self->private_impl.f_buf_data[20u])) << 32u) | ++ (((uint64_t)(self->private_impl.f_buf_data[21u])) << 40u) | ++ (((uint64_t)(self->private_impl.f_buf_data[22u])) << 48u) | ++ (((uint64_t)(self->private_impl.f_buf_data[23u])) << 56u)); ++ v_v2 = ((uint64_t)(self->private_impl.f_v2 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); ++ v_v2 = (((uint64_t)(v_v2 << 31u)) | (v_v2 >> 33u)); ++ self->private_impl.f_v2 = ((uint64_t)(v_v2 * 11400714785074694791u)); ++ v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[24u])) | ++ (((uint64_t)(self->private_impl.f_buf_data[25u])) << 8u) | ++ (((uint64_t)(self->private_impl.f_buf_data[26u])) << 16u) | ++ (((uint64_t)(self->private_impl.f_buf_data[27u])) << 24u) | ++ (((uint64_t)(self->private_impl.f_buf_data[28u])) << 32u) | ++ (((uint64_t)(self->private_impl.f_buf_data[29u])) << 40u) | ++ (((uint64_t)(self->private_impl.f_buf_data[30u])) << 48u) | ++ (((uint64_t)(self->private_impl.f_buf_data[31u])) << 56u)); ++ v_v3 = ((uint64_t)(self->private_impl.f_v3 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); ++ v_v3 = (((uint64_t)(v_v3 << 31u)) | (v_v3 >> 33u)); ++ self->private_impl.f_v3 = ((uint64_t)(v_v3 * 11400714785074694791u)); ++ self->private_impl.f_buf_len = 0u; ++ break; ++ } ++ if (((uint64_t)(a_x.len)) <= 0u) { ++ return wuffs_base__make_empty_struct(); ++ } ++ self->private_impl.f_buf_data[self->private_impl.f_buf_len] = a_x.ptr[0u]; ++ self->private_impl.f_buf_len += 1u; ++ a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); ++ } ++ v_buf_len = (self->private_impl.f_buf_len & 31u); ++ v_v0 = self->private_impl.f_v0; ++ v_v1 = self->private_impl.f_v1; ++ v_v2 = self->private_impl.f_v2; ++ v_v3 = self->private_impl.f_v3; ++ { ++ wuffs_base__slice_u8 i_slice_p = a_x; ++ v_p.ptr = i_slice_p.ptr; ++ v_p.len = 32; ++ const uint8_t* i_end0_p = wuffs_private_impl__ptr_u8_plus_len(v_p.ptr, (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32)); ++ while (v_p.ptr < i_end0_p) { ++ v_buf_u64 = (((uint64_t)(v_p.ptr[0u])) | ++ (((uint64_t)(v_p.ptr[1u])) << 8u) | ++ (((uint64_t)(v_p.ptr[2u])) << 16u) | ++ (((uint64_t)(v_p.ptr[3u])) << 24u) | ++ (((uint64_t)(v_p.ptr[4u])) << 32u) | ++ (((uint64_t)(v_p.ptr[5u])) << 40u) | ++ (((uint64_t)(v_p.ptr[6u])) << 48u) | ++ (((uint64_t)(v_p.ptr[7u])) << 56u)); ++ v_v0 = ((uint64_t)(v_v0 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); ++ v_v0 = (((uint64_t)(v_v0 << 31u)) | (v_v0 >> 33u)); ++ v_v0 = ((uint64_t)(v_v0 * 11400714785074694791u)); ++ v_buf_u64 = (((uint64_t)(v_p.ptr[8u])) | ++ (((uint64_t)(v_p.ptr[9u])) << 8u) | ++ (((uint64_t)(v_p.ptr[10u])) << 16u) | ++ (((uint64_t)(v_p.ptr[11u])) << 24u) | ++ (((uint64_t)(v_p.ptr[12u])) << 32u) | ++ (((uint64_t)(v_p.ptr[13u])) << 40u) | ++ (((uint64_t)(v_p.ptr[14u])) << 48u) | ++ (((uint64_t)(v_p.ptr[15u])) << 56u)); ++ v_v1 = ((uint64_t)(v_v1 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); ++ v_v1 = (((uint64_t)(v_v1 << 31u)) | (v_v1 >> 33u)); ++ v_v1 = ((uint64_t)(v_v1 * 11400714785074694791u)); ++ v_buf_u64 = (((uint64_t)(v_p.ptr[16u])) | ++ (((uint64_t)(v_p.ptr[17u])) << 8u) | ++ (((uint64_t)(v_p.ptr[18u])) << 16u) | ++ (((uint64_t)(v_p.ptr[19u])) << 24u) | ++ (((uint64_t)(v_p.ptr[20u])) << 32u) | ++ (((uint64_t)(v_p.ptr[21u])) << 40u) | ++ (((uint64_t)(v_p.ptr[22u])) << 48u) | ++ (((uint64_t)(v_p.ptr[23u])) << 56u)); ++ v_v2 = ((uint64_t)(v_v2 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); ++ v_v2 = (((uint64_t)(v_v2 << 31u)) | (v_v2 >> 33u)); ++ v_v2 = ((uint64_t)(v_v2 * 11400714785074694791u)); ++ v_buf_u64 = (((uint64_t)(v_p.ptr[24u])) | ++ (((uint64_t)(v_p.ptr[25u])) << 8u) | ++ (((uint64_t)(v_p.ptr[26u])) << 16u) | ++ (((uint64_t)(v_p.ptr[27u])) << 24u) | ++ (((uint64_t)(v_p.ptr[28u])) << 32u) | ++ (((uint64_t)(v_p.ptr[29u])) << 40u) | ++ (((uint64_t)(v_p.ptr[30u])) << 48u) | ++ (((uint64_t)(v_p.ptr[31u])) << 56u)); ++ v_v3 = ((uint64_t)(v_v3 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); ++ v_v3 = (((uint64_t)(v_v3 << 31u)) | (v_v3 >> 33u)); ++ v_v3 = ((uint64_t)(v_v3 * 11400714785074694791u)); ++ v_p.ptr += 32; ++ } ++ v_p.len = 1; ++ const uint8_t* i_end1_p = wuffs_private_impl__ptr_u8_plus_len(i_slice_p.ptr, i_slice_p.len); ++ while (v_p.ptr < i_end1_p) { ++ self->private_impl.f_buf_data[v_buf_len] = v_p.ptr[0u]; ++ v_buf_len = ((v_buf_len + 1u) & 31u); ++ v_p.ptr += 1; ++ } ++ v_p.len = 0; + } +- return status; ++ self->private_impl.f_buf_len = v_buf_len; ++ self->private_impl.f_v0 = v_v0; ++ self->private_impl.f_v1 = v_v1; ++ self->private_impl.f_v2 = v_v2; ++ self->private_impl.f_v3 = v_v3; ++ return wuffs_base__make_empty_struct(); + } + +-// -------- func wbmp.decoder.history_retain_length ++// -------- func xxhash64.hasher.checksum_u64 + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_wbmp__decoder__history_retain_length( +- const wuffs_wbmp__decoder* self) { ++wuffs_xxhash64__hasher__checksum_u64( ++ const wuffs_xxhash64__hasher* self) { + if (!self) { + return 0; + } +@@ -61369,83 +76255,307 @@ wuffs_wbmp__decoder__history_retain_length( + return 0; + } + +- return 0u; +-} +- +-// -------- func wbmp.decoder.workbuf_len ++ uint64_t v_ret = 0; ++ uint64_t v_v0 = 0; ++ uint64_t v_v1 = 0; ++ uint64_t v_v2 = 0; ++ uint64_t v_v3 = 0; ++ uint32_t v_i = 0; ++ uint32_t v_i8 = 0; ++ uint32_t v_n = 0; ++ uint32_t v_buf_u32 = 0; ++ uint64_t v_buf_u64 = 0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 +-wuffs_wbmp__decoder__workbuf_len( +- const wuffs_wbmp__decoder* self) { +- if (!self) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ if ((self->private_impl.f_length_modulo_u64 >= 32u) || self->private_impl.f_length_overflows_u64) { ++ v_ret += (((uint64_t)(self->private_impl.f_v0 << 1u)) | (self->private_impl.f_v0 >> 63u)); ++ v_ret += (((uint64_t)(self->private_impl.f_v1 << 7u)) | (self->private_impl.f_v1 >> 57u)); ++ v_ret += (((uint64_t)(self->private_impl.f_v2 << 12u)) | (self->private_impl.f_v2 >> 52u)); ++ v_ret += (((uint64_t)(self->private_impl.f_v3 << 18u)) | (self->private_impl.f_v3 >> 46u)); ++ v_v0 = ((uint64_t)(self->private_impl.f_v0 * 14029467366897019727u)); ++ v_v0 = (((uint64_t)(v_v0 << 31u)) | (v_v0 >> 33u)); ++ v_v0 *= 11400714785074694791u; ++ v_v1 = ((uint64_t)(self->private_impl.f_v1 * 14029467366897019727u)); ++ v_v1 = (((uint64_t)(v_v1 << 31u)) | (v_v1 >> 33u)); ++ v_v1 *= 11400714785074694791u; ++ v_v2 = ((uint64_t)(self->private_impl.f_v2 * 14029467366897019727u)); ++ v_v2 = (((uint64_t)(v_v2 << 31u)) | (v_v2 >> 33u)); ++ v_v2 *= 11400714785074694791u; ++ v_v3 = ((uint64_t)(self->private_impl.f_v3 * 14029467366897019727u)); ++ v_v3 = (((uint64_t)(v_v3 << 31u)) | (v_v3 >> 33u)); ++ v_v3 *= 11400714785074694791u; ++ v_ret = ((uint64_t)(((uint64_t)((v_ret ^ v_v0) * 11400714785074694791u)) + 9650029242287828579u)); ++ v_ret = ((uint64_t)(((uint64_t)((v_ret ^ v_v1) * 11400714785074694791u)) + 9650029242287828579u)); ++ v_ret = ((uint64_t)(((uint64_t)((v_ret ^ v_v2) * 11400714785074694791u)) + 9650029242287828579u)); ++ v_ret = ((uint64_t)(((uint64_t)((v_ret ^ v_v3) * 11400714785074694791u)) + 9650029242287828579u)); ++ v_ret += self->private_impl.f_length_modulo_u64; ++ } else { ++ v_ret += 2870177450012600261u; ++ v_ret += self->private_impl.f_length_modulo_u64; + } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return wuffs_base__utility__empty_range_ii_u64(); ++ v_n = 32u; ++ v_n = wuffs_base__u32__min(v_n, self->private_impl.f_buf_len); ++ if (8u <= v_n) { ++ v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[0u])) | ++ (((uint64_t)(self->private_impl.f_buf_data[1u])) << 8u) | ++ (((uint64_t)(self->private_impl.f_buf_data[2u])) << 16u) | ++ (((uint64_t)(self->private_impl.f_buf_data[3u])) << 24u) | ++ (((uint64_t)(self->private_impl.f_buf_data[4u])) << 32u) | ++ (((uint64_t)(self->private_impl.f_buf_data[5u])) << 40u) | ++ (((uint64_t)(self->private_impl.f_buf_data[6u])) << 48u) | ++ (((uint64_t)(self->private_impl.f_buf_data[7u])) << 56u)); ++ v_buf_u64 *= 14029467366897019727u; ++ v_buf_u64 = (((uint64_t)(v_buf_u64 << 31u)) | (v_buf_u64 >> 33u)); ++ v_buf_u64 *= 11400714785074694791u; ++ v_ret ^= v_buf_u64; ++ v_ret = (((uint64_t)(v_ret << 27u)) | (v_ret >> 37u)); ++ v_ret *= 11400714785074694791u; ++ v_ret += 9650029242287828579u; ++ v_i = 8u; + } +- +- return wuffs_base__utility__make_range_ii_u64(0u, 0u); ++ if (16u <= v_n) { ++ v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[8u])) | ++ (((uint64_t)(self->private_impl.f_buf_data[9u])) << 8u) | ++ (((uint64_t)(self->private_impl.f_buf_data[10u])) << 16u) | ++ (((uint64_t)(self->private_impl.f_buf_data[11u])) << 24u) | ++ (((uint64_t)(self->private_impl.f_buf_data[12u])) << 32u) | ++ (((uint64_t)(self->private_impl.f_buf_data[13u])) << 40u) | ++ (((uint64_t)(self->private_impl.f_buf_data[14u])) << 48u) | ++ (((uint64_t)(self->private_impl.f_buf_data[15u])) << 56u)); ++ v_buf_u64 *= 14029467366897019727u; ++ v_buf_u64 = (((uint64_t)(v_buf_u64 << 31u)) | (v_buf_u64 >> 33u)); ++ v_buf_u64 *= 11400714785074694791u; ++ v_ret ^= v_buf_u64; ++ v_ret = (((uint64_t)(v_ret << 27u)) | (v_ret >> 37u)); ++ v_ret *= 11400714785074694791u; ++ v_ret += 9650029242287828579u; ++ v_i = 16u; ++ } ++ if (24u <= v_n) { ++ v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[16u])) | ++ (((uint64_t)(self->private_impl.f_buf_data[17u])) << 8u) | ++ (((uint64_t)(self->private_impl.f_buf_data[18u])) << 16u) | ++ (((uint64_t)(self->private_impl.f_buf_data[19u])) << 24u) | ++ (((uint64_t)(self->private_impl.f_buf_data[20u])) << 32u) | ++ (((uint64_t)(self->private_impl.f_buf_data[21u])) << 40u) | ++ (((uint64_t)(self->private_impl.f_buf_data[22u])) << 48u) | ++ (((uint64_t)(self->private_impl.f_buf_data[23u])) << 56u)); ++ v_buf_u64 *= 14029467366897019727u; ++ v_buf_u64 = (((uint64_t)(v_buf_u64 << 31u)) | (v_buf_u64 >> 33u)); ++ v_buf_u64 *= 11400714785074694791u; ++ v_ret ^= v_buf_u64; ++ v_ret = (((uint64_t)(v_ret << 27u)) | (v_ret >> 37u)); ++ v_ret *= 11400714785074694791u; ++ v_ret += 9650029242287828579u; ++ v_i = 24u; ++ } ++ if ((v_n & 4u) != 0u) { ++ v_i8 = (v_i & 24u); ++ v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[(v_i8 + 0u)])) | ++ (((uint32_t)(self->private_impl.f_buf_data[(v_i8 + 1u)])) << 8u) | ++ (((uint32_t)(self->private_impl.f_buf_data[(v_i8 + 2u)])) << 16u) | ++ (((uint32_t)(self->private_impl.f_buf_data[(v_i8 + 3u)])) << 24u)); ++ v_ret ^= ((uint64_t)(((uint64_t)(v_buf_u32)) * 11400714785074694791u)); ++ v_ret = (((uint64_t)(v_ret << 23u)) | (v_ret >> 41u)); ++ v_ret *= 14029467366897019727u; ++ v_ret += 1609587929392839161u; ++ v_i = (v_i8 + 4u); ++ } ++ while (v_i < v_n) { ++ v_ret ^= ((uint64_t)(((uint64_t)(self->private_impl.f_buf_data[v_i])) * 2870177450012600261u)); ++ v_ret = (((uint64_t)(v_ret << 11u)) | (v_ret >> 53u)); ++ v_ret *= 11400714785074694791u; ++ v_i += 1u; ++ } ++ v_ret ^= (v_ret >> 33u); ++ v_ret *= 14029467366897019727u; ++ v_ret ^= (v_ret >> 29u); ++ v_ret *= 1609587929392839161u; ++ v_ret ^= (v_ret >> 32u); ++ return ((uint64_t)(v_ret)); + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH64) + +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH32) ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XZ) + + // ---------------- Status Codes Implementations + +-// ---------------- Private Consts ++const char wuffs_xz__error__bad_bcj_offset[] = "#xz: bad BCJ offset"; ++const char wuffs_xz__error__bad_block_header[] = "#xz: bad block header"; ++const char wuffs_xz__error__bad_checksum[] = "#xz: bad checksum"; ++const char wuffs_xz__error__bad_filter[] = "#xz: bad filter"; ++const char wuffs_xz__error__bad_footer[] = "#xz: bad footer"; ++const char wuffs_xz__error__bad_header[] = "#xz: bad header"; ++const char wuffs_xz__error__bad_header_concatenated_stream[] = "#xz: bad header (concatenated stream)"; ++const char wuffs_xz__error__bad_index[] = "#xz: bad index"; ++const char wuffs_xz__error__bad_padding[] = "#xz: bad padding"; ++const char wuffs_xz__error__truncated_input[] = "#xz: truncated input"; ++const char wuffs_xz__error__unsupported_checksum_algorithm[] = "#xz: unsupported checksum algorithm"; ++const char wuffs_xz__error__unsupported_filter[] = "#xz: unsupported filter"; ++const char wuffs_xz__error__unsupported_filter_combination[] = "#xz: unsupported filter combination"; ++const char wuffs_xz__error__internal_error_inconsistent_bcj_filter_state[] = "#xz: internal error: inconsistent BCJ filter state"; + +-#define WUFFS_XXHASH32__XXH_PRIME32_1 2654435761 ++// ---------------- Private Consts + +-#define WUFFS_XXHASH32__XXH_PRIME32_2 2246822519 ++static const bool ++WUFFS_XZ__FILTER_04_X86_MASK_TO_ALLOWED_STATUS[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 1u, 1u, 1u, 0u, 1u, 0u, 0u, 0u, ++}; + +-#define WUFFS_XXHASH32__XXH_PRIME32_3 3266489917 ++static const uint8_t ++WUFFS_XZ__FILTER_04_X86_MASK_TO_BIT_NUM[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 1u, 2u, 2u, 3u, 3u, 3u, 3u, ++}; + +-#define WUFFS_XXHASH32__XXH_PRIME32_4 668265263 ++static const uint32_t ++WUFFS_XZ__FILTER_04_X86_MASK_TO_XOR_OPERAND[8] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 4294967295u, 16777215u, 65535u, 65535u, 255u, 255u, 255u, 255u, ++}; + +-#define WUFFS_XXHASH32__XXH_PRIME32_5 374761393 ++static const uint8_t ++WUFFS_XZ__FILTER_06_IA64_BRANCH_TABLE[32] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, ++ 4u, 4u, 6u, 6u, 0u, 0u, 7u, 7u, ++ 4u, 4u, 0u, 0u, 4u, 4u, 0u, 0u, ++}; + +-#define WUFFS_XXHASH32__INITIAL_V0 606290984 ++#define WUFFS_XZ__QUIRKS_BASE 2021322752u + +-#define WUFFS_XXHASH32__INITIAL_V1 2246822519 ++static const uint8_t ++WUFFS_XZ__CHECKSUM_LENGTH[4] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 4u, 8u, 32u, ++}; + +-#define WUFFS_XXHASH32__INITIAL_V2 0 ++static const uint8_t ++WUFFS_XZ__ZEROES[3] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 0u, ++}; + +-#define WUFFS_XXHASH32__INITIAL_V3 1640531535 ++static const uint8_t ++WUFFS_XZ__BCJ_OFFSET_ALIGNMENT[12] WUFFS_BASE__POTENTIALLY_UNUSED = { ++ 0u, 0u, 0u, 0u, 1u, 4u, 16u, 4u, ++ 2u, 4u, 4u, 2u, ++}; + + // ---------------- Private Initializer Prototypes + + // ---------------- Private Function Prototypes + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_xxhash32__hasher__up( +- wuffs_xxhash32__hasher* self, +- wuffs_base__slice_u8 a_x); ++static uint8_t ++wuffs_xz__decoder__apply_non_final_filters( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_non_final_filters__choosy_default( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_04_x86( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_05_powerpc( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_06_ia64( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_07_arm( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_08_armthumb( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_09_sparc( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_0a_arm64( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_0b_riscv( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_xz__decoder__do_transform_io( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_xz__decoder__decode_block_header_with_padding( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_xz__decoder__decode_block_header_sans_padding( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_xz__decoder__verify_index( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_src); ++ ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_xz__decoder__verify_footer( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_src); + + // ---------------- VTables + +-const wuffs_base__hasher_u32__func_ptrs +-wuffs_xxhash32__hasher__func_ptrs_for__wuffs_base__hasher_u32 = { +- (uint32_t(*)(const void*))(&wuffs_xxhash32__hasher__checksum_u32), ++const wuffs_base__io_transformer__func_ptrs ++wuffs_xz__decoder__func_ptrs_for__wuffs_base__io_transformer = { ++ (wuffs_base__optional_u63(*)(const void*))(&wuffs_xz__decoder__dst_history_retain_length), + (uint64_t(*)(const void*, +- uint32_t))(&wuffs_xxhash32__hasher__get_quirk), ++ uint32_t))(&wuffs_xz__decoder__get_quirk), + (wuffs_base__status(*)(void*, + uint32_t, +- uint64_t))(&wuffs_xxhash32__hasher__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- wuffs_base__slice_u8))(&wuffs_xxhash32__hasher__update), +- (uint32_t(*)(void*, +- wuffs_base__slice_u8))(&wuffs_xxhash32__hasher__update_u32), ++ uint64_t))(&wuffs_xz__decoder__set_quirk), ++ (wuffs_base__status(*)(void*, ++ wuffs_base__io_buffer*, ++ wuffs_base__io_buffer*, ++ wuffs_base__slice_u8))(&wuffs_xz__decoder__transform_io), ++ (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_xz__decoder__workbuf_len), + }; + + // ---------------- Initializer Implementations + + wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_xxhash32__hasher__initialize( +- wuffs_xxhash32__hasher* self, ++wuffs_xz__decoder__initialize( ++ wuffs_xz__decoder* self, + size_t sizeof_star_self, + uint64_t wuffs_version, + uint32_t options){ +@@ -61482,23 +76592,53 @@ wuffs_xxhash32__hasher__initialize( + } + } + ++ self->private_impl.choosy_apply_non_final_filters = &wuffs_xz__decoder__apply_non_final_filters__choosy_default; ++ ++ { ++ wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize( ++ &self->private_data.f_crc32, sizeof(self->private_data.f_crc32), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ { ++ wuffs_base__status z = wuffs_crc64__ecma_hasher__initialize( ++ &self->private_data.f_crc64, sizeof(self->private_data.f_crc64), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ { ++ wuffs_base__status z = wuffs_sha256__hasher__initialize( ++ &self->private_data.f_sha256, sizeof(self->private_data.f_sha256), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } ++ { ++ wuffs_base__status z = wuffs_lzma__decoder__initialize( ++ &self->private_data.f_lzma, sizeof(self->private_data.f_lzma), WUFFS_VERSION, options); ++ if (z.repr) { ++ return z; ++ } ++ } + self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name = +- wuffs_base__hasher_u32__vtable_name; +- self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers = +- (const void*)(&wuffs_xxhash32__hasher__func_ptrs_for__wuffs_base__hasher_u32); ++ self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name = ++ wuffs_base__io_transformer__vtable_name; ++ self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers = ++ (const void*)(&wuffs_xz__decoder__func_ptrs_for__wuffs_base__io_transformer); + return wuffs_base__make_status(NULL); + } + +-wuffs_xxhash32__hasher* +-wuffs_xxhash32__hasher__alloc(void) { +- wuffs_xxhash32__hasher* x = +- (wuffs_xxhash32__hasher*)(calloc(sizeof(wuffs_xxhash32__hasher), 1)); ++wuffs_xz__decoder* ++wuffs_xz__decoder__alloc(void) { ++ wuffs_xz__decoder* x = ++ (wuffs_xz__decoder*)(calloc(1, sizeof(wuffs_xz__decoder))); + if (!x) { + return NULL; + } +- if (wuffs_xxhash32__hasher__initialize( +- x, sizeof(wuffs_xxhash32__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { ++ if (wuffs_xz__decoder__initialize( ++ x, sizeof(wuffs_xz__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { + free(x); + return NULL; + } +@@ -61506,18 +76646,511 @@ wuffs_xxhash32__hasher__alloc(void) { + } + + size_t +-sizeof__wuffs_xxhash32__hasher(void) { +- return sizeof(wuffs_xxhash32__hasher); ++sizeof__wuffs_xz__decoder(void) { ++ return sizeof(wuffs_xz__decoder); + } + + // ---------------- Function Implementations + +-// -------- func xxhash32.hasher.get_quirk ++// -------- func xz.decoder.apply_non_final_filters ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_non_final_filters( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ return (*self->private_impl.choosy_apply_non_final_filters)(self, a_dst_slice); ++} ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_non_final_filters__choosy_default( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ uint32_t v_f = 0; ++ uint64_t v_i = 0; ++ uint32_t v_filter_id = 0; ++ uint32_t v_delta_dist = 0; ++ uint32_t v_delta_pos = 0; ++ uint8_t v_c8 = 0; ++ ++ if (self->private_impl.f_num_non_final_filters <= 0u) { ++ return 0u; ++ } ++ v_f = (self->private_impl.f_num_non_final_filters - 1u); ++ while (true) { ++ v_filter_id = (self->private_impl.f_filters[v_f] & 127u); ++ if (v_filter_id == 3u) { ++ v_delta_dist = (((self->private_impl.f_filters[v_f] >> 8u) & 255u) + 1u); ++ v_delta_pos = (self->private_impl.f_filters[v_f] >> 24u); ++ v_i = 0u; ++ while (v_i < ((uint64_t)(a_dst_slice.len))) { ++ v_c8 = a_dst_slice.ptr[v_i]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#endif ++ v_c8 += self->private_data.f_filter_data[v_f][(((uint32_t)(v_delta_dist + v_delta_pos)) & 255u)]; ++#if defined(__GNUC__) ++#pragma GCC diagnostic pop ++#endif ++ self->private_data.f_filter_data[v_f][(v_delta_pos & 255u)] = v_c8; ++ v_delta_pos -= 1u; ++ a_dst_slice.ptr[v_i] = v_c8; ++ v_i += 1u; ++ } ++ self->private_impl.f_filters[v_f] &= 65535u; ++ self->private_impl.f_filters[v_f] |= ((uint32_t)(v_delta_pos << 24u)); ++ } ++ if (v_f <= 0u) { ++ break; ++ } ++ v_f -= 1u; ++ } ++ return 0u; ++} ++ ++// -------- func xz.decoder.apply_filter_04_x86 ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_04_x86( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ wuffs_base__slice_u8 v_s = {0}; ++ uint32_t v_p = 0; ++ uint64_t v_i = 0; ++ uint64_t v_prev_pos = 0; ++ uint32_t v_prev_mask = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_src = 0; ++ uint32_t v_dst = 0; ++ uint32_t v_bit_num = 0; ++ ++ v_s = a_dst_slice; ++ v_p = ((uint32_t)(self->private_impl.f_bcj_pos + 5u)); ++ v_prev_pos = 18446744073709551615u; ++ v_prev_mask = self->private_impl.f_bcj_x86_prev_mask; ++ while (((uint64_t)(v_s.len)) >= 5u) { ++ if (((uint8_t)(v_s.ptr[0u] & 254u)) != 232u) { ++ v_i += 1u; ++ v_p += 1u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 1u); ++ continue; ++ } ++ v_prev_pos = ((uint64_t)(v_i - v_prev_pos)); ++ if (v_prev_pos > 3u) { ++ v_prev_mask = 0u; ++ } else if (v_prev_pos > 0u) { ++ v_prev_mask = (((uint32_t)(v_prev_mask << (v_prev_pos - 1u))) & 7u); ++ if (v_prev_mask != 0u) { ++ v_c8 = v_s.ptr[((uint8_t)(4u - WUFFS_XZ__FILTER_04_X86_MASK_TO_BIT_NUM[(v_prev_mask & 7u)]))]; ++ if ( ! WUFFS_XZ__FILTER_04_X86_MASK_TO_ALLOWED_STATUS[(v_prev_mask & 7u)] || (v_c8 == 0u) || (v_c8 == 255u)) { ++ v_prev_pos = v_i; ++ v_prev_mask = (((uint32_t)(v_prev_mask << 1u)) | 1u); ++ v_i += 1u; ++ v_p += 1u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 1u); ++ continue; ++ } ++ } ++ } ++ v_prev_pos = v_i; ++ v_c8 = v_s.ptr[4u]; ++ if ((v_c8 != 0u) && (v_c8 != 255u)) { ++ v_prev_mask = (((uint32_t)(v_prev_mask << 1u)) | 1u); ++ v_i += 1u; ++ v_p += 1u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 1u); ++ continue; ++ } ++ v_src = ((((uint32_t)(v_s.ptr[1u])) << 0u) | ++ (((uint32_t)(v_s.ptr[2u])) << 8u) | ++ (((uint32_t)(v_s.ptr[3u])) << 16u) | ++ (((uint32_t)(v_s.ptr[4u])) << 24u)); ++ while (true) { ++ v_dst = ((uint32_t)(v_src - v_p)); ++ if (v_prev_mask == 0u) { ++ break; ++ } ++ v_bit_num = ((uint32_t)(WUFFS_XZ__FILTER_04_X86_MASK_TO_BIT_NUM[(v_prev_mask & 7u)])); ++ v_c8 = ((uint8_t)((v_dst >> (24u - (v_bit_num * 8u))))); ++ if ((v_c8 != 0u) && (v_c8 != 255u)) { ++ break; ++ } ++ v_src = (v_dst ^ WUFFS_XZ__FILTER_04_X86_MASK_TO_XOR_OPERAND[(v_prev_mask & 7u)]); ++ } ++ v_dst &= 33554431u; ++ v_dst |= ((uint32_t)(0u - (v_dst & 16777216u))); ++ v_s.ptr[1u] = ((uint8_t)((v_dst >> 0u))); ++ v_s.ptr[2u] = ((uint8_t)((v_dst >> 8u))); ++ v_s.ptr[3u] = ((uint8_t)((v_dst >> 16u))); ++ v_s.ptr[4u] = ((uint8_t)((v_dst >> 24u))); ++ v_i += 5u; ++ v_p += 5u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 5u); ++ } ++ v_prev_pos = ((uint64_t)(v_i - v_prev_pos)); ++ if (v_prev_pos > 3u) { ++ self->private_impl.f_bcj_x86_prev_mask = 0u; ++ } else if (v_prev_pos > 0u) { ++ self->private_impl.f_bcj_x86_prev_mask = ((uint32_t)(v_prev_mask << (v_prev_pos - 1u))); ++ } ++ self->private_impl.f_bcj_pos = ((uint32_t)(v_p - 5u)); ++ return ((uint8_t)(((uint64_t)(v_s.len)))); ++} ++ ++// -------- func xz.decoder.apply_filter_05_powerpc ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_05_powerpc( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ wuffs_base__slice_u8 v_s = {0}; ++ uint32_t v_p = 0; ++ uint32_t v_x = 0; ++ ++ v_s = a_dst_slice; ++ v_p = self->private_impl.f_bcj_pos; ++ while (((uint64_t)(v_s.len)) >= 4u) { ++ v_x = ((((uint32_t)(v_s.ptr[0u])) << 24u) | ++ (((uint32_t)(v_s.ptr[1u])) << 16u) | ++ (((uint32_t)(v_s.ptr[2u])) << 8u) | ++ (((uint32_t)(v_s.ptr[3u])) << 0u)); ++ if ((v_x & 4227858435u) == 1207959553u) { ++ v_x = ((((uint32_t)((v_x & 67108860u) - v_p)) & 67108860u) | 1207959553u); ++ v_s.ptr[0u] = ((uint8_t)((v_x >> 24u))); ++ v_s.ptr[1u] = ((uint8_t)((v_x >> 16u))); ++ v_s.ptr[2u] = ((uint8_t)((v_x >> 8u))); ++ v_s.ptr[3u] = ((uint8_t)((v_x >> 0u))); ++ } ++ v_p += 4u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ } ++ self->private_impl.f_bcj_pos = v_p; ++ return ((uint8_t)(((uint64_t)(v_s.len)))); ++} ++ ++// -------- func xz.decoder.apply_filter_06_ia64 ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_06_ia64( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ wuffs_base__slice_u8 v_s = {0}; ++ uint32_t v_p = 0; ++ uint32_t v_mask = 0; ++ uint32_t v_slot = 0; ++ uint32_t v_bit_pos = 0; ++ uint32_t v_byte_pos = 0; ++ uint32_t v_bit_res = 0; ++ uint64_t v_x = 0; ++ uint32_t v_j = 0; ++ uint64_t v_norm = 0; ++ uint32_t v_addr = 0; ++ ++ v_s = a_dst_slice; ++ v_p = self->private_impl.f_bcj_pos; ++ while (((uint64_t)(v_s.len)) >= 16u) { ++ v_mask = ((uint32_t)(WUFFS_XZ__FILTER_06_IA64_BRANCH_TABLE[((uint8_t)(v_s.ptr[0u] & 31u))])); ++ v_slot = 0u; ++ while (true) { ++ do { ++ if (((v_mask >> v_slot) & 1u) == 0u) { ++ break; ++ } ++ v_bit_pos = ((v_slot * 41u) + 5u); ++ v_byte_pos = (v_bit_pos >> 3u); ++ v_bit_res = (v_bit_pos & 7u); ++ v_x = 0u; ++ v_j = 0u; ++ while (v_j < 6u) { ++ v_x |= (((uint64_t)(v_s.ptr[(v_j + v_byte_pos)])) << (8u * v_j)); ++ v_j += 1u; ++ } ++ v_norm = (v_x >> v_bit_res); ++ if ((((v_norm >> 37u) & 15u) != 5u) || (((v_norm >> 9u) & 7u) != 0u)) { ++ break; ++ } ++ v_addr = ((uint32_t)(((v_norm >> 13u) & 1048575u))); ++ v_addr |= (((uint32_t)(((v_norm >> 36u) & 1u))) << 20u); ++ v_addr <<= 4u; ++ v_addr -= v_p; ++ v_addr >>= 4u; ++ v_norm &= 18446743996400148479u; ++ v_norm |= (((uint64_t)((v_addr & 1048575u))) << 13u); ++ v_norm |= (((uint64_t)((v_addr & 1048576u))) << 16u); ++ v_x &= ((((uint64_t)(1u)) << v_bit_res) - 1u); ++ v_x |= ((uint64_t)(v_norm << v_bit_res)); ++ v_j = 0u; ++ while (v_j < 6u) { ++ v_s.ptr[(v_j + v_byte_pos)] = ((uint8_t)((v_x >> (8u * v_j)))); ++ v_j += 1u; ++ } ++ } while (0); ++ if (v_slot >= 2u) { ++ break; ++ } ++ v_slot += 1u; ++ } ++ v_p += 16u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 16u); ++ } ++ self->private_impl.f_bcj_pos = v_p; ++ return ((uint8_t)(((uint64_t)(v_s.len)))); ++} ++ ++// -------- func xz.decoder.apply_filter_07_arm ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_07_arm( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ wuffs_base__slice_u8 v_s = {0}; ++ uint32_t v_p = 0; ++ uint32_t v_x = 0; ++ ++ v_s = a_dst_slice; ++ v_p = ((uint32_t)(self->private_impl.f_bcj_pos + 8u)); ++ while (((uint64_t)(v_s.len)) >= 4u) { ++ if (v_s.ptr[3u] == 235u) { ++ v_x = ((((uint32_t)(v_s.ptr[0u])) << 0u) | ++ (((uint32_t)(v_s.ptr[1u])) << 8u) | ++ (((uint32_t)(v_s.ptr[2u])) << 16u) | ++ (((uint32_t)(v_s.ptr[3u])) << 24u)); ++ v_x = (((uint32_t)(((v_x & 16777215u) << 2u) - v_p)) >> 2u); ++ v_s.ptr[0u] = ((uint8_t)((v_x >> 0u))); ++ v_s.ptr[1u] = ((uint8_t)((v_x >> 8u))); ++ v_s.ptr[2u] = ((uint8_t)((v_x >> 16u))); ++ } ++ v_p += 4u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ } ++ self->private_impl.f_bcj_pos = ((uint32_t)(v_p - 8u)); ++ return ((uint8_t)(((uint64_t)(v_s.len)))); ++} ++ ++// -------- func xz.decoder.apply_filter_08_armthumb ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_08_armthumb( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ wuffs_base__slice_u8 v_s = {0}; ++ uint32_t v_p = 0; ++ uint32_t v_x = 0; ++ uint32_t v_y = 0; ++ ++ v_s = a_dst_slice; ++ v_p = ((uint32_t)(self->private_impl.f_bcj_pos + 4u)); ++ while (((uint64_t)(v_s.len)) >= 4u) { ++ v_x = ((((uint32_t)(v_s.ptr[0u])) << 0u) | ++ (((uint32_t)(v_s.ptr[1u])) << 8u) | ++ (((uint32_t)(v_s.ptr[2u])) << 16u) | ++ (((uint32_t)(v_s.ptr[3u])) << 24u)); ++ if ((v_x & 4160813056u) != 4160811008u) { ++ v_p += 2u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 2u); ++ continue; ++ } ++ v_y = ((((uint32_t)(((uint8_t)(v_s.ptr[0u] & 255u)))) << 11u) | ++ (((uint32_t)(((uint8_t)(v_s.ptr[1u] & 7u)))) << 19u) | ++ (((uint32_t)(((uint8_t)(v_s.ptr[2u] & 255u)))) << 0u) | ++ (((uint32_t)(((uint8_t)(v_s.ptr[3u] & 7u)))) << 8u)); ++ v_y = (((uint32_t)(((uint32_t)(v_y << 1u)) - v_p)) >> 1u); ++ v_s.ptr[0u] = ((uint8_t)((v_y >> 11u))); ++ v_s.ptr[1u] = ((uint8_t)((((v_y >> 19u) & 7u) | 240u))); ++ v_s.ptr[2u] = ((uint8_t)((v_y >> 0u))); ++ v_s.ptr[3u] = ((uint8_t)((((v_y >> 8u) & 7u) | 248u))); ++ v_p += 4u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ } ++ self->private_impl.f_bcj_pos = ((uint32_t)(v_p - 4u)); ++ return ((uint8_t)(((uint64_t)(v_s.len)))); ++} ++ ++// -------- func xz.decoder.apply_filter_09_sparc ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_09_sparc( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ wuffs_base__slice_u8 v_s = {0}; ++ uint32_t v_p = 0; ++ uint32_t v_x = 0; ++ ++ v_s = a_dst_slice; ++ v_p = self->private_impl.f_bcj_pos; ++ while (((uint64_t)(v_s.len)) >= 4u) { ++ v_x = ((((uint32_t)(v_s.ptr[0u])) << 24u) | ++ (((uint32_t)(v_s.ptr[1u])) << 16u) | ++ (((uint32_t)(v_s.ptr[2u])) << 8u) | ++ (((uint32_t)(v_s.ptr[3u])) << 0u)); ++ if (((v_x >> 22u) == 256u) || ((v_x >> 22u) == 511u)) { ++ v_x = (((uint32_t)(((uint32_t)(v_x << 2u)) - v_p)) >> 2u); ++ v_x = ((1073741824u - (v_x & 4194304u)) | 1073741824u | (v_x & 4194303u)); ++ v_s.ptr[0u] = ((uint8_t)((v_x >> 24u))); ++ v_s.ptr[1u] = ((uint8_t)((v_x >> 16u))); ++ v_s.ptr[2u] = ((uint8_t)((v_x >> 8u))); ++ v_s.ptr[3u] = ((uint8_t)((v_x >> 0u))); ++ } ++ v_p += 4u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ } ++ self->private_impl.f_bcj_pos = v_p; ++ return ((uint8_t)(((uint64_t)(v_s.len)))); ++} ++ ++// -------- func xz.decoder.apply_filter_0a_arm64 ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_0a_arm64( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ wuffs_base__slice_u8 v_s = {0}; ++ uint32_t v_p = 0; ++ uint32_t v_x = 0; ++ uint32_t v_y = 0; ++ ++ v_s = a_dst_slice; ++ v_p = self->private_impl.f_bcj_pos; ++ while (((uint64_t)(v_s.len)) >= 4u) { ++ v_x = ((((uint32_t)(v_s.ptr[0u])) << 0u) | ++ (((uint32_t)(v_s.ptr[1u])) << 8u) | ++ (((uint32_t)(v_s.ptr[2u])) << 16u) | ++ (((uint32_t)(v_s.ptr[3u])) << 24u)); ++ if ((v_x >> 26u) == 37u) { ++ v_y = ((uint32_t)(v_x - (v_p >> 2u))); ++ v_x = (2483027968u | (v_y & 67108863u)); ++ v_s.ptr[0u] = ((uint8_t)((v_x >> 0u))); ++ v_s.ptr[1u] = ((uint8_t)((v_x >> 8u))); ++ v_s.ptr[2u] = ((uint8_t)((v_x >> 16u))); ++ v_s.ptr[3u] = ((uint8_t)((v_x >> 24u))); ++ } else if ((v_x & 2667577344u) == 2415919104u) { ++ v_y = (((v_x >> 29u) & 3u) | ((v_x >> 3u) & 2097148u)); ++ if ((((uint32_t)(v_y + 131072u)) & 1835008u) == 0u) { ++ v_y -= (v_p >> 12u); ++ v_x &= 2415919135u; ++ v_x |= ((v_y & 3u) << 29u); ++ v_x |= ((v_y & 262140u) << 3u); ++ v_x |= (((uint32_t)(0u - (v_y & 131072u))) & 14680064u); ++ v_s.ptr[0u] = ((uint8_t)((v_x >> 0u))); ++ v_s.ptr[1u] = ((uint8_t)((v_x >> 8u))); ++ v_s.ptr[2u] = ((uint8_t)((v_x >> 16u))); ++ v_s.ptr[3u] = ((uint8_t)((v_x >> 24u))); ++ } ++ } ++ v_p += 4u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ } ++ self->private_impl.f_bcj_pos = v_p; ++ return ((uint8_t)(((uint64_t)(v_s.len)))); ++} ++ ++// -------- func xz.decoder.apply_filter_0b_riscv ++ ++WUFFS_BASE__GENERATED_C_CODE ++static uint8_t ++wuffs_xz__decoder__apply_filter_0b_riscv( ++ wuffs_xz__decoder* self, ++ wuffs_base__slice_u8 a_dst_slice) { ++ wuffs_base__slice_u8 v_s = {0}; ++ uint32_t v_p = 0; ++ uint32_t v_x = 0; ++ uint32_t v_x27 = 0; ++ uint32_t v_y = 0; ++ uint32_t v_addr = 0; ++ ++ v_s = a_dst_slice; ++ v_p = self->private_impl.f_bcj_pos; ++ while (((uint64_t)(v_s.len)) >= 8u) { ++ if (v_s.ptr[0u] == 239u) { ++ if (((uint8_t)(v_s.ptr[1u] & 13u)) != 0u) { ++ v_p += 2u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 2u); ++ continue; ++ } ++ v_addr = ((((uint32_t)(((uint8_t)(v_s.ptr[1u] & 240u)))) << 13u) | (((uint32_t)(v_s.ptr[2u])) << 9u) | (((uint32_t)(v_s.ptr[3u])) << 1u)); ++ v_addr -= v_p; ++ v_s.ptr[1u] = ((uint8_t)(((uint8_t)(v_s.ptr[1u] & 15u)) | ((uint8_t)(((v_addr >> 8u) & 240u))))); ++ v_s.ptr[2u] = ((uint8_t)((((v_addr >> 16u) & 15u) | ((v_addr >> 7u) & 16u) | (((uint32_t)(v_addr << 4u)) & 224u)))); ++ v_s.ptr[3u] = ((uint8_t)((((v_addr >> 4u) & 127u) | ((v_addr >> 13u) & 128u)))); ++ v_p += 4u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ continue; ++ } else if (((uint8_t)(v_s.ptr[0u] & 127u)) == 23u) { ++ v_x = ((((uint32_t)(v_s.ptr[0u])) << 0u) | ++ (((uint32_t)(v_s.ptr[1u])) << 8u) | ++ (((uint32_t)(v_s.ptr[2u])) << 16u) | ++ (((uint32_t)(v_s.ptr[3u])) << 24u)); ++ if ((v_x & 3712u) != 0u) { ++ v_y = ((((uint32_t)(v_s.ptr[4u])) << 0u) | ++ (((uint32_t)(v_s.ptr[5u])) << 8u) | ++ (((uint32_t)(v_s.ptr[6u])) << 16u) | ++ (((uint32_t)(v_s.ptr[7u])) << 24u)); ++ if (((((uint32_t)(v_x << 8u)) ^ ((uint32_t)(v_y - 3u))) & 1015811u) != 0u) { ++ v_p += 6u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 6u); ++ continue; ++ } ++ v_addr = ((v_x & 4294963200u) | (v_y >> 20u)); ++ v_x = (279u | ((uint32_t)(v_y << 12u))); ++ v_s.ptr[0u] = ((uint8_t)((v_x >> 0u))); ++ v_s.ptr[1u] = ((uint8_t)((v_x >> 8u))); ++ v_s.ptr[2u] = ((uint8_t)((v_x >> 16u))); ++ v_s.ptr[3u] = ((uint8_t)((v_x >> 24u))); ++ v_s.ptr[4u] = ((uint8_t)((v_addr >> 0u))); ++ v_s.ptr[5u] = ((uint8_t)((v_addr >> 8u))); ++ v_s.ptr[6u] = ((uint8_t)((v_addr >> 16u))); ++ v_s.ptr[7u] = ((uint8_t)((v_addr >> 24u))); ++ v_p += 8u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 8u); ++ continue; ++ } ++ v_x27 = (v_x >> 27u); ++ if (((uint32_t)(((uint32_t)(v_x - 12567u)) << 18u)) >= (v_x27 & 29u)) { ++ v_p += 4u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u); ++ continue; ++ } ++ v_addr = ((((uint32_t)(v_s.ptr[4u])) << 24u) | ++ (((uint32_t)(v_s.ptr[5u])) << 16u) | ++ (((uint32_t)(v_s.ptr[6u])) << 8u) | ++ (((uint32_t)(v_s.ptr[7u])) << 0u)); ++ v_addr -= v_p; ++ v_y = ((v_x >> 12u) | ((uint32_t)(v_addr << 20u))); ++ v_x = (23u | (v_x27 << 7u) | (((uint32_t)(v_addr + 2048u)) & 4294963200u)); ++ v_s.ptr[0u] = ((uint8_t)((v_x >> 0u))); ++ v_s.ptr[1u] = ((uint8_t)((v_x >> 8u))); ++ v_s.ptr[2u] = ((uint8_t)((v_x >> 16u))); ++ v_s.ptr[3u] = ((uint8_t)((v_x >> 24u))); ++ v_s.ptr[4u] = ((uint8_t)((v_y >> 0u))); ++ v_s.ptr[5u] = ((uint8_t)((v_y >> 8u))); ++ v_s.ptr[6u] = ((uint8_t)((v_y >> 16u))); ++ v_s.ptr[7u] = ((uint8_t)((v_y >> 24u))); ++ v_p += 8u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 8u); ++ continue; ++ } ++ v_p += 2u; ++ v_s = wuffs_base__slice_u8__subslice_i(v_s, 2u); ++ } ++ self->private_impl.f_bcj_pos = v_p; ++ return ((uint8_t)(((uint64_t)(v_s.len)))); ++} ++ ++// -------- func xz.decoder.get_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_xxhash32__hasher__get_quirk( +- const wuffs_xxhash32__hasher* self, ++wuffs_xz__decoder__get_quirk( ++ const wuffs_xz__decoder* self, + uint32_t a_key) { + if (!self) { + return 0; +@@ -61527,15 +77160,24 @@ wuffs_xxhash32__hasher__get_quirk( + return 0; + } + ++ if (a_key == 1u) { ++ if (self->private_impl.f_ignore_checksum) { ++ return 1u; ++ } ++ } else if (a_key == 2021322752u) { ++ if (self->private_impl.f_standalone_format) { ++ return 1u; ++ } ++ } + return 0u; + } + +-// -------- func xxhash32.hasher.set_quirk ++// -------- func xz.decoder.set_quirk + + WUFFS_BASE__GENERATED_C_CODE + WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_xxhash32__hasher__set_quirk( +- wuffs_xxhash32__hasher* self, ++wuffs_xz__decoder__set_quirk( ++ wuffs_xz__decoder* self, + uint32_t a_key, + uint64_t a_value) { + if (!self) { +@@ -61548,747 +77190,1667 @@ wuffs_xxhash32__hasher__set_quirk( + : wuffs_base__error__initialize_not_called); + } + ++ if (a_key == 1u) { ++ self->private_impl.f_ignore_checksum = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } else if (a_key == 2021322752u) { ++ self->private_impl.f_standalone_format = (a_value > 0u); ++ return wuffs_base__make_status(NULL); ++ } + return wuffs_base__make_status(wuffs_base__error__unsupported_option); + } + +-// -------- func xxhash32.hasher.update ++// -------- func xz.decoder.dst_history_retain_length + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_xxhash32__hasher__update( +- wuffs_xxhash32__hasher* self, +- wuffs_base__slice_u8 a_x) { ++WUFFS_BASE__MAYBE_STATIC wuffs_base__optional_u63 ++wuffs_xz__decoder__dst_history_retain_length( ++ const wuffs_xz__decoder* self) { + if (!self) { +- return wuffs_base__make_empty_struct(); ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__make_optional_u63(false, 0u); ++ } ++ ++ return wuffs_lzma__decoder__dst_history_retain_length(&self->private_data.f_lzma); ++} ++ ++// -------- func xz.decoder.workbuf_len ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 ++wuffs_xz__decoder__workbuf_len( ++ const wuffs_xz__decoder* self) { ++ if (!self) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && ++ (self->private_impl.magic != WUFFS_BASE__DISABLED)) { ++ return wuffs_base__utility__empty_range_ii_u64(); ++ } ++ ++ return wuffs_lzma__decoder__workbuf_len(&self->private_data.f_lzma); ++} ++ ++// -------- func xz.decoder.transform_io ++ ++WUFFS_BASE__GENERATED_C_CODE ++WUFFS_BASE__MAYBE_STATIC wuffs_base__status ++wuffs_xz__decoder__transform_io( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ if (!self) { ++ return wuffs_base__make_status(wuffs_base__error__bad_receiver); + } + if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); ++ return wuffs_base__make_status( ++ (self->private_impl.magic == WUFFS_BASE__DISABLED) ++ ? wuffs_base__error__disabled_by_previous_error ++ : wuffs_base__error__initialize_not_called); ++ } ++ if (!a_dst || !a_src) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__bad_argument); ++ } ++ if ((self->private_impl.active_coroutine != 0) && ++ (self->private_impl.active_coroutine != 1)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; ++ return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls); ++ } ++ self->private_impl.active_coroutine = 0; ++ wuffs_base__status status = wuffs_base__make_status(NULL); ++ ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ ++ uint32_t coro_susp_point = self->private_impl.p_transform_io; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ while (true) { ++ { ++ wuffs_base__status t_0 = wuffs_xz__decoder__do_transform_io(self, a_dst, a_src, a_workbuf); ++ v_status = t_0; ++ } ++ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) { ++ status = wuffs_base__make_status(wuffs_xz__error__truncated_input); ++ goto exit; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1); ++ } ++ ++ ok: ++ self->private_impl.p_transform_io = 0; ++ goto exit; + } + +- wuffs_base__slice_u8 v_remaining = {0}; ++ goto suspend; ++ suspend: ++ self->private_impl.p_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0; + +- if ((self->private_impl.f_length_modulo_u32 == 0u) && ! self->private_impl.f_length_overflows_u32) { +- self->private_impl.f_v0 = 606290984u; +- self->private_impl.f_v1 = 2246822519u; +- self->private_impl.f_v2 = 0u; +- self->private_impl.f_v3 = 1640531535u; +- } +- while (((uint64_t)(a_x.len)) > 0u) { +- v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0u); +- if (((uint64_t)(a_x.len)) > 16777216u) { +- v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 16777216u); +- a_x = wuffs_base__slice_u8__subslice_j(a_x, 16777216u); +- } +- wuffs_xxhash32__hasher__up(self, a_x); +- a_x = v_remaining; ++ goto exit; ++ exit: ++ if (wuffs_base__status__is_error(&status)) { ++ self->private_impl.magic = WUFFS_BASE__DISABLED; + } +- return wuffs_base__make_empty_struct(); ++ return status; + } + +-// -------- func xxhash32.hasher.update_u32 ++// -------- func xz.decoder.do_transform_io + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_xxhash32__hasher__update_u32( +- wuffs_xxhash32__hasher* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return 0; +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return 0; +- } ++static wuffs_base__status ++wuffs_xz__decoder__do_transform_io( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_dst, ++ wuffs_base__io_buffer* a_src, ++ wuffs_base__slice_u8 a_workbuf) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- wuffs_xxhash32__hasher__update(self, a_x); +- return wuffs_xxhash32__hasher__checksum_u32(self); +-} ++ uint64_t v_header_magic = 0; ++ uint64_t v_dmark = 0; ++ uint64_t v_smark = 0; ++ uint8_t v_i8 = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint32_t v_checksum32_have = 0; ++ uint32_t v_checksum32_want = 0; ++ uint64_t v_checksum64_have = 0; ++ uint64_t v_checksum64_want = 0; ++ wuffs_base__bitvec256 v_checksum256_have = {0}; ++ uint64_t v_compressed_size = 0; ++ uint64_t v_uncompressed_size = 0; ++ uint32_t v_hash = 0; ++ uint8_t v_c8 = 0; ++ uint32_t v_c32 = 0; ++ uint16_t v_footer_magic = 0; + +-// -------- func xxhash32.hasher.up ++ uint8_t* iop_a_dst = NULL; ++ uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_dst && a_dst->data.ptr) { ++ 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; ++ } ++ } ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_xxhash32__hasher__up( +- wuffs_xxhash32__hasher* self, +- wuffs_base__slice_u8 a_x) { +- uint32_t v_new_lmu = 0; +- uint32_t v_buf_u32 = 0; +- uint32_t v_buf_len = 0; +- uint32_t v_v0 = 0; +- uint32_t v_v1 = 0; +- uint32_t v_v2 = 0; +- uint32_t v_v3 = 0; +- wuffs_base__slice_u8 v_p = {0}; ++ uint32_t coro_susp_point = self->private_impl.p_do_transform_io; ++ if (coro_susp_point) { ++ v_checksum32_have = self->private_data.s_do_transform_io.v_checksum32_have; ++ v_checksum32_want = self->private_data.s_do_transform_io.v_checksum32_want; ++ v_checksum256_have = self->private_data.s_do_transform_io.v_checksum256_have; ++ v_compressed_size = self->private_data.s_do_transform_io.v_compressed_size; ++ v_uncompressed_size = self->private_data.s_do_transform_io.v_uncompressed_size; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- v_new_lmu = ((uint32_t)(self->private_impl.f_length_modulo_u32 + ((uint32_t)(((uint64_t)(a_x.len)))))); +- self->private_impl.f_length_overflows_u32 = ((v_new_lmu < self->private_impl.f_length_modulo_u32) || self->private_impl.f_length_overflows_u32); +- self->private_impl.f_length_modulo_u32 = v_new_lmu; +- while (true) { +- if (self->private_impl.f_buf_len >= 16u) { +- v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[0u])) | +- (((uint32_t)(self->private_impl.f_buf_data[1u])) << 8u) | +- (((uint32_t)(self->private_impl.f_buf_data[2u])) << 16u) | +- (((uint32_t)(self->private_impl.f_buf_data[3u])) << 24u)); +- v_v0 = ((uint32_t)(self->private_impl.f_v0 + ((uint32_t)(v_buf_u32 * 2246822519u)))); +- v_v0 = (((uint32_t)(v_v0 << 13u)) | (v_v0 >> 19u)); +- self->private_impl.f_v0 = ((uint32_t)(v_v0 * 2654435761u)); +- v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[4u])) | +- (((uint32_t)(self->private_impl.f_buf_data[5u])) << 8u) | +- (((uint32_t)(self->private_impl.f_buf_data[6u])) << 16u) | +- (((uint32_t)(self->private_impl.f_buf_data[7u])) << 24u)); +- v_v1 = ((uint32_t)(self->private_impl.f_v1 + ((uint32_t)(v_buf_u32 * 2246822519u)))); +- v_v1 = (((uint32_t)(v_v1 << 13u)) | (v_v1 >> 19u)); +- self->private_impl.f_v1 = ((uint32_t)(v_v1 * 2654435761u)); +- v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[8u])) | +- (((uint32_t)(self->private_impl.f_buf_data[9u])) << 8u) | +- (((uint32_t)(self->private_impl.f_buf_data[10u])) << 16u) | +- (((uint32_t)(self->private_impl.f_buf_data[11u])) << 24u)); +- v_v2 = ((uint32_t)(self->private_impl.f_v2 + ((uint32_t)(v_buf_u32 * 2246822519u)))); +- v_v2 = (((uint32_t)(v_v2 << 13u)) | (v_v2 >> 19u)); +- self->private_impl.f_v2 = ((uint32_t)(v_v2 * 2654435761u)); +- v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[12u])) | +- (((uint32_t)(self->private_impl.f_buf_data[13u])) << 8u) | +- (((uint32_t)(self->private_impl.f_buf_data[14u])) << 16u) | +- (((uint32_t)(self->private_impl.f_buf_data[15u])) << 24u)); +- v_v3 = ((uint32_t)(self->private_impl.f_v3 + ((uint32_t)(v_buf_u32 * 2246822519u)))); +- v_v3 = (((uint32_t)(v_v3 << 13u)) | (v_v3 >> 19u)); +- self->private_impl.f_v3 = ((uint32_t)(v_v3 * 2654435761u)); +- self->private_impl.f_buf_len = 0u; +- break; +- } +- if (((uint64_t)(a_x.len)) <= 0u) { +- return wuffs_base__make_empty_struct(); +- } +- self->private_impl.f_buf_data[self->private_impl.f_buf_len] = a_x.ptr[0u]; ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint64_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 6)) { ++ t_0 = ((uint64_t)(wuffs_base__peek_u48le__no_bounds_check(iop_a_src))); ++ iop_a_src += 6; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 40) { ++ t_0 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ v_header_magic = t_0; ++ } ++ if (v_header_magic != 388031461373u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_header); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint64_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 6)) { ++ t_1 = ((uint64_t)(wuffs_base__peek_u48le__no_bounds_check(iop_a_src))); ++ iop_a_src += 6; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 40) { ++ t_1 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ v_header_magic = t_1; ++ } ++ if (v_header_magic == 72400582410240u) { ++ self->private_impl.f_checksummer = 0u; ++ } else if (v_header_magic == 60327687946496u) { ++ self->private_impl.f_checksummer = 1u; ++ } else if (v_header_magic == 77742513456128u) { ++ self->private_impl.f_checksummer = 2u; ++ } else if (v_header_magic == 177077137508864u) { ++ self->private_impl.f_checksummer = 3u; ++ } else if ((v_header_magic & 61695u) != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_header); ++ goto exit; ++ } else { ++ v_header_magic = (15u & (v_header_magic >> 8u)); ++ if ((v_header_magic != 0u) && ++ (v_header_magic != 1u) && ++ (v_header_magic != 4u) && ++ (v_header_magic != 10u)) { ++ status = wuffs_base__make_status(wuffs_xz__error__unsupported_checksum_algorithm); ++ goto exit; ++ } ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } ++ self->private_impl.f_flags = ((uint16_t)(v_header_magic)); ++ self->private_impl.f_num_actual_blocks = 0u; ++ while (true) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0u) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5); ++ continue; ++ } else if (wuffs_base__peek_u8be__no_bounds_check(iop_a_src) == 0u) { ++ break; ++ } ++ self->private_impl.f_num_actual_blocks += 1u; ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ } ++ self->private_impl.f_compressed_size_for_index = 4u; ++ while (true) { ++ v_smark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_2 = wuffs_xz__decoder__decode_block_header_with_padding(self, a_src); ++ v_status = t_2; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_compressed_size_for_index, wuffs_private_impl__io__count_since(v_smark, ((uint64_t)(iop_a_src - io0_a_src)))); ++ if ( ! self->private_impl.f_ignore_checksum) { ++ v_checksum32_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_private_impl__io__since(v_smark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ uint32_t t_3; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_3 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3; ++ if (num_bits_3 == 24) { ++ t_3 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_3 += 8u; ++ *scratch |= ((uint64_t)(num_bits_3)) << 56; ++ } ++ } ++ v_checksum32_want = t_3; ++ } ++ if (self->private_impl.f_ignore_checksum) { ++ } else if (v_checksum32_have != v_checksum32_want) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } else { ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ wuffs_private_impl__ignore_status(wuffs_crc64__ecma_hasher__initialize(&self->private_data.f_crc64, ++ sizeof (wuffs_crc64__ecma_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ wuffs_private_impl__ignore_status(wuffs_sha256__hasher__initialize(&self->private_data.f_sha256, ++ sizeof (wuffs_sha256__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ } ++ v_compressed_size = 0u; ++ v_uncompressed_size = 0u; ++ while (true) { ++ if (((uint64_t)(self->private_impl.f_bcj_undo_index)) > ((uint64_t)(io2_a_dst - iop_a_dst))) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_write); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); ++ continue; ++ } ++ v_dmark = ((uint64_t)(iop_a_dst - io0_a_dst)); ++ v_smark = ((uint64_t)(iop_a_src - io0_a_src)); ++ if (self->private_impl.f_num_non_final_filters == 0u) { ++ { ++ 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__status t_4 = wuffs_lzma__decoder__transform_io(&self->private_data.f_lzma, a_dst, a_src, a_workbuf); ++ v_status = t_4; ++ 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; ++ } ++ } ++ } else { ++ if (self->private_impl.f_bcj_undo_index > 0u) { ++ wuffs_private_impl__io_writer__copy_from_slice(&iop_a_dst, io2_a_dst,wuffs_base__make_slice_u8(self->private_data.f_filter_data[0u], self->private_impl.f_bcj_undo_index)); ++ self->private_impl.f_bcj_undo_index = 0u; ++ } ++ { ++ uint8_t* o_0_io0_a_dst = io0_a_dst; ++ uint8_t* o_0_io1_a_dst = io1_a_dst; ++ io0_a_dst = iop_a_dst; ++ io1_a_dst = iop_a_dst; ++ wuffs_base__io_buffer o_0_a_dst; ++ if (a_dst) { ++ memcpy(&o_0_a_dst, a_dst, sizeof(*a_dst)); ++ size_t wi0 = a_dst->meta.wi; ++ a_dst->data.ptr += wi0; ++ a_dst->data.len -= wi0; ++ a_dst->meta.ri = 0; ++ a_dst->meta.wi = 0; ++ a_dst->meta.pos = wuffs_base__u64__sat_add(a_dst->meta.pos, wi0); ++ } ++ { ++ 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__status t_5 = wuffs_lzma__decoder__transform_io(&self->private_data.f_lzma, a_dst, a_src, a_workbuf); ++ v_status = t_5; ++ 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 (a_dst) { ++ memcpy(a_dst, &o_0_a_dst, sizeof(*a_dst)); ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); ++ io0_a_dst = o_0_io0_a_dst; ++ io1_a_dst = o_0_io1_a_dst; ++ } ++ } ++ self->private_impl.f_bcj_undo_index = wuffs_xz__decoder__apply_non_final_filters(self, wuffs_private_impl__io__since(v_dmark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); ++ if ((self->private_impl.f_bcj_undo_index > 0u) && ! wuffs_base__status__is_ok(&v_status)) { ++ v_i8 = ((uint8_t)(self->private_impl.f_bcj_undo_index - 1u)); ++ while (true) { ++ if ( ! (iop_a_dst > io1_a_dst)) { ++ status = wuffs_base__make_status(wuffs_xz__error__internal_error_inconsistent_bcj_filter_state); ++ goto exit; ++ } ++ self->private_data.f_filter_data[0u][v_i8] = iop_a_dst[-1]; ++ iop_a_dst--; ++ if (v_i8 <= 0u) { ++ break; ++ } + #if defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #endif +- self->private_impl.f_buf_len += 1u; ++ v_i8 -= 1u; + #if defined(__GNUC__) + #pragma GCC diagnostic pop + #endif +- a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); +- } +- v_buf_len = ((uint32_t)((self->private_impl.f_buf_len & 15u))); +- v_v0 = self->private_impl.f_v0; +- v_v1 = self->private_impl.f_v1; +- v_v2 = self->private_impl.f_v2; +- v_v3 = self->private_impl.f_v3; +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 16; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 16) * 16); +- while (v_p.ptr < i_end0_p) { +- v_buf_u32 = (((uint32_t)(v_p.ptr[0u])) | +- (((uint32_t)(v_p.ptr[1u])) << 8u) | +- (((uint32_t)(v_p.ptr[2u])) << 16u) | +- (((uint32_t)(v_p.ptr[3u])) << 24u)); +- v_v0 = ((uint32_t)(v_v0 + ((uint32_t)(v_buf_u32 * 2246822519u)))); +- v_v0 = (((uint32_t)(v_v0 << 13u)) | (v_v0 >> 19u)); +- v_v0 = ((uint32_t)(v_v0 * 2654435761u)); +- v_buf_u32 = (((uint32_t)(v_p.ptr[4u])) | +- (((uint32_t)(v_p.ptr[5u])) << 8u) | +- (((uint32_t)(v_p.ptr[6u])) << 16u) | +- (((uint32_t)(v_p.ptr[7u])) << 24u)); +- v_v1 = ((uint32_t)(v_v1 + ((uint32_t)(v_buf_u32 * 2246822519u)))); +- v_v1 = (((uint32_t)(v_v1 << 13u)) | (v_v1 >> 19u)); +- v_v1 = ((uint32_t)(v_v1 * 2654435761u)); +- v_buf_u32 = (((uint32_t)(v_p.ptr[8u])) | +- (((uint32_t)(v_p.ptr[9u])) << 8u) | +- (((uint32_t)(v_p.ptr[10u])) << 16u) | +- (((uint32_t)(v_p.ptr[11u])) << 24u)); +- v_v2 = ((uint32_t)(v_v2 + ((uint32_t)(v_buf_u32 * 2246822519u)))); +- v_v2 = (((uint32_t)(v_v2 << 13u)) | (v_v2 >> 19u)); +- v_v2 = ((uint32_t)(v_v2 * 2654435761u)); +- v_buf_u32 = (((uint32_t)(v_p.ptr[12u])) | +- (((uint32_t)(v_p.ptr[13u])) << 8u) | +- (((uint32_t)(v_p.ptr[14u])) << 16u) | +- (((uint32_t)(v_p.ptr[15u])) << 24u)); +- v_v3 = ((uint32_t)(v_v3 + ((uint32_t)(v_buf_u32 * 2246822519u)))); +- v_v3 = (((uint32_t)(v_v3 << 13u)) | (v_v3 >> 19u)); +- v_v3 = ((uint32_t)(v_v3 * 2654435761u)); +- v_p.ptr += 16; +- } +- v_p.len = 1; +- uint8_t* i_end1_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end1_p) { +- self->private_impl.f_buf_data[v_buf_len] = v_p.ptr[0u]; +- v_buf_len = ((v_buf_len + 1u) & 15u); +- v_p.ptr += 1; ++ } ++ } ++ } ++ v_compressed_size += wuffs_private_impl__io__count_since(v_smark, ((uint64_t)(iop_a_src - io0_a_src))); ++ v_uncompressed_size += wuffs_private_impl__io__count_since(v_dmark, ((uint64_t)(iop_a_dst - io0_a_dst))); ++ if (self->private_impl.f_ignore_checksum) { ++ } else if (self->private_impl.f_checksummer == 1u) { ++ wuffs_crc32__ieee_hasher__update(&self->private_data.f_crc32, wuffs_private_impl__io__since(v_dmark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); ++ } else if (self->private_impl.f_checksummer == 2u) { ++ wuffs_crc64__ecma_hasher__update(&self->private_data.f_crc64, wuffs_private_impl__io__since(v_dmark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); ++ } else if (self->private_impl.f_checksummer == 3u) { ++ wuffs_sha256__hasher__update(&self->private_data.f_sha256, wuffs_private_impl__io__since(v_dmark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)); ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); ++ } ++ if ((self->private_impl.f_block_has_compressed_size && (self->private_impl.f_block_compressed_size != v_compressed_size)) || (self->private_impl.f_block_has_uncompressed_size && (self->private_impl.f_block_uncompressed_size != v_uncompressed_size))) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_block_header); ++ goto exit; ++ } ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_compressed_size_for_index, v_compressed_size); ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_compressed_size_for_index, ((uint64_t)(WUFFS_XZ__CHECKSUM_LENGTH[self->private_impl.f_checksummer]))); ++ self->private_impl.f_verification_have_total_sizes[0u] += self->private_impl.f_compressed_size_for_index; ++ v_hash = ((uint32_t)((self->private_impl.f_compressed_size_for_index ^ (self->private_impl.f_compressed_size_for_index >> 32u)))); ++ v_hash *= 3432918353u; ++ v_hash = (((uint32_t)(v_hash << 15u)) | (v_hash >> 17u)); ++ v_hash *= 461845907u; ++ v_hash ^= self->private_impl.f_verification_have_hashed_sizes[0u]; ++ v_hash = (((uint32_t)(v_hash << 13u)) | (v_hash >> 19u)); ++ self->private_impl.f_verification_have_hashed_sizes[0u] = ((uint32_t)(((uint32_t)(v_hash * 5u)) + 3864292196u)); ++ self->private_impl.f_verification_have_total_sizes[1u] += v_uncompressed_size; ++ v_hash = ((uint32_t)((v_uncompressed_size ^ (v_uncompressed_size >> 32u)))); ++ v_hash *= 3432918353u; ++ v_hash = (((uint32_t)(v_hash << 15u)) | (v_hash >> 17u)); ++ v_hash *= 461845907u; ++ v_hash ^= self->private_impl.f_verification_have_hashed_sizes[1u]; ++ v_hash = (((uint32_t)(v_hash << 13u)) | (v_hash >> 19u)); ++ self->private_impl.f_verification_have_hashed_sizes[1u] = ((uint32_t)(((uint32_t)(v_hash * 5u)) + 3864292196u)); ++ while ((v_compressed_size & 3u) != 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; ++ } ++ if (v_c8 != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_padding); ++ goto exit; ++ } ++ v_compressed_size += 1u; ++ } ++ self->private_impl.f_lzma_needs_reset = true; ++ if (self->private_impl.f_ignore_checksum) { ++ self->private_data.s_do_transform_io.scratch = ((uint32_t)(WUFFS_XZ__CHECKSUM_LENGTH[self->private_impl.f_checksummer])); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ if (self->private_data.s_do_transform_io.scratch > ((uint64_t)(io2_a_src - iop_a_src))) { ++ self->private_data.s_do_transform_io.scratch -= ((uint64_t)(io2_a_src - iop_a_src)); ++ iop_a_src = io2_a_src; ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ iop_a_src += self->private_data.s_do_transform_io.scratch; ++ } else if (self->private_impl.f_checksummer == 1u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13); ++ uint32_t t_7; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_7 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7; ++ if (num_bits_7 == 24) { ++ t_7 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_7 += 8u; ++ *scratch |= ((uint64_t)(num_bits_7)) << 56; ++ } ++ } ++ v_checksum32_want = t_7; ++ } ++ v_checksum32_have = wuffs_crc32__ieee_hasher__checksum_u32(&self->private_data.f_crc32); ++ if (v_checksum32_have != v_checksum32_want) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } ++ } else if (self->private_impl.f_checksummer == 2u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15); ++ uint64_t t_8; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_8 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8; ++ if (num_bits_8 == 56) { ++ t_8 = ((uint64_t)(*scratch)); ++ break; ++ } ++ num_bits_8 += 8u; ++ *scratch |= ((uint64_t)(num_bits_8)) << 56; ++ } ++ } ++ v_checksum64_want = t_8; ++ } ++ v_checksum64_have = wuffs_crc64__ecma_hasher__checksum_u64(&self->private_data.f_crc64); ++ if (v_checksum64_have != v_checksum64_want) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } ++ } else if (self->private_impl.f_checksummer == 3u) { ++ v_checksum256_have = wuffs_sha256__hasher__checksum_bitvec256(&self->private_data.f_sha256); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17); ++ uint64_t t_9; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_9 = wuffs_base__peek_u64be__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_9 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_9); ++ if (num_bits_9 == 56) { ++ t_9 = ((uint64_t)(*scratch >> 0)); ++ break; ++ } ++ num_bits_9 += 8u; ++ *scratch |= ((uint64_t)(num_bits_9)); ++ } ++ } ++ v_checksum64_want = t_9; ++ } ++ if (wuffs_base__bitvec256__get_u64(&v_checksum256_have, 3u) != v_checksum64_want) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19); ++ uint64_t t_10; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_10 = wuffs_base__peek_u64be__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_10 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_10); ++ if (num_bits_10 == 56) { ++ t_10 = ((uint64_t)(*scratch >> 0)); ++ break; ++ } ++ num_bits_10 += 8u; ++ *scratch |= ((uint64_t)(num_bits_10)); ++ } ++ } ++ v_checksum64_want = t_10; ++ } ++ if (wuffs_base__bitvec256__get_u64(&v_checksum256_have, 2u) != v_checksum64_want) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21); ++ uint64_t t_11; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_11 = wuffs_base__peek_u64be__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_11 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_11); ++ if (num_bits_11 == 56) { ++ t_11 = ((uint64_t)(*scratch >> 0)); ++ break; ++ } ++ num_bits_11 += 8u; ++ *scratch |= ((uint64_t)(num_bits_11)); ++ } ++ } ++ v_checksum64_want = t_11; ++ } ++ if (wuffs_base__bitvec256__get_u64(&v_checksum256_have, 1u) != v_checksum64_want) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23); ++ uint64_t t_12; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) { ++ t_12 = wuffs_base__peek_u64be__no_bounds_check(iop_a_src); ++ iop_a_src += 8; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_12 = ((uint32_t)(*scratch & 0xFFu)); ++ *scratch >>= 8; ++ *scratch <<= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_12); ++ if (num_bits_12 == 56) { ++ t_12 = ((uint64_t)(*scratch >> 0)); ++ break; ++ } ++ num_bits_12 += 8u; ++ *scratch |= ((uint64_t)(num_bits_12)); ++ } ++ } ++ v_checksum64_want = t_12; ++ } ++ if (wuffs_base__bitvec256__get_u64(&v_checksum256_have, 0u) != v_checksum64_want) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } ++ } ++ } ++ self->private_impl.f_backwards_size = 0u; ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ } ++ while (true) { ++ v_smark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_13 = wuffs_xz__decoder__verify_index(self, a_src); ++ v_status = t_13; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ wuffs_private_impl__u64__sat_add_indirect(&self->private_impl.f_backwards_size, wuffs_private_impl__io__count_since(v_smark, ((uint64_t)(iop_a_src - io0_a_src)))); ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_crc32__ieee_hasher__update(&self->private_data.f_crc32, wuffs_private_impl__io__since(v_smark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(25); ++ } ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_crc32__ieee_hasher__update(&self->private_data.f_crc32, wuffs_base__make_slice_u8(wuffs_base__strip_const_from_u8_ptr(WUFFS_XZ__ZEROES), (3u & ((uint64_t)(0u - (3u & self->private_impl.f_backwards_size)))))); ++ } ++ while ((self->private_impl.f_backwards_size & 3u) != 0u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(26); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_14 = *iop_a_src++; ++ v_c8 = t_14; ++ } ++ if (v_c8 != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ self->private_impl.f_backwards_size += 1u; ++ } ++ self->private_impl.f_backwards_size >>= 2u; ++ if ((self->private_impl.f_backwards_size == 0u) || (self->private_impl.f_backwards_size > 4294967295u)) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(27); ++ uint32_t t_15; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_15 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(28); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_15 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_15; ++ if (num_bits_15 == 24) { ++ t_15 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_15 += 8u; ++ *scratch |= ((uint64_t)(num_bits_15)) << 56; ++ } ++ } ++ v_checksum32_want = t_15; ++ } ++ if (self->private_impl.f_ignore_checksum) { ++ } else if (v_checksum32_want != wuffs_crc32__ieee_hasher__checksum_u32(&self->private_data.f_crc32)) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } else { ++ wuffs_private_impl__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32, ++ sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(29); ++ uint32_t t_16; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_16 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(30); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_16 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_16; ++ if (num_bits_16 == 24) { ++ t_16 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_16 += 8u; ++ *scratch |= ((uint64_t)(num_bits_16)) << 56; ++ } ++ } ++ v_checksum32_want = t_16; ++ } ++ while (true) { ++ v_smark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_17 = wuffs_xz__decoder__verify_footer(self, a_src); ++ v_status = t_17; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ if ( ! self->private_impl.f_ignore_checksum) { ++ wuffs_crc32__ieee_hasher__update(&self->private_data.f_crc32, wuffs_private_impl__io__since(v_smark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src)); ++ } ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(31); ++ } ++ if ( ! self->private_impl.f_ignore_checksum && (v_checksum32_want != wuffs_crc32__ieee_hasher__checksum_u32(&self->private_data.f_crc32))) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_checksum); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(32); ++ uint16_t t_18; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_18 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_do_transform_io.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(33); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_do_transform_io.scratch; ++ uint32_t num_bits_18 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_18; ++ if (num_bits_18 == 8) { ++ t_18 = ((uint16_t)(*scratch)); ++ break; ++ } ++ num_bits_18 += 8u; ++ *scratch |= ((uint64_t)(num_bits_18)) << 56; ++ } ++ } ++ v_footer_magic = t_18; ++ } ++ if (v_footer_magic != 23129u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_footer); ++ goto exit; ++ } ++ if ( ! self->private_impl.f_standalone_format) { ++ break; ++ } ++ while (true) { ++ while (((uint64_t)(io2_a_src - iop_a_src)) < 4u) { ++ if (a_src && a_src->meta.closed) { ++ if (((uint64_t)(io2_a_src - iop_a_src)) == 0u) { ++ goto label__streams__break; ++ } else { ++ status = wuffs_base__make_status(wuffs_xz__error__truncated_input); ++ goto exit; ++ } ++ } ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(34); ++ } ++ v_c32 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ if (v_c32 == 1484404733u) { ++ break; ++ } else if (v_c32 != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_header_concatenated_stream); ++ goto exit; ++ } ++ iop_a_src += 4u; ++ } ++ self->private_impl.f_started_verify_index = false; + } +- v_p.len = 0; +- } +- self->private_impl.f_buf_len = ((uint8_t)(v_buf_len)); +- self->private_impl.f_v0 = v_v0; +- self->private_impl.f_v1 = v_v1; +- self->private_impl.f_v2 = v_v2; +- self->private_impl.f_v3 = v_v3; +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func xxhash32.hasher.checksum_u32 ++ label__streams__break:; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint32_t +-wuffs_xxhash32__hasher__checksum_u32( +- const wuffs_xxhash32__hasher* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ ok: ++ self->private_impl.p_do_transform_io = 0; ++ goto exit; + } + +- uint32_t v_ret = 0; +- uint32_t v_i = 0; +- uint32_t v_n = 0; +- uint32_t v_buf_u32 = 0; ++ goto suspend; ++ suspend: ++ self->private_impl.p_do_transform_io = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_do_transform_io.v_checksum32_have = v_checksum32_have; ++ self->private_data.s_do_transform_io.v_checksum32_want = v_checksum32_want; ++ self->private_data.s_do_transform_io.v_checksum256_have = v_checksum256_have; ++ self->private_data.s_do_transform_io.v_compressed_size = v_compressed_size; ++ self->private_data.s_do_transform_io.v_uncompressed_size = v_uncompressed_size; + +- if ((self->private_impl.f_length_modulo_u32 >= 16u) || self->private_impl.f_length_overflows_u32) { +- v_ret += (((uint32_t)(self->private_impl.f_v0 << 1u)) | (self->private_impl.f_v0 >> 31u)); +- v_ret += (((uint32_t)(self->private_impl.f_v1 << 7u)) | (self->private_impl.f_v1 >> 25u)); +- v_ret += (((uint32_t)(self->private_impl.f_v2 << 12u)) | (self->private_impl.f_v2 >> 20u)); +- v_ret += (((uint32_t)(self->private_impl.f_v3 << 18u)) | (self->private_impl.f_v3 >> 14u)); +- v_ret += self->private_impl.f_length_modulo_u32; +- } else { +- v_ret += 374761393u; +- v_ret += self->private_impl.f_length_modulo_u32; +- } +- v_n = 16u; +- v_n = wuffs_base__u32__min(v_n, ((uint32_t)(self->private_impl.f_buf_len))); +- if (4u <= v_n) { +- v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[0u])) | +- (((uint32_t)(self->private_impl.f_buf_data[1u])) << 8u) | +- (((uint32_t)(self->private_impl.f_buf_data[2u])) << 16u) | +- (((uint32_t)(self->private_impl.f_buf_data[3u])) << 24u)); +- v_ret += ((uint32_t)(v_buf_u32 * 3266489917u)); +- v_ret = (((uint32_t)(v_ret << 17u)) | (v_ret >> 15u)); +- v_ret *= 668265263u; +- v_i = 4u; +- } +- if (8u <= v_n) { +- v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[4u])) | +- (((uint32_t)(self->private_impl.f_buf_data[5u])) << 8u) | +- (((uint32_t)(self->private_impl.f_buf_data[6u])) << 16u) | +- (((uint32_t)(self->private_impl.f_buf_data[7u])) << 24u)); +- v_ret += ((uint32_t)(v_buf_u32 * 3266489917u)); +- v_ret = (((uint32_t)(v_ret << 17u)) | (v_ret >> 15u)); +- v_ret *= 668265263u; +- v_i = 8u; +- } +- if (12u <= v_n) { +- v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[8u])) | +- (((uint32_t)(self->private_impl.f_buf_data[9u])) << 8u) | +- (((uint32_t)(self->private_impl.f_buf_data[10u])) << 16u) | +- (((uint32_t)(self->private_impl.f_buf_data[11u])) << 24u)); +- v_ret += ((uint32_t)(v_buf_u32 * 3266489917u)); +- v_ret = (((uint32_t)(v_ret << 17u)) | (v_ret >> 15u)); +- v_ret *= 668265263u; +- v_i = 12u; ++ goto exit; ++ exit: ++ if (a_dst && a_dst->data.ptr) { ++ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr)); + } +- while (v_i < v_n) { +- v_ret += ((uint32_t)(((uint32_t)(self->private_impl.f_buf_data[v_i])) * 374761393u)); +- v_ret = (((uint32_t)(v_ret << 11u)) | (v_ret >> 21u)); +- v_ret *= 2654435761u; +- v_i += 1u; ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- v_ret ^= (v_ret >> 15u); +- v_ret *= 2246822519u; +- v_ret ^= (v_ret >> 13u); +- v_ret *= 3266489917u; +- v_ret ^= (v_ret >> 16u); +- return v_ret; +-} +- +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH32) +- +-#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH64) +- +-// ---------------- Status Codes Implementations + +-// ---------------- Private Consts ++ return status; ++} + +-#define WUFFS_XXHASH64__XXH_PRIME64_1 11400714785074694791 ++// -------- func xz.decoder.decode_block_header_with_padding + +-#define WUFFS_XXHASH64__XXH_PRIME64_2 14029467366897019727 ++WUFFS_BASE__GENERATED_C_CODE ++static wuffs_base__status ++wuffs_xz__decoder__decode_block_header_with_padding( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-#define WUFFS_XXHASH64__XXH_PRIME64_3 1609587929392839161 ++ uint8_t v_c8 = 0; ++ uint64_t v_padded_size_have = 0; ++ uint64_t v_padded_size_want = 0; ++ uint64_t v_smark = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); + +-#define WUFFS_XXHASH64__XXH_PRIME64_4 9650029242287828579 ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; ++ } + +-#define WUFFS_XXHASH64__XXH_PRIME64_5 2870177450012600261 ++ uint32_t coro_susp_point = self->private_impl.p_decode_block_header_with_padding; ++ if (coro_susp_point) { ++ v_padded_size_have = self->private_data.s_decode_block_header_with_padding.v_padded_size_have; ++ v_padded_size_want = self->private_data.s_decode_block_header_with_padding.v_padded_size_want; ++ } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-#define WUFFS_XXHASH64__INITIAL_V0 6983438078262162902 ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ v_padded_size_want = ((uint64_t)((((uint64_t)(v_c8)) * 4u) - 1u)); ++ while (true) { ++ v_smark = ((uint64_t)(iop_a_src - io0_a_src)); ++ { ++ if (a_src) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } ++ wuffs_base__status t_1 = wuffs_xz__decoder__decode_block_header_sans_padding(self, a_src); ++ v_status = t_1; ++ if (a_src) { ++ iop_a_src = a_src->data.ptr + a_src->meta.ri; ++ } ++ } ++ wuffs_private_impl__u64__sat_add_indirect(&v_padded_size_have, wuffs_private_impl__io__count_since(v_smark, ((uint64_t)(iop_a_src - io0_a_src)))); ++ if (wuffs_base__status__is_ok(&v_status)) { ++ break; ++ } ++ status = v_status; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); ++ } ++ if (v_padded_size_have > v_padded_size_want) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_block_header); ++ goto exit; ++ } ++ while (v_padded_size_have < v_padded_size_want) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ if (v_c8 != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_block_header); ++ goto exit; ++ } ++ v_padded_size_have += 1u; ++ } + +-#define WUFFS_XXHASH64__INITIAL_V1 14029467366897019727 ++ ok: ++ self->private_impl.p_decode_block_header_with_padding = 0; ++ goto exit; ++ } + +-#define WUFFS_XXHASH64__INITIAL_V2 0 ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_block_header_with_padding = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_block_header_with_padding.v_padded_size_have = v_padded_size_have; ++ self->private_data.s_decode_block_header_with_padding.v_padded_size_want = v_padded_size_want; + +-#define WUFFS_XXHASH64__INITIAL_V3 7046029288634856825 ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); ++ } + +-// ---------------- Private Initializer Prototypes ++ return status; ++} + +-// ---------------- Private Function Prototypes ++// -------- func xz.decoder.decode_block_header_sans_padding + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_xxhash64__hasher__up( +- wuffs_xxhash64__hasher* self, +- wuffs_base__slice_u8 a_x); +- +-// ---------------- VTables +- +-const wuffs_base__hasher_u64__func_ptrs +-wuffs_xxhash64__hasher__func_ptrs_for__wuffs_base__hasher_u64 = { +- (uint64_t(*)(const void*))(&wuffs_xxhash64__hasher__checksum_u64), +- (uint64_t(*)(const void*, +- uint32_t))(&wuffs_xxhash64__hasher__get_quirk), +- (wuffs_base__status(*)(void*, +- uint32_t, +- uint64_t))(&wuffs_xxhash64__hasher__set_quirk), +- (wuffs_base__empty_struct(*)(void*, +- wuffs_base__slice_u8))(&wuffs_xxhash64__hasher__update), +- (uint64_t(*)(void*, +- wuffs_base__slice_u8))(&wuffs_xxhash64__hasher__update_u64), +-}; ++static wuffs_base__status ++wuffs_xz__decoder__decode_block_header_sans_padding( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-// ---------------- Initializer Implementations ++ uint8_t v_c8 = 0; ++ uint32_t v_c32 = 0; ++ uint32_t v_alignment = 0; ++ uint8_t v_flags = 0; ++ uint8_t v_filter_id = 0; ++ wuffs_base__status v_status = wuffs_base__make_status(NULL); ++ uint32_t v_shift = 0; ++ uint32_t v_f = 0; ++ uint32_t v_k = 0; + +-wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT +-wuffs_xxhash64__hasher__initialize( +- wuffs_xxhash64__hasher* self, +- size_t sizeof_star_self, +- uint64_t wuffs_version, +- uint32_t options){ +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (sizeof(*self) != sizeof_star_self) { +- return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } +- if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) || +- (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) { +- return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version); ++ ++ uint32_t coro_susp_point = self->private_impl.p_decode_block_header_sans_padding; ++ if (coro_susp_point) { ++ v_flags = self->private_data.s_decode_block_header_sans_padding.v_flags; ++ v_filter_id = self->private_data.s_decode_block_header_sans_padding.v_filter_id; ++ v_shift = self->private_data.s_decode_block_header_sans_padding.v_shift; ++ v_f = self->private_data.s_decode_block_header_sans_padding.v_f; + } ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +- if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) { +- // The whole point of this if-check is to detect an uninitialized *self. +- // We disable the warning on GCC. Clang-5.0 does not have this warning. +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +-#endif +- if (self->private_impl.magic != 0) { +- return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed); ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_flags = t_0; + } +-#if !defined(__clang__) && defined(__GNUC__) +-#pragma GCC diagnostic pop +-#endif +- } else { +- if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) { +- memset(self, 0, sizeof(*self)); +- options |= WUFFS_INITIALIZE__ALREADY_ZEROED; ++ self->private_impl.f_num_non_final_filters = ((uint32_t)(((uint8_t)(v_flags & 3u)))); ++ if (((uint8_t)(v_flags & 60u)) != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_block_header); ++ goto exit; ++ } ++ self->private_impl.f_block_has_compressed_size = (((uint8_t)(v_flags & 64u)) != 0u); ++ if (self->private_impl.f_block_has_compressed_size) { ++ self->private_impl.f_block_compressed_size = 0u; ++ v_shift = 0u; ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (v_shift <= 56u) { ++ self->private_impl.f_block_compressed_size |= (((uint64_t)(((uint8_t)(v_c8 & 127u)))) << v_shift); ++ if (v_c8 >= 128u) { ++ v_shift += 7u; ++ continue; ++ } else if ((v_c8 == 0u) && (v_shift > 0u)) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_block_header); ++ goto exit; ++ } ++ break; ++ } else if (v_c8 != 1u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_block_header); ++ goto exit; ++ } ++ self->private_impl.f_block_compressed_size |= (((uint64_t)(1u)) << 63u); ++ break; ++ } ++ } ++ self->private_impl.f_block_has_uncompressed_size = (((uint8_t)(v_flags & 128u)) != 0u); ++ if (self->private_impl.f_block_has_uncompressed_size) { ++ self->private_impl.f_block_uncompressed_size = 0u; ++ v_shift = 0u; ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ if (v_shift <= 56u) { ++ self->private_impl.f_block_uncompressed_size |= (((uint64_t)(((uint8_t)(v_c8 & 127u)))) << v_shift); ++ if (v_c8 >= 128u) { ++ v_shift += 7u; ++ continue; ++ } else if ((v_c8 == 0u) && (v_shift > 0u)) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_block_header); ++ goto exit; ++ } ++ break; ++ } else if (v_c8 != 1u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_block_header); ++ goto exit; ++ } ++ self->private_impl.f_block_uncompressed_size |= (((uint64_t)(1u)) << 63u); ++ break; ++ } ++ } ++ self->private_impl.f_bcj_x86_prev_mask = 0u; ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_non_final_filters__choosy_default); ++ v_f = 0u; ++ while (v_f < self->private_impl.f_num_non_final_filters) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_filter_id = t_3; ++ } ++ if (v_filter_id == 33u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_filter); ++ goto exit; ++ } else if (v_filter_id == 3u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_4 = *iop_a_src++; ++ v_c8 = t_4; ++ } ++ if (v_c8 != 1u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_filter); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_5 = *iop_a_src++; ++ v_c8 = t_5; ++ } ++ self->private_impl.f_filters[v_f] = ((((uint32_t)(v_c8)) << 8u) | 3u); ++ v_k = 0u; ++ while (v_k < 256u) { ++ self->private_data.f_filter_data[v_f][v_k] = 0u; ++ v_k += 1u; ++ } ++ } else if ((v_filter_id < 3u) || (11u < v_filter_id)) { ++ status = wuffs_base__make_status(wuffs_xz__error__unsupported_filter); ++ goto exit; ++ } else if (v_f != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__unsupported_filter_combination); ++ goto exit; ++ } else { ++ self->private_impl.f_filters[v_f] = ((uint32_t)(v_filter_id)); ++ if (v_filter_id == 4u) { ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_filter_04_x86); ++ } else if (v_filter_id == 5u) { ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_filter_05_powerpc); ++ } else if (v_filter_id == 6u) { ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_filter_06_ia64); ++ } else if (v_filter_id == 7u) { ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_filter_07_arm); ++ } else if (v_filter_id == 8u) { ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_filter_08_armthumb); ++ } else if (v_filter_id == 9u) { ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_filter_09_sparc); ++ } else if (v_filter_id == 10u) { ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_filter_0a_arm64); ++ } else { ++ self->private_impl.choosy_apply_non_final_filters = ( ++ &wuffs_xz__decoder__apply_filter_0b_riscv); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_6 = *iop_a_src++; ++ v_c8 = t_6; ++ } ++ if (v_c8 == 0u) { ++ self->private_impl.f_bcj_pos = 0u; ++ } else if (v_c8 == 4u) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); ++ uint32_t t_7; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_7 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_decode_block_header_sans_padding.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_decode_block_header_sans_padding.scratch; ++ uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7; ++ if (num_bits_7 == 24) { ++ t_7 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_7 += 8u; ++ *scratch |= ((uint64_t)(num_bits_7)) << 56; ++ } ++ } ++ v_c32 = t_7; ++ } ++ v_alignment = ((uint32_t)(WUFFS_XZ__BCJ_OFFSET_ALIGNMENT[v_filter_id])); ++ if (v_alignment > 0u) { ++ if ((v_c32 % v_alignment) != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_bcj_offset); ++ goto exit; ++ } ++ } ++ self->private_impl.f_bcj_pos = v_c32; ++ } else { ++ status = wuffs_base__make_status(wuffs_xz__error__unsupported_filter); ++ goto exit; ++ } ++ } ++ v_f += 1u; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_8 = *iop_a_src++; ++ v_filter_id = t_8; ++ } ++ if (v_filter_id == 33u) { ++ if (self->private_impl.f_lzma_needs_reset) { ++ wuffs_private_impl__ignore_status(wuffs_lzma__decoder__initialize(&self->private_data.f_lzma, ++ sizeof (wuffs_lzma__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_9 = *iop_a_src++; ++ v_c8 = t_9; ++ } ++ if (v_c8 != 1u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_filter); ++ goto exit; ++ } ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_10 = *iop_a_src++; ++ v_c8 = t_10; ++ } ++ v_status = wuffs_lzma__decoder__set_quirk(&self->private_data.f_lzma, 1348001793u, (2u | (((uint64_t)(v_c8)) << 8u))); ++ if ( ! wuffs_base__status__is_ok(&v_status)) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_filter); ++ goto exit; ++ } ++ } else if ((v_filter_id < 3u) || (11u < v_filter_id)) { ++ status = wuffs_base__make_status(wuffs_xz__error__unsupported_filter); ++ goto exit; + } else { +- memset(&(self->private_impl), 0, sizeof(self->private_impl)); ++ status = wuffs_base__make_status(wuffs_xz__error__bad_filter); ++ goto exit; + } +- } + +- self->private_impl.magic = WUFFS_BASE__MAGIC; +- self->private_impl.vtable_for__wuffs_base__hasher_u64.vtable_name = +- wuffs_base__hasher_u64__vtable_name; +- self->private_impl.vtable_for__wuffs_base__hasher_u64.function_pointers = +- (const void*)(&wuffs_xxhash64__hasher__func_ptrs_for__wuffs_base__hasher_u64); +- return wuffs_base__make_status(NULL); +-} +- +-wuffs_xxhash64__hasher* +-wuffs_xxhash64__hasher__alloc(void) { +- wuffs_xxhash64__hasher* x = +- (wuffs_xxhash64__hasher*)(calloc(sizeof(wuffs_xxhash64__hasher), 1)); +- if (!x) { +- return NULL; +- } +- if (wuffs_xxhash64__hasher__initialize( +- x, sizeof(wuffs_xxhash64__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) { +- free(x); +- return NULL; ++ goto ok; ++ ok: ++ self->private_impl.p_decode_block_header_sans_padding = 0; ++ goto exit; + } +- return x; +-} +- +-size_t +-sizeof__wuffs_xxhash64__hasher(void) { +- return sizeof(wuffs_xxhash64__hasher); +-} + +-// ---------------- Function Implementations +- +-// -------- func xxhash64.hasher.get_quirk ++ goto suspend; ++ suspend: ++ self->private_impl.p_decode_block_header_sans_padding = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_decode_block_header_sans_padding.v_flags = v_flags; ++ self->private_data.s_decode_block_header_sans_padding.v_filter_id = v_filter_id; ++ self->private_data.s_decode_block_header_sans_padding.v_shift = v_shift; ++ self->private_data.s_decode_block_header_sans_padding.v_f = v_f; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_xxhash64__hasher__get_quirk( +- const wuffs_xxhash64__hasher* self, +- uint32_t a_key) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- return 0u; ++ return status; + } + +-// -------- func xxhash64.hasher.set_quirk ++// -------- func xz.decoder.verify_index + + WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__status +-wuffs_xxhash64__hasher__set_quirk( +- wuffs_xxhash64__hasher* self, +- uint32_t a_key, +- uint64_t a_value) { +- if (!self) { +- return wuffs_base__make_status(wuffs_base__error__bad_receiver); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_status( +- (self->private_impl.magic == WUFFS_BASE__DISABLED) +- ? wuffs_base__error__disabled_by_previous_error +- : wuffs_base__error__initialize_not_called); +- } +- +- return wuffs_base__make_status(wuffs_base__error__unsupported_option); +-} ++static wuffs_base__status ++wuffs_xz__decoder__verify_index( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +-// -------- func xxhash64.hasher.update ++ uint8_t v_c8 = 0; ++ uint32_t v_shift = 0; ++ uint32_t v_hash = 0; + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct +-wuffs_xxhash64__hasher__update( +- wuffs_xxhash64__hasher* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return wuffs_base__make_empty_struct(); +- } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return wuffs_base__make_empty_struct(); ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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; + } + +- if ((self->private_impl.f_length_modulo_u64 == 0u) && ! self->private_impl.f_length_overflows_u64) { +- self->private_impl.f_v0 = 6983438078262162902u; +- self->private_impl.f_v1 = 14029467366897019727u; +- self->private_impl.f_v2 = 0u; +- self->private_impl.f_v3 = 7046029288634856825u; ++ uint32_t coro_susp_point = self->private_impl.p_verify_index; ++ if (coro_susp_point) { ++ v_shift = self->private_data.s_verify_index.v_shift; + } +- wuffs_xxhash64__hasher__up(self, a_x); +- return wuffs_base__make_empty_struct(); +-} ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; + +-// -------- func xxhash64.hasher.update_u64 ++ if ( ! self->private_impl.f_started_verify_index) { ++ self->private_impl.f_started_verify_index = true; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_0 = *iop_a_src++; ++ v_c8 = t_0; ++ } ++ if (v_c8 != 0u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ self->private_impl.f_num_index_blocks = 0u; ++ v_shift = 0u; ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_1 = *iop_a_src++; ++ v_c8 = t_1; ++ } ++ if (v_shift <= 56u) { ++ self->private_impl.f_num_index_blocks |= (((uint64_t)(((uint8_t)(v_c8 & 127u)))) << v_shift); ++ if (v_c8 >= 128u) { ++ v_shift += 7u; ++ continue; ++ } else if ((v_c8 == 0u) && (v_shift > 0u)) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ break; ++ } else if (v_c8 != 1u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ self->private_impl.f_num_index_blocks |= (((uint64_t)(1u)) << 63u); ++ break; ++ } ++ if (self->private_impl.f_num_index_blocks != self->private_impl.f_num_actual_blocks) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ } ++ while (self->private_impl.f_num_index_blocks > 0u) { ++ self->private_impl.f_num_index_blocks -= 1u; ++ self->private_impl.f_index_block_compressed_size = 0u; ++ v_shift = 0u; ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_2 = *iop_a_src++; ++ v_c8 = t_2; ++ } ++ if (v_shift <= 56u) { ++ self->private_impl.f_index_block_compressed_size |= (((uint64_t)(((uint8_t)(v_c8 & 127u)))) << v_shift); ++ if (v_c8 >= 128u) { ++ v_shift += 7u; ++ continue; ++ } else if ((v_c8 == 0u) && (v_shift > 0u)) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ break; ++ } else if (v_c8 != 1u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ self->private_impl.f_index_block_compressed_size |= (((uint64_t)(1u)) << 63u); ++ break; ++ } ++ self->private_impl.f_index_block_uncompressed_size = 0u; ++ v_shift = 0u; ++ while (true) { ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint8_t t_3 = *iop_a_src++; ++ v_c8 = t_3; ++ } ++ if (v_shift <= 56u) { ++ self->private_impl.f_index_block_uncompressed_size |= (((uint64_t)(((uint8_t)(v_c8 & 127u)))) << v_shift); ++ if (v_c8 >= 128u) { ++ v_shift += 7u; ++ continue; ++ } else if ((v_c8 == 0u) && (v_shift > 0u)) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ break; ++ } else if (v_c8 != 1u) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } ++ self->private_impl.f_index_block_uncompressed_size |= (((uint64_t)(1u)) << 63u); ++ break; ++ } ++ self->private_impl.f_verification_want_total_sizes[0u] += self->private_impl.f_index_block_compressed_size; ++ v_hash = ((uint32_t)((self->private_impl.f_index_block_compressed_size ^ (self->private_impl.f_index_block_compressed_size >> 32u)))); ++ v_hash *= 3432918353u; ++ v_hash = (((uint32_t)(v_hash << 15u)) | (v_hash >> 17u)); ++ v_hash *= 461845907u; ++ v_hash ^= self->private_impl.f_verification_want_hashed_sizes[0u]; ++ v_hash = (((uint32_t)(v_hash << 13u)) | (v_hash >> 19u)); ++ self->private_impl.f_verification_want_hashed_sizes[0u] = ((uint32_t)(((uint32_t)(v_hash * 5u)) + 3864292196u)); ++ self->private_impl.f_verification_want_total_sizes[1u] += self->private_impl.f_index_block_uncompressed_size; ++ v_hash = ((uint32_t)((self->private_impl.f_index_block_uncompressed_size ^ (self->private_impl.f_index_block_uncompressed_size >> 32u)))); ++ v_hash *= 3432918353u; ++ v_hash = (((uint32_t)(v_hash << 15u)) | (v_hash >> 17u)); ++ v_hash *= 461845907u; ++ v_hash ^= self->private_impl.f_verification_want_hashed_sizes[1u]; ++ v_hash = (((uint32_t)(v_hash << 13u)) | (v_hash >> 19u)); ++ self->private_impl.f_verification_want_hashed_sizes[1u] = ((uint32_t)(((uint32_t)(v_hash * 5u)) + 3864292196u)); ++ } ++ if ((self->private_impl.f_verification_have_hashed_sizes[0u] != self->private_impl.f_verification_want_hashed_sizes[0u]) || ++ (self->private_impl.f_verification_have_hashed_sizes[1u] != self->private_impl.f_verification_want_hashed_sizes[1u]) || ++ (self->private_impl.f_verification_have_total_sizes[0u] != self->private_impl.f_verification_want_total_sizes[0u]) || ++ (self->private_impl.f_verification_have_total_sizes[1u] != self->private_impl.f_verification_want_total_sizes[1u])) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_index); ++ goto exit; ++ } + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_xxhash64__hasher__update_u64( +- wuffs_xxhash64__hasher* self, +- wuffs_base__slice_u8 a_x) { +- if (!self) { +- return 0; ++ goto ok; ++ ok: ++ self->private_impl.p_verify_index = 0; ++ goto exit; + } +- if (self->private_impl.magic != WUFFS_BASE__MAGIC) { +- return 0; ++ ++ goto suspend; ++ suspend: ++ self->private_impl.p_verify_index = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; ++ self->private_data.s_verify_index.v_shift = v_shift; ++ ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } + +- wuffs_xxhash64__hasher__update(self, a_x); +- return wuffs_xxhash64__hasher__checksum_u64(self); ++ return status; + } + +-// -------- func xxhash64.hasher.up ++// -------- func xz.decoder.verify_footer + + WUFFS_BASE__GENERATED_C_CODE +-static wuffs_base__empty_struct +-wuffs_xxhash64__hasher__up( +- wuffs_xxhash64__hasher* self, +- wuffs_base__slice_u8 a_x) { +- uint64_t v_new_lmu = 0; +- uint64_t v_buf_u64 = 0; +- uint32_t v_buf_len = 0; +- uint64_t v_v0 = 0; +- uint64_t v_v1 = 0; +- uint64_t v_v2 = 0; +- uint64_t v_v3 = 0; +- wuffs_base__slice_u8 v_p = {0}; ++static wuffs_base__status ++wuffs_xz__decoder__verify_footer( ++ wuffs_xz__decoder* self, ++ wuffs_base__io_buffer* a_src) { ++ wuffs_base__status status = wuffs_base__make_status(NULL); + +- v_new_lmu = ((uint64_t)(self->private_impl.f_length_modulo_u64 + ((uint64_t)(a_x.len)))); +- self->private_impl.f_length_overflows_u64 = ((v_new_lmu < self->private_impl.f_length_modulo_u64) || self->private_impl.f_length_overflows_u64); +- self->private_impl.f_length_modulo_u64 = v_new_lmu; +- while (true) { +- if (self->private_impl.f_buf_len >= 32u) { +- v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[0u])) | +- (((uint64_t)(self->private_impl.f_buf_data[1u])) << 8u) | +- (((uint64_t)(self->private_impl.f_buf_data[2u])) << 16u) | +- (((uint64_t)(self->private_impl.f_buf_data[3u])) << 24u) | +- (((uint64_t)(self->private_impl.f_buf_data[4u])) << 32u) | +- (((uint64_t)(self->private_impl.f_buf_data[5u])) << 40u) | +- (((uint64_t)(self->private_impl.f_buf_data[6u])) << 48u) | +- (((uint64_t)(self->private_impl.f_buf_data[7u])) << 56u)); +- v_v0 = ((uint64_t)(self->private_impl.f_v0 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); +- v_v0 = (((uint64_t)(v_v0 << 31u)) | (v_v0 >> 33u)); +- self->private_impl.f_v0 = ((uint64_t)(v_v0 * 11400714785074694791u)); +- v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[8u])) | +- (((uint64_t)(self->private_impl.f_buf_data[9u])) << 8u) | +- (((uint64_t)(self->private_impl.f_buf_data[10u])) << 16u) | +- (((uint64_t)(self->private_impl.f_buf_data[11u])) << 24u) | +- (((uint64_t)(self->private_impl.f_buf_data[12u])) << 32u) | +- (((uint64_t)(self->private_impl.f_buf_data[13u])) << 40u) | +- (((uint64_t)(self->private_impl.f_buf_data[14u])) << 48u) | +- (((uint64_t)(self->private_impl.f_buf_data[15u])) << 56u)); +- v_v1 = ((uint64_t)(self->private_impl.f_v1 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); +- v_v1 = (((uint64_t)(v_v1 << 31u)) | (v_v1 >> 33u)); +- self->private_impl.f_v1 = ((uint64_t)(v_v1 * 11400714785074694791u)); +- v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[16u])) | +- (((uint64_t)(self->private_impl.f_buf_data[17u])) << 8u) | +- (((uint64_t)(self->private_impl.f_buf_data[18u])) << 16u) | +- (((uint64_t)(self->private_impl.f_buf_data[19u])) << 24u) | +- (((uint64_t)(self->private_impl.f_buf_data[20u])) << 32u) | +- (((uint64_t)(self->private_impl.f_buf_data[21u])) << 40u) | +- (((uint64_t)(self->private_impl.f_buf_data[22u])) << 48u) | +- (((uint64_t)(self->private_impl.f_buf_data[23u])) << 56u)); +- v_v2 = ((uint64_t)(self->private_impl.f_v2 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); +- v_v2 = (((uint64_t)(v_v2 << 31u)) | (v_v2 >> 33u)); +- self->private_impl.f_v2 = ((uint64_t)(v_v2 * 11400714785074694791u)); +- v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[24u])) | +- (((uint64_t)(self->private_impl.f_buf_data[25u])) << 8u) | +- (((uint64_t)(self->private_impl.f_buf_data[26u])) << 16u) | +- (((uint64_t)(self->private_impl.f_buf_data[27u])) << 24u) | +- (((uint64_t)(self->private_impl.f_buf_data[28u])) << 32u) | +- (((uint64_t)(self->private_impl.f_buf_data[29u])) << 40u) | +- (((uint64_t)(self->private_impl.f_buf_data[30u])) << 48u) | +- (((uint64_t)(self->private_impl.f_buf_data[31u])) << 56u)); +- v_v3 = ((uint64_t)(self->private_impl.f_v3 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); +- v_v3 = (((uint64_t)(v_v3 << 31u)) | (v_v3 >> 33u)); +- self->private_impl.f_v3 = ((uint64_t)(v_v3 * 11400714785074694791u)); +- self->private_impl.f_buf_len = 0u; +- break; ++ uint32_t v_c32 = 0; ++ ++ const uint8_t* iop_a_src = NULL; ++ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL; ++ if (a_src && a_src->data.ptr) { ++ 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_verify_footer; ++ switch (coro_susp_point) { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0; ++ ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); ++ uint32_t t_0; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) { ++ t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src); ++ iop_a_src += 4; ++ } else { ++ self->private_data.s_verify_footer.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_verify_footer.scratch; ++ uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0; ++ if (num_bits_0 == 24) { ++ t_0 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_0 += 8u; ++ *scratch |= ((uint64_t)(num_bits_0)) << 56; ++ } ++ } ++ v_c32 = t_0; + } +- if (((uint64_t)(a_x.len)) <= 0u) { +- return wuffs_base__make_empty_struct(); ++ if (v_c32 != ((uint32_t)(self->private_impl.f_backwards_size))) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_footer); ++ goto exit; + } +- self->private_impl.f_buf_data[self->private_impl.f_buf_len] = a_x.ptr[0u]; +- self->private_impl.f_buf_len += 1u; +- a_x = wuffs_base__slice_u8__subslice_i(a_x, 1u); +- } +- v_buf_len = (self->private_impl.f_buf_len & 31u); +- v_v0 = self->private_impl.f_v0; +- v_v1 = self->private_impl.f_v1; +- v_v2 = self->private_impl.f_v2; +- v_v3 = self->private_impl.f_v3; +- { +- wuffs_base__slice_u8 i_slice_p = a_x; +- v_p.ptr = i_slice_p.ptr; +- v_p.len = 32; +- uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32); +- while (v_p.ptr < i_end0_p) { +- v_buf_u64 = (((uint64_t)(v_p.ptr[0u])) | +- (((uint64_t)(v_p.ptr[1u])) << 8u) | +- (((uint64_t)(v_p.ptr[2u])) << 16u) | +- (((uint64_t)(v_p.ptr[3u])) << 24u) | +- (((uint64_t)(v_p.ptr[4u])) << 32u) | +- (((uint64_t)(v_p.ptr[5u])) << 40u) | +- (((uint64_t)(v_p.ptr[6u])) << 48u) | +- (((uint64_t)(v_p.ptr[7u])) << 56u)); +- v_v0 = ((uint64_t)(v_v0 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); +- v_v0 = (((uint64_t)(v_v0 << 31u)) | (v_v0 >> 33u)); +- v_v0 = ((uint64_t)(v_v0 * 11400714785074694791u)); +- v_buf_u64 = (((uint64_t)(v_p.ptr[8u])) | +- (((uint64_t)(v_p.ptr[9u])) << 8u) | +- (((uint64_t)(v_p.ptr[10u])) << 16u) | +- (((uint64_t)(v_p.ptr[11u])) << 24u) | +- (((uint64_t)(v_p.ptr[12u])) << 32u) | +- (((uint64_t)(v_p.ptr[13u])) << 40u) | +- (((uint64_t)(v_p.ptr[14u])) << 48u) | +- (((uint64_t)(v_p.ptr[15u])) << 56u)); +- v_v1 = ((uint64_t)(v_v1 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); +- v_v1 = (((uint64_t)(v_v1 << 31u)) | (v_v1 >> 33u)); +- v_v1 = ((uint64_t)(v_v1 * 11400714785074694791u)); +- v_buf_u64 = (((uint64_t)(v_p.ptr[16u])) | +- (((uint64_t)(v_p.ptr[17u])) << 8u) | +- (((uint64_t)(v_p.ptr[18u])) << 16u) | +- (((uint64_t)(v_p.ptr[19u])) << 24u) | +- (((uint64_t)(v_p.ptr[20u])) << 32u) | +- (((uint64_t)(v_p.ptr[21u])) << 40u) | +- (((uint64_t)(v_p.ptr[22u])) << 48u) | +- (((uint64_t)(v_p.ptr[23u])) << 56u)); +- v_v2 = ((uint64_t)(v_v2 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); +- v_v2 = (((uint64_t)(v_v2 << 31u)) | (v_v2 >> 33u)); +- v_v2 = ((uint64_t)(v_v2 * 11400714785074694791u)); +- v_buf_u64 = (((uint64_t)(v_p.ptr[24u])) | +- (((uint64_t)(v_p.ptr[25u])) << 8u) | +- (((uint64_t)(v_p.ptr[26u])) << 16u) | +- (((uint64_t)(v_p.ptr[27u])) << 24u) | +- (((uint64_t)(v_p.ptr[28u])) << 32u) | +- (((uint64_t)(v_p.ptr[29u])) << 40u) | +- (((uint64_t)(v_p.ptr[30u])) << 48u) | +- (((uint64_t)(v_p.ptr[31u])) << 56u)); +- v_v3 = ((uint64_t)(v_v3 + ((uint64_t)(v_buf_u64 * 14029467366897019727u)))); +- v_v3 = (((uint64_t)(v_v3 << 31u)) | (v_v3 >> 33u)); +- v_v3 = ((uint64_t)(v_v3 * 11400714785074694791u)); +- v_p.ptr += 32; ++ { ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); ++ uint32_t t_1; ++ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) { ++ t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src))); ++ iop_a_src += 2; ++ } else { ++ self->private_data.s_verify_footer.scratch = 0; ++ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); ++ while (true) { ++ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) { ++ status = wuffs_base__make_status(wuffs_base__suspension__short_read); ++ goto suspend; ++ } ++ uint64_t* scratch = &self->private_data.s_verify_footer.scratch; ++ uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56)); ++ *scratch <<= 8; ++ *scratch >>= 8; ++ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1; ++ if (num_bits_1 == 8) { ++ t_1 = ((uint32_t)(*scratch)); ++ break; ++ } ++ num_bits_1 += 8u; ++ *scratch |= ((uint64_t)(num_bits_1)) << 56; ++ } ++ } ++ v_c32 = t_1; + } +- v_p.len = 1; +- uint8_t* i_end1_p = i_slice_p.ptr + i_slice_p.len; +- while (v_p.ptr < i_end1_p) { +- self->private_impl.f_buf_data[v_buf_len] = v_p.ptr[0u]; +- v_buf_len = ((v_buf_len + 1u) & 31u); +- v_p.ptr += 1; ++ if (v_c32 != ((uint32_t)(self->private_impl.f_flags))) { ++ status = wuffs_base__make_status(wuffs_xz__error__bad_footer); ++ goto exit; + } +- v_p.len = 0; +- } +- self->private_impl.f_buf_len = v_buf_len; +- self->private_impl.f_v0 = v_v0; +- self->private_impl.f_v1 = v_v1; +- self->private_impl.f_v2 = v_v2; +- self->private_impl.f_v3 = v_v3; +- return wuffs_base__make_empty_struct(); +-} +- +-// -------- func xxhash64.hasher.checksum_u64 + +-WUFFS_BASE__GENERATED_C_CODE +-WUFFS_BASE__MAYBE_STATIC uint64_t +-wuffs_xxhash64__hasher__checksum_u64( +- const wuffs_xxhash64__hasher* self) { +- if (!self) { +- return 0; +- } +- if ((self->private_impl.magic != WUFFS_BASE__MAGIC) && +- (self->private_impl.magic != WUFFS_BASE__DISABLED)) { +- return 0; ++ goto ok; ++ ok: ++ self->private_impl.p_verify_footer = 0; ++ goto exit; + } + +- uint64_t v_ret = 0; +- uint64_t v_v0 = 0; +- uint64_t v_v1 = 0; +- uint64_t v_v2 = 0; +- uint64_t v_v3 = 0; +- uint32_t v_i = 0; +- uint32_t v_i8 = 0; +- uint32_t v_n = 0; +- uint32_t v_buf_u32 = 0; +- uint64_t v_buf_u64 = 0; ++ goto suspend; ++ suspend: ++ self->private_impl.p_verify_footer = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0; + +- if ((self->private_impl.f_length_modulo_u64 >= 32u) || self->private_impl.f_length_overflows_u64) { +- v_ret += (((uint64_t)(self->private_impl.f_v0 << 1u)) | (self->private_impl.f_v0 >> 63u)); +- v_ret += (((uint64_t)(self->private_impl.f_v1 << 7u)) | (self->private_impl.f_v1 >> 57u)); +- v_ret += (((uint64_t)(self->private_impl.f_v2 << 12u)) | (self->private_impl.f_v2 >> 52u)); +- v_ret += (((uint64_t)(self->private_impl.f_v3 << 18u)) | (self->private_impl.f_v3 >> 46u)); +- v_v0 = ((uint64_t)(self->private_impl.f_v0 * 14029467366897019727u)); +- v_v0 = (((uint64_t)(v_v0 << 31u)) | (v_v0 >> 33u)); +- v_v0 *= 11400714785074694791u; +- v_v1 = ((uint64_t)(self->private_impl.f_v1 * 14029467366897019727u)); +- v_v1 = (((uint64_t)(v_v1 << 31u)) | (v_v1 >> 33u)); +- v_v1 *= 11400714785074694791u; +- v_v2 = ((uint64_t)(self->private_impl.f_v2 * 14029467366897019727u)); +- v_v2 = (((uint64_t)(v_v2 << 31u)) | (v_v2 >> 33u)); +- v_v2 *= 11400714785074694791u; +- v_v3 = ((uint64_t)(self->private_impl.f_v3 * 14029467366897019727u)); +- v_v3 = (((uint64_t)(v_v3 << 31u)) | (v_v3 >> 33u)); +- v_v3 *= 11400714785074694791u; +- v_ret = ((uint64_t)(((uint64_t)((v_ret ^ v_v0) * 11400714785074694791u)) + 9650029242287828579u)); +- v_ret = ((uint64_t)(((uint64_t)((v_ret ^ v_v1) * 11400714785074694791u)) + 9650029242287828579u)); +- v_ret = ((uint64_t)(((uint64_t)((v_ret ^ v_v2) * 11400714785074694791u)) + 9650029242287828579u)); +- v_ret = ((uint64_t)(((uint64_t)((v_ret ^ v_v3) * 11400714785074694791u)) + 9650029242287828579u)); +- v_ret += self->private_impl.f_length_modulo_u64; +- } else { +- v_ret += 2870177450012600261u; +- v_ret += self->private_impl.f_length_modulo_u64; +- } +- v_n = 32u; +- v_n = wuffs_base__u32__min(v_n, self->private_impl.f_buf_len); +- if (8u <= v_n) { +- v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[0u])) | +- (((uint64_t)(self->private_impl.f_buf_data[1u])) << 8u) | +- (((uint64_t)(self->private_impl.f_buf_data[2u])) << 16u) | +- (((uint64_t)(self->private_impl.f_buf_data[3u])) << 24u) | +- (((uint64_t)(self->private_impl.f_buf_data[4u])) << 32u) | +- (((uint64_t)(self->private_impl.f_buf_data[5u])) << 40u) | +- (((uint64_t)(self->private_impl.f_buf_data[6u])) << 48u) | +- (((uint64_t)(self->private_impl.f_buf_data[7u])) << 56u)); +- v_buf_u64 *= 14029467366897019727u; +- v_buf_u64 = (((uint64_t)(v_buf_u64 << 31u)) | (v_buf_u64 >> 33u)); +- v_buf_u64 *= 11400714785074694791u; +- v_ret ^= v_buf_u64; +- v_ret = (((uint64_t)(v_ret << 27u)) | (v_ret >> 37u)); +- v_ret *= 11400714785074694791u; +- v_ret += 9650029242287828579u; +- v_i = 8u; +- } +- if (16u <= v_n) { +- v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[8u])) | +- (((uint64_t)(self->private_impl.f_buf_data[9u])) << 8u) | +- (((uint64_t)(self->private_impl.f_buf_data[10u])) << 16u) | +- (((uint64_t)(self->private_impl.f_buf_data[11u])) << 24u) | +- (((uint64_t)(self->private_impl.f_buf_data[12u])) << 32u) | +- (((uint64_t)(self->private_impl.f_buf_data[13u])) << 40u) | +- (((uint64_t)(self->private_impl.f_buf_data[14u])) << 48u) | +- (((uint64_t)(self->private_impl.f_buf_data[15u])) << 56u)); +- v_buf_u64 *= 14029467366897019727u; +- v_buf_u64 = (((uint64_t)(v_buf_u64 << 31u)) | (v_buf_u64 >> 33u)); +- v_buf_u64 *= 11400714785074694791u; +- v_ret ^= v_buf_u64; +- v_ret = (((uint64_t)(v_ret << 27u)) | (v_ret >> 37u)); +- v_ret *= 11400714785074694791u; +- v_ret += 9650029242287828579u; +- v_i = 16u; +- } +- if (24u <= v_n) { +- v_buf_u64 = (((uint64_t)(self->private_impl.f_buf_data[16u])) | +- (((uint64_t)(self->private_impl.f_buf_data[17u])) << 8u) | +- (((uint64_t)(self->private_impl.f_buf_data[18u])) << 16u) | +- (((uint64_t)(self->private_impl.f_buf_data[19u])) << 24u) | +- (((uint64_t)(self->private_impl.f_buf_data[20u])) << 32u) | +- (((uint64_t)(self->private_impl.f_buf_data[21u])) << 40u) | +- (((uint64_t)(self->private_impl.f_buf_data[22u])) << 48u) | +- (((uint64_t)(self->private_impl.f_buf_data[23u])) << 56u)); +- v_buf_u64 *= 14029467366897019727u; +- v_buf_u64 = (((uint64_t)(v_buf_u64 << 31u)) | (v_buf_u64 >> 33u)); +- v_buf_u64 *= 11400714785074694791u; +- v_ret ^= v_buf_u64; +- v_ret = (((uint64_t)(v_ret << 27u)) | (v_ret >> 37u)); +- v_ret *= 11400714785074694791u; +- v_ret += 9650029242287828579u; +- v_i = 24u; +- } +- if ((v_n & 4u) != 0u) { +- v_i8 = (v_i & 24u); +- v_buf_u32 = (((uint32_t)(self->private_impl.f_buf_data[(v_i8 + 0u)])) | +- (((uint32_t)(self->private_impl.f_buf_data[(v_i8 + 1u)])) << 8u) | +- (((uint32_t)(self->private_impl.f_buf_data[(v_i8 + 2u)])) << 16u) | +- (((uint32_t)(self->private_impl.f_buf_data[(v_i8 + 3u)])) << 24u)); +- v_ret ^= ((uint64_t)(((uint64_t)(v_buf_u32)) * 11400714785074694791u)); +- v_ret = (((uint64_t)(v_ret << 23u)) | (v_ret >> 41u)); +- v_ret *= 14029467366897019727u; +- v_ret += 1609587929392839161u; +- v_i = (v_i8 + 4u); +- } +- while (v_i < v_n) { +- v_ret ^= ((uint64_t)(((uint64_t)(self->private_impl.f_buf_data[v_i])) * 2870177450012600261u)); +- v_ret = (((uint64_t)(v_ret << 11u)) | (v_ret >> 53u)); +- v_ret *= 11400714785074694791u; +- v_i += 1u; ++ goto exit; ++ exit: ++ if (a_src && a_src->data.ptr) { ++ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr)); + } +- v_ret ^= (v_ret >> 33u); +- v_ret *= 14029467366897019727u; +- v_ret ^= (v_ret >> 29u); +- v_ret *= 1609587929392839161u; +- v_ret ^= (v_ret >> 32u); +- return ((uint64_t)(v_ret)); ++ ++ return status; + } + +-#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XXHASH64) ++#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__XZ) + + #if defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR) + +@@ -62309,16 +78871,12 @@ DynIOBuffer::DynIOBuffer(uint64_t max_incl) + : m_buf(wuffs_base__empty_io_buffer()), m_max_incl(max_incl) {} + + DynIOBuffer::~DynIOBuffer() { +- if (m_buf.data.ptr) { +- free(m_buf.data.ptr); +- } ++ free(m_buf.data.ptr); + } + + void // + DynIOBuffer::drop() { +- if (m_buf.data.ptr) { +- free(m_buf.data.ptr); +- } ++ free(m_buf.data.ptr); + m_buf = wuffs_base__empty_io_buffer(); + } + +@@ -62329,13 +78887,16 @@ DynIOBuffer::grow(uint64_t min_incl) { + return ((min_incl == 0) && (m_max_incl == 0)) + ? DynIOBuffer::GrowResult::OK + : DynIOBuffer::GrowResult::FailedMaxInclExceeded; ++ } else if (n > SIZE_MAX) { ++ return DynIOBuffer::GrowResult::FailedOutOfMemory; + } else if (n > m_buf.data.len) { +- uint8_t* ptr = static_cast(realloc(m_buf.data.ptr, n)); ++ uint8_t* ptr = ++ static_cast(realloc(m_buf.data.ptr, static_cast(n))); + if (!ptr) { + return DynIOBuffer::GrowResult::FailedOutOfMemory; + } + m_buf.data.ptr = ptr; +- m_buf.data.len = n; ++ m_buf.data.len = static_cast(n); + } + return DynIOBuffer::GrowResult::OK; + } +@@ -62382,7 +78943,7 @@ Input::BringsItsOwnIOBuffer() { + FileInput::FileInput(FILE* f) : m_f(f) {} + + std::string // +-FileInput::CopyIn(IOBuffer* dst, uint64_t history_retain_length) { ++FileInput::CopyIn(IOBuffer* dst) { + if (!m_f) { + return "wuffs_aux::sync_io::FileInput: nullptr file"; + } else if (!dst) { +@@ -62390,7 +78951,7 @@ FileInput::CopyIn(IOBuffer* dst, uint64_t history_retain_length) { + } else if (dst->meta.closed) { + return "wuffs_aux::sync_io::FileInput: end of file"; + } else { +- dst->compact_retaining(history_retain_length); ++ dst->compact(); + size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f); + dst->meta.wi += n; + dst->meta.closed = feof(m_f); +@@ -62418,7 +78979,7 @@ MemoryInput::BringsItsOwnIOBuffer() { + } + + std::string // +-MemoryInput::CopyIn(IOBuffer* dst, uint64_t history_retain_length) { ++MemoryInput::CopyIn(IOBuffer* dst) { + if (!dst) { + return "wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer"; + } else if (dst->meta.closed) { +@@ -62428,7 +78989,7 @@ MemoryInput::CopyIn(IOBuffer* dst, uint64_t history_retain_length) { + // to it. + return "wuffs_aux::sync_io::MemoryInput: overlapping buffers"; + } else { +- dst->compact_retaining(history_retain_length); ++ dst->compact(); + size_t nd = dst->writer_length(); + size_t ns = m_io.reader_length(); + size_t n = (nd < ns) ? nd : ns; +@@ -62483,7 +79044,7 @@ AdvanceIOBufferTo(const ErrorMessages& error_messages, + if (!input.BringsItsOwnIOBuffer()) { + io_buf.compact(); + } +- std::string error_message = input.CopyIn(&io_buf, 0); ++ std::string error_message = input.CopyIn(&io_buf); + if (!error_message.empty()) { + return error_message; + } +@@ -62566,7 +79127,7 @@ HandleMetadata( + } else if (!input.BringsItsOwnIOBuffer()) { + io_buf.compact(); + } +- std::string error_message = input.CopyIn(&io_buf, 0); ++ std::string error_message = input.CopyIn(&io_buf); + if (!error_message.empty()) { + return error_message; + } +@@ -62627,15 +79188,13 @@ DecodeCborCallbacks::Done(DecodeCborResult& result, + sync_io::Input& input, + IOBuffer& buffer) {} + +-DecodeCborArgQuirks::DecodeCborArgQuirks(wuffs_base__slice_u32 repr0) +- : repr(repr0) {} +- +-DecodeCborArgQuirks::DecodeCborArgQuirks(uint32_t* ptr0, size_t len0) +- : repr(wuffs_base__make_slice_u32(ptr0, len0)) {} ++DecodeCborArgQuirks::DecodeCborArgQuirks(const QuirkKeyValuePair* ptr0, ++ const size_t len0) ++ : ptr(ptr0), len(len0) {} + + DecodeCborArgQuirks // + DecodeCborArgQuirks::DefaultValue() { +- return DecodeCborArgQuirks(wuffs_base__empty_slice_u32()); ++ return DecodeCborArgQuirks(nullptr, 0); + } + + DecodeCborResult // +@@ -62664,8 +79223,8 @@ DecodeCbor(DecodeCborCallbacks& callbacks, + ret_error_message = "wuffs_aux::DecodeCbor: out of memory"; + goto done; + } +- for (size_t i = 0; i < quirks.repr.len; i++) { +- dec->set_quirk(quirks.repr.ptr[i], 1); ++ for (size_t i = 0; i < quirks.len; i++) { ++ dec->set_quirk(quirks.ptr[i].first, quirks.ptr[i].second); + } + + // Prepare the wuffs_base__tok_buffer. 256 tokens is 2KiB. +@@ -62710,14 +79269,14 @@ DecodeCbor(DecodeCborCallbacks& callbacks, + "wuffs_aux::DecodeCbor: internal error: io_buf is closed"; + goto done; + } +- io_buf->compact_retaining(dec->history_retain_length()); ++ io_buf->compact(); + if (io_buf->meta.wi >= io_buf->data.len) { + ret_error_message = + "wuffs_aux::DecodeCbor: internal error: io_buf is full"; + goto done; + } + cursor_index = io_buf->meta.ri; +- io_error_message = input.CopyIn(io_buf, dec->history_retain_length()); ++ io_error_message = input.CopyIn(io_buf); + } else { + ret_error_message = tok_status.message(); + goto done; +@@ -62796,7 +79355,7 @@ DecodeCbor(DecodeCborCallbacks& callbacks, + goto done; + } + depth++; +- if (depth > WUFFS_CBOR__DECODER_DEPTH_MAX_INCL) { ++ if (depth > (int32_t)WUFFS_CBOR__DECODER_DEPTH_MAX_INCL) { + ret_error_message = + "wuffs_aux::DecodeCbor: internal error: bad depth"; + goto done; +@@ -63052,6 +79611,11 @@ DecodeImageCallbacks::SelectDecoder(uint32_t fourcc, + } + #endif + ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__QOI) ++ case WUFFS_BASE__FOURCC__QOI: ++ return wuffs_qoi__decoder::alloc_as__wuffs_base__image_decoder(); ++#endif ++ + #if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) + case WUFFS_BASE__FOURCC__TGA: + return wuffs_tga__decoder::alloc_as__wuffs_base__image_decoder(); +@@ -63061,6 +79625,11 @@ DecodeImageCallbacks::SelectDecoder(uint32_t fourcc, + case WUFFS_BASE__FOURCC__WBMP: + return wuffs_wbmp__decoder::alloc_as__wuffs_base__image_decoder(); + #endif ++ ++#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WEBP) ++ case WUFFS_BASE__FOURCC__WEBP: ++ return wuffs_webp__decoder::alloc_as__wuffs_base__image_decoder(); ++#endif + } + + return wuffs_base__image_decoder::unique_ptr(nullptr); +@@ -63091,7 +79660,7 @@ DecodeImageCallbacks::AllocPixbuf(const wuffs_base__image_config& image_config, + return AllocPixbufResult(DecodeImage_UnsupportedPixelConfiguration); + } + void* ptr = +- allow_uninitialized_memory ? malloc((size_t)len) : calloc((size_t)len, 1); ++ allow_uninitialized_memory ? malloc((size_t)len) : calloc(1, (size_t)len); + if (!ptr) { + return AllocPixbufResult(DecodeImage_OutOfMemory); + } +@@ -63116,7 +79685,7 @@ DecodeImageCallbacks::AllocWorkbuf(wuffs_base__range_ii_u64 len_range, + return AllocWorkbufResult(DecodeImage_OutOfMemory); + } + void* ptr = +- allow_uninitialized_memory ? malloc((size_t)len) : calloc((size_t)len, 1); ++ allow_uninitialized_memory ? malloc((size_t)len) : calloc(1, (size_t)len); + if (!ptr) { + return AllocWorkbufResult(DecodeImage_OutOfMemory); + } +@@ -63153,15 +79722,13 @@ const char DecodeImage_UnsupportedPixelConfiguration[] = // + const char DecodeImage_UnsupportedPixelFormat[] = // + "wuffs_aux::DecodeImage: unsupported pixel format"; + +-DecodeImageArgQuirks::DecodeImageArgQuirks(wuffs_base__slice_u32 repr0) +- : repr(repr0) {} +- +-DecodeImageArgQuirks::DecodeImageArgQuirks(uint32_t* ptr0, size_t len0) +- : repr(wuffs_base__make_slice_u32(ptr0, len0)) {} ++DecodeImageArgQuirks::DecodeImageArgQuirks(const QuirkKeyValuePair* ptr0, ++ const size_t len0) ++ : ptr(ptr0), len(len0) {} + + DecodeImageArgQuirks // + DecodeImageArgQuirks::DefaultValue() { +- return DecodeImageArgQuirks(wuffs_base__empty_slice_u32()); ++ return DecodeImageArgQuirks(nullptr, 0); + } + + DecodeImageArgFlags::DecodeImageArgFlags(uint64_t repr0) : repr(repr0) {} +@@ -63259,7 +79826,8 @@ DecodeImage0(wuffs_base__image_decoder::unique_ptr& image_decoder, + DecodeImageCallbacks& callbacks, + sync_io::Input& input, + wuffs_base__io_buffer& io_buf, +- wuffs_base__slice_u32 quirks, ++ const QuirkKeyValuePair* quirks_ptr, ++ const size_t quirks_len, + uint64_t flags, + wuffs_base__pixel_blend pixel_blend, + wuffs_base__color_u32_argb_premul background_color, +@@ -63301,7 +79869,7 @@ redirect: + fourcc = 0; + break; + } +- std::string error_message = input.CopyIn(&io_buf, 0); ++ std::string error_message = input.CopyIn(&io_buf); + if (!error_message.empty()) { + return DecodeImageResult(std::move(error_message)); + } +@@ -63342,8 +79910,8 @@ redirect: + } + + // Apply quirks. +- for (size_t i = 0; i < quirks.len; i++) { +- image_decoder->set_quirk(quirks.ptr[i], 1); ++ for (size_t i = 0; i < quirks_len; i++) { ++ image_decoder->set_quirk(quirks_ptr[i].first, quirks_ptr[i].second); + } + + // Apply flags. +@@ -63397,8 +79965,7 @@ redirect: + } else if (io_buf.meta.closed) { + return DecodeImageResult(DecodeImage_UnexpectedEndOfFile); + } else { +- std::string error_message = +- input.CopyIn(&io_buf, image_decoder->history_retain_length()); ++ std::string error_message = input.CopyIn(&io_buf); + if (!error_message.empty()) { + return DecodeImageResult(std::move(error_message)); + } +@@ -63480,8 +80047,7 @@ redirect: + } else if (io_buf.meta.closed) { + return DecodeImageResult(DecodeImage_UnexpectedEndOfFile); + } else { +- std::string error_message = +- input.CopyIn(&io_buf, image_decoder->history_retain_length()); ++ std::string error_message = input.CopyIn(&io_buf); + if (!error_message.empty()) { + return DecodeImageResult(std::move(error_message)); + } +@@ -63510,8 +80076,7 @@ redirect: + message = DecodeImage_UnexpectedEndOfFile; + break; + } else { +- std::string error_message = +- input.CopyIn(&io_buf, image_decoder->history_retain_length()); ++ std::string error_message = input.CopyIn(&io_buf); + if (!error_message.empty()) { + message = std::move(error_message); + break; +@@ -63539,8 +80104,7 @@ redirect: + } else if (io_buf.meta.closed) { + return DecodeImageResult(DecodeImage_UnexpectedEndOfFile); + } else { +- std::string error_message = +- input.CopyIn(&io_buf, image_decoder->history_retain_length()); ++ std::string error_message = input.CopyIn(&io_buf); + if (!error_message.empty()) { + return DecodeImageResult(std::move(error_message)); + } +@@ -63574,10 +80138,10 @@ DecodeImage(DecodeImageCallbacks& callbacks, + } + + wuffs_base__image_decoder::unique_ptr image_decoder(nullptr); +- DecodeImageResult result = +- DecodeImage0(image_decoder, callbacks, input, *io_buf, quirks.repr, +- flags.repr, pixel_blend.repr, background_color.repr, +- max_incl_dimension.repr, max_incl_metadata_length.repr); ++ DecodeImageResult result = DecodeImage0( ++ image_decoder, callbacks, input, *io_buf, quirks.ptr, quirks.len, ++ flags.repr, pixel_blend.repr, background_color.repr, ++ max_incl_dimension.repr, max_incl_metadata_length.repr); + callbacks.Done(result, input, *io_buf, std::move(image_decoder)); + return result; + } +@@ -63612,15 +80176,13 @@ const char DecodeJson_BadJsonPointer[] = // + const char DecodeJson_NoMatch[] = // + "wuffs_aux::DecodeJson: no match"; + +-DecodeJsonArgQuirks::DecodeJsonArgQuirks(wuffs_base__slice_u32 repr0) +- : repr(repr0) {} +- +-DecodeJsonArgQuirks::DecodeJsonArgQuirks(uint32_t* ptr0, size_t len0) +- : repr(wuffs_base__make_slice_u32(ptr0, len0)) {} ++DecodeJsonArgQuirks::DecodeJsonArgQuirks(const QuirkKeyValuePair* ptr0, ++ const size_t len0) ++ : ptr(ptr0), len(len0) {} + + DecodeJsonArgQuirks // + DecodeJsonArgQuirks::DefaultValue() { +- return DecodeJsonArgQuirks(wuffs_base__empty_slice_u32()); ++ return DecodeJsonArgQuirks(nullptr, 0); + } + + DecodeJsonArgJsonPointer::DecodeJsonArgJsonPointer(std::string repr0) +@@ -63633,58 +80195,58 @@ DecodeJsonArgJsonPointer::DefaultValue() { + + // -------- + +-#define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN \ +- while (tok_buf.meta.ri >= tok_buf.meta.wi) { \ +- if (tok_status.repr == nullptr) { \ +- goto done; \ +- } else if (tok_status.repr == wuffs_base__suspension__short_write) { \ +- tok_buf.compact(); \ +- } else if (tok_status.repr == wuffs_base__suspension__short_read) { \ +- if (!io_error_message.empty()) { \ +- ret_error_message = std::move(io_error_message); \ +- goto done; \ +- } else if (cursor_index != io_buf->meta.ri) { \ +- ret_error_message = \ +- "wuffs_aux::DecodeJson: internal error: bad cursor_index"; \ +- goto done; \ +- } else if (io_buf->meta.closed) { \ +- ret_error_message = \ +- "wuffs_aux::DecodeJson: internal error: io_buf is closed"; \ +- goto done; \ +- } \ +- io_buf->compact_retaining(dec->history_retain_length()); \ +- if (io_buf->meta.wi >= io_buf->data.len) { \ +- ret_error_message = \ +- "wuffs_aux::DecodeJson: internal error: io_buf is full"; \ +- goto done; \ +- } \ +- cursor_index = io_buf->meta.ri; \ +- io_error_message = input.CopyIn(io_buf, dec->history_retain_length()); \ +- } else { \ +- ret_error_message = tok_status.message(); \ +- goto done; \ +- } \ +- tok_status = \ +- dec->decode_tokens(&tok_buf, io_buf, wuffs_base__empty_slice_u8()); \ +- if ((tok_buf.meta.ri > tok_buf.meta.wi) || \ +- (tok_buf.meta.wi > tok_buf.data.len) || \ +- (io_buf->meta.ri > io_buf->meta.wi) || \ +- (io_buf->meta.wi > io_buf->data.len)) { \ +- ret_error_message = \ +- "wuffs_aux::DecodeJson: internal error: bad buffer indexes"; \ +- goto done; \ +- } \ +- } \ +- wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++]; \ +- uint64_t token_len = token.length(); \ +- if ((io_buf->meta.ri < cursor_index) || \ +- ((io_buf->meta.ri - cursor_index) < token_len)) { \ +- ret_error_message = \ +- "wuffs_aux::DecodeJson: internal error: bad token indexes"; \ +- goto done; \ +- } \ +- uint8_t* token_ptr = io_buf->data.ptr + cursor_index; \ +- (void)(token_ptr); \ ++#define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN \ ++ while (tok_buf.meta.ri >= tok_buf.meta.wi) { \ ++ if (tok_status.repr == nullptr) { \ ++ goto done; \ ++ } else if (tok_status.repr == wuffs_base__suspension__short_write) { \ ++ tok_buf.compact(); \ ++ } else if (tok_status.repr == wuffs_base__suspension__short_read) { \ ++ if (!io_error_message.empty()) { \ ++ ret_error_message = std::move(io_error_message); \ ++ goto done; \ ++ } else if (cursor_index != io_buf->meta.ri) { \ ++ ret_error_message = \ ++ "wuffs_aux::DecodeJson: internal error: bad cursor_index"; \ ++ goto done; \ ++ } else if (io_buf->meta.closed) { \ ++ ret_error_message = \ ++ "wuffs_aux::DecodeJson: internal error: io_buf is closed"; \ ++ goto done; \ ++ } \ ++ io_buf->compact(); \ ++ if (io_buf->meta.wi >= io_buf->data.len) { \ ++ ret_error_message = \ ++ "wuffs_aux::DecodeJson: internal error: io_buf is full"; \ ++ goto done; \ ++ } \ ++ cursor_index = io_buf->meta.ri; \ ++ io_error_message = input.CopyIn(io_buf); \ ++ } else { \ ++ ret_error_message = tok_status.message(); \ ++ goto done; \ ++ } \ ++ tok_status = \ ++ dec->decode_tokens(&tok_buf, io_buf, wuffs_base__empty_slice_u8()); \ ++ if ((tok_buf.meta.ri > tok_buf.meta.wi) || \ ++ (tok_buf.meta.wi > tok_buf.data.len) || \ ++ (io_buf->meta.ri > io_buf->meta.wi) || \ ++ (io_buf->meta.wi > io_buf->data.len)) { \ ++ ret_error_message = \ ++ "wuffs_aux::DecodeJson: internal error: bad buffer indexes"; \ ++ goto done; \ ++ } \ ++ } \ ++ wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++]; \ ++ uint64_t token_len = token.length(); \ ++ if ((io_buf->meta.ri < cursor_index) || \ ++ ((io_buf->meta.ri - cursor_index) < token_len)) { \ ++ ret_error_message = \ ++ "wuffs_aux::DecodeJson: internal error: bad token indexes"; \ ++ goto done; \ ++ } \ ++ uint8_t* token_ptr = io_buf->data.ptr + cursor_index; \ ++ (void)(token_ptr); \ + cursor_index += static_cast(token_len) + + // -------- +@@ -63965,11 +80527,11 @@ DecodeJson(DecodeJsonCallbacks& callbacks, + goto done; + } + bool allow_tilde_n_tilde_r_tilde_t = false; +- for (size_t i = 0; i < quirks.repr.len; i++) { +- dec->set_quirk(quirks.repr.ptr[i], 1); +- if (quirks.repr.ptr[i] == ++ for (size_t i = 0; i < quirks.len; i++) { ++ dec->set_quirk(quirks.ptr[i].first, quirks.ptr[i].second); ++ if (quirks.ptr[i].first == + WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_N_TILDE_R_TILDE_T) { +- allow_tilde_n_tilde_r_tilde_t = true; ++ allow_tilde_n_tilde_r_tilde_t = (quirks.ptr[i].second != 0); + } + } + +@@ -64025,7 +80587,7 @@ DecodeJson(DecodeJsonCallbacks& callbacks, + goto done; + } + depth++; +- if (depth > WUFFS_JSON__DECODER_DEPTH_MAX_INCL) { ++ if (depth > (int32_t)WUFFS_JSON__DECODER_DEPTH_MAX_INCL) { + ret_error_message = + "wuffs_aux::DecodeJson: internal error: bad depth"; + goto done; +-- +2.39.2 + diff --git a/patches/coreboot-24.02.01/0002-increase_heap_from1mb_to4mb_when_bootpslash_enabled.patch b/patches/coreboot-24.02.01/0002-increase_heap_from1mb_to4mb_when_bootpslash_enabled.patch deleted file mode 100644 index a31118c1..00000000 --- a/patches/coreboot-24.02.01/0002-increase_heap_from1mb_to4mb_when_bootpslash_enabled.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 00d695849a5fb503d87203e3515f761fa8dac850 Mon Sep 17 00:00:00 2001 -From: Jonathon Hall -Date: Mon, 15 Jul 2024 16:37:40 -0400 -Subject: [PATCH] bootsplash: Increase heap from 1 MB to 4 MB when bootsplash - is enabled - -Since commit 1d029b40c9de ("lib/jpeg: Replace decoder with Wuffs' -implementation"), a relatively large heap allocation is needed to -decode many JPEGs for use as work area. The prior decoder did not need -this, but also had many limitations in the JPEGs it could decode. - -A 1024x768 non-progressive JPEG used in Heads needs 1179648 bytes of -work area; about 1.2 MB. While the work area will also depend on the -subsampling of each channel, it's generally proportional to the image -size. - -Increasing the heap size to 4 MB when bootsplash is enabled should be -enough to decode bootsplashes up to 1920x1080 with some headroom. - -Change-Id: Ia4348d39effbc16c1b42ab01bcf1e4ec5d652fa9 -Signed-off-by: Jonathon Hall ---- - src/device/Kconfig | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/device/Kconfig b/src/device/Kconfig -index 243e23e52a..4dd03eba21 100644 ---- a/src/device/Kconfig -+++ b/src/device/Kconfig -@@ -501,6 +501,11 @@ config BOOTSPLASH - image in the 'General' section or add it manually to CBFS, using, - for example, cbfstool. - -+# The bootsplash JPEG decoder requires heap space approximately proportional to -+# the image size. This usually needs a larger heap. -+config HEAP_SIZE -+ default 0x400000 if BOOTSPLASH -+ - config LINEAR_FRAMEBUFFER_MAX_WIDTH - int "Maximum width in pixels" - depends on LINEAR_FRAMEBUFFER && MAINBOARD_USE_LIBGFXINIT --- -2.39.2 - diff --git a/patches/coreboot-24.02.01/0002-lib_jpeg-avoidcalling-malloc-and-free.patch b/patches/coreboot-24.02.01/0002-lib_jpeg-avoidcalling-malloc-and-free.patch new file mode 100644 index 00000000..fa131062 --- /dev/null +++ b/patches/coreboot-24.02.01/0002-lib_jpeg-avoidcalling-malloc-and-free.patch @@ -0,0 +1,91 @@ +From efad423f8472c1b9c130842e3d92625500f82d5d Mon Sep 17 00:00:00 2001 +From: Nigel Tao +Date: Tue, 13 Aug 2024 22:29:21 +1000 +Subject: [PATCH] lib/jpeg: avoid calling malloc and free + +Since commit 1d029b40c9de ("lib/jpeg: Replace decoder with Wuffs' +implementation"), a relatively large heap allocation is needed to decode +many JPEGs for use as work area. The prior decoder did not need this, +but also had many limitations in the JPEGs it could decode, was not as +memory-safe and quickly crashed under fuzzing. + +This commit keeps using Wuffs' JPEG decoder, but it no longer requires +any heap allocation (and thus configuring the heap size depending on how +big a bootsplash image you want to support). + +Change-Id: Ie4c52520cbce498539517c4898ff765365a6beba +Signed-off-by: Nigel Tao +Reviewed-on: https://review.coreboot.org/c/coreboot/+/83895 +Tested-by: build bot (Jenkins) +Reviewed-by: Nico Huber +Reviewed-by: Felix Singer +Reviewed-by: Jonathon Hall +--- + src/lib/jpeg.c | 36 +++++++++++++++++++++--------------- + 1 file changed, 21 insertions(+), 15 deletions(-) + +diff --git a/src/lib/jpeg.c b/src/lib/jpeg.c +index 242cf0ca8e..617ab0b22a 100644 +--- a/src/lib/jpeg.c ++++ b/src/lib/jpeg.c +@@ -1,9 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + + /* +- * Provide a simple API around the Wuffs JPEG decoder +- * Uses the heap (and lots of it) for the image-size specific +- * work buffer, so ramstage-only. ++ * Provide a simple API around the Wuffs JPEG decoder. + */ + + #include +@@ -85,6 +83,24 @@ int jpeg_decode(unsigned char *filedata, size_t filesize, unsigned char *pic, + return JPEG_DECODE_FAILED; + } + ++ /* Opting in to lower quality means that we can pass an empty slice as the ++ * "work buffer" argument to wuffs_jpeg__decoder__decode_frame below. ++ * ++ * Decoding progressive (not sequential) JPEGs would still require dynamic ++ * memory allocation (and the amount of work buffer required depends on the ++ * image dimensions), but we choose to just reject progressive JPEGs. It is ++ * simpler than sometimes calling malloc (which can fail, especially for ++ * large allocations) and free. ++ * ++ * More commentary about these quirks is at ++ * https://github.com/google/wuffs/blob/beaf45650085a16780b5f708b72daaeb1aa865c8/std/jpeg/decode_quirks.wuffs ++ */ ++ wuffs_jpeg__decoder__set_quirk( ++ &dec, WUFFS_BASE__QUIRK_QUALITY, ++ WUFFS_BASE__QUIRK_QUALITY__VALUE__LOWER_QUALITY); ++ wuffs_jpeg__decoder__set_quirk( ++ &dec, WUFFS_JPEG__QUIRK_REJECT_PROGRESSIVE_JPEGS, 1); ++ + wuffs_base__image_config imgcfg; + wuffs_base__io_buffer src = wuffs_base__ptr_u8__reader(filedata, filesize, true); + status = wuffs_jpeg__decoder__decode_image_config(&dec, &imgcfg, &src); +@@ -104,19 +120,9 @@ int jpeg_decode(unsigned char *filedata, size_t filesize, unsigned char *pic, + return JPEG_DECODE_FAILED; + } + +- uint64_t workbuf_len_min_incl = wuffs_jpeg__decoder__workbuf_len(&dec).min_incl; +- uint8_t *workbuf_array = malloc(workbuf_len_min_incl); +- if ((workbuf_array == NULL) && workbuf_len_min_incl) { +- return JPEG_DECODE_FAILED; +- } +- +- wuffs_base__slice_u8 workbuf = +- wuffs_base__make_slice_u8(workbuf_array, workbuf_len_min_incl); + status = wuffs_jpeg__decoder__decode_frame(&dec, &pixbuf, &src, +- WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL); +- +- free(workbuf_array); +- ++ WUFFS_BASE__PIXEL_BLEND__SRC, ++ wuffs_base__empty_slice_u8(), NULL); + if (status.repr) { + return JPEG_DECODE_FAILED; + } +-- +2.39.2 + From cd64f3cc2ac9651ca4fd901a97cfd5897b9b34b1 Mon Sep 17 00:00:00 2001 From: Jonathon Hall Date: Fri, 18 Oct 2024 17:22:03 -0400 Subject: [PATCH 02/17] modules/coreboot: Update Purism coreboot with latest JPEG decoder patch Instead of requesting additional ramstage heap, cherry-pick patches for newer JPEG decoder that does not require heap allocation. Signed-off-by: Jonathon Hall Signed-off-by: Thierry Laurion --- modules/coreboot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/coreboot b/modules/coreboot index 13fc943f..23de9a45 100644 --- a/modules/coreboot +++ b/modules/coreboot @@ -88,7 +88,7 @@ $(eval $(call coreboot_module,talos_2,)) # coreboot-purism is based on 24.02.01 - reuse that toolchain. coreboot-purism_repo := https://source.puri.sm/firmware/coreboot.git -coreboot-purism_commit_hash := f4f61b75bcfc50fa3a89f8f438e5312e750f6e3c +coreboot-purism_commit_hash := bea9947a1279be7d4a72b38a601d0288d10d1cb8 $(eval $(call coreboot_module,purism,24.02.01)) # MSI and Nitropad NV41 / NS50 boards are based on Dasharo coreboot port From f82785565de7316c7c435e8483c6c80154002f79 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 19 Oct 2024 09:31:05 -0400 Subject: [PATCH 03/17] librems coreboot configs: apply coreboot.save_in_oldconfig_format_in_place Signed-off-by: Thierry Laurion --- config/coreboot-librem_11.config | 2 +- config/coreboot-librem_13v2.config | 2 +- config/coreboot-librem_13v4.config | 2 +- config/coreboot-librem_14.config | 2 +- config/coreboot-librem_15v3.config | 2 +- config/coreboot-librem_15v4.config | 2 +- config/coreboot-librem_l1um_v2.config | 2 +- config/coreboot-librem_mini.config | 2 +- config/coreboot-librem_mini_v2.config | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config/coreboot-librem_11.config b/config/coreboot-librem_11.config index e4fb403d..a1e0af90 100644 --- a/config/coreboot-librem_11.config +++ b/config/coreboot-librem_11.config @@ -478,7 +478,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -623,6 +622,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-librem_13v2.config b/config/coreboot-librem_13v2.config index 699c54a3..31494c99 100644 --- a/config/coreboot-librem_13v2.config +++ b/config/coreboot-librem_13v2.config @@ -501,7 +501,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -662,6 +661,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-librem_13v4.config b/config/coreboot-librem_13v4.config index 84b37ae2..1aaba3d4 100644 --- a/config/coreboot-librem_13v4.config +++ b/config/coreboot-librem_13v4.config @@ -501,7 +501,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -662,6 +661,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-librem_14.config b/config/coreboot-librem_14.config index f72db439..6333e19d 100644 --- a/config/coreboot-librem_14.config +++ b/config/coreboot-librem_14.config @@ -498,7 +498,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -668,6 +667,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-librem_15v3.config b/config/coreboot-librem_15v3.config index 395a8be8..d8565415 100644 --- a/config/coreboot-librem_15v3.config +++ b/config/coreboot-librem_15v3.config @@ -501,7 +501,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -662,6 +661,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-librem_15v4.config b/config/coreboot-librem_15v4.config index dd16e94c..f277f7c5 100644 --- a/config/coreboot-librem_15v4.config +++ b/config/coreboot-librem_15v4.config @@ -501,7 +501,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -662,6 +661,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-librem_l1um_v2.config b/config/coreboot-librem_l1um_v2.config index ca70ea96..b9b6edb9 100644 --- a/config/coreboot-librem_l1um_v2.config +++ b/config/coreboot-librem_l1um_v2.config @@ -498,7 +498,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -658,6 +657,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-librem_mini.config b/config/coreboot-librem_mini.config index 62d2c37d..d4842e18 100644 --- a/config/coreboot-librem_mini.config +++ b/config/coreboot-librem_mini.config @@ -502,7 +502,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -650,6 +649,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-librem_mini_v2.config b/config/coreboot-librem_mini_v2.config index 85ed80b7..cbe34a87 100644 --- a/config/coreboot-librem_mini_v2.config +++ b/config/coreboot-librem_mini_v2.config @@ -504,7 +504,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x100000 # end of Display CONFIG_PCI=y @@ -657,6 +656,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console From ee6e05b2bd83280bb2a47e09ca097d89f16badce Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 30 Oct 2024 09:52:18 -0400 Subject: [PATCH 04/17] Optiplex coreboot configs: coreboot.modify_and_save_oldconfig_in_place to fix CONFIG_HEAP_SIZE Did for TXT/non-TXT boards: docker run -e DISPLAY=$DISPLAY --network host --rm -ti -v $(pwd):$(pwd) -w $(pwd) tlaurion/heads-dev-env:latest -- make BOARD=optiplex-7010_9010*-hotp-maximized coreboot.modify_and_save_oldconfig_in_place Signed-off-by: Thierry Laurion --- config/coreboot-optiplex-7019_9010-maximized.config | 2 +- config/coreboot-optiplex-7019_9010_TXT-maximized.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/coreboot-optiplex-7019_9010-maximized.config b/config/coreboot-optiplex-7019_9010-maximized.config index 7e07d902..97d00972 100644 --- a/config/coreboot-optiplex-7019_9010-maximized.config +++ b/config/coreboot-optiplex-7019_9010-maximized.config @@ -385,7 +385,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 # end of Display CONFIG_PCI=y @@ -535,6 +534,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console diff --git a/config/coreboot-optiplex-7019_9010_TXT-maximized.config b/config/coreboot-optiplex-7019_9010_TXT-maximized.config index 6f2d4fd4..03be491e 100644 --- a/config/coreboot-optiplex-7019_9010_TXT-maximized.config +++ b/config/coreboot-optiplex-7019_9010_TXT-maximized.config @@ -389,7 +389,6 @@ CONFIG_NO_EARLY_GFX_INIT=y CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y CONFIG_LINEAR_FRAMEBUFFER=y CONFIG_BOOTSPLASH=y -CONFIG_HEAP_SIZE=0x400000 # end of Display CONFIG_PCI=y @@ -549,6 +548,7 @@ CONFIG_BOOT_DEVICE_SPI_FLASH=y CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y CONFIG_BOOT_DEVICE_SUPPORTS_WRITES=y CONFIG_RTC=y +CONFIG_HEAP_SIZE=0x100000 # # Console From 0679b75e1dee391ea2f7301cec6fcf6d8dc4a851 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 16 Aug 2024 15:08:45 -0400 Subject: [PATCH 05/17] Bump 5.10.5 kernel to 5.10.214 Cloudfare patches to speed up LUKS encryption were upstreamed into linux kernel and backported to 5.10.9: https://github.com/cloudflare/linux/issues/1#issuecomment-763085915 Therefore, we bump to latest of 5.10.x (bump from 5.10.5 which doesn't contain the fixes) Trace: sed -i 's/5.10.5/5.10.214/g' boards/*/*.config find ./boards/*/*.config | awk -F "/" {'print $3'}| while read board; do echo "make BOARD=$board linux"; make BOARD=$board linux; echo make BOARD=$board linux.save_in_oldconfig_format_in_place || make BOARD=$board linux.modify_and_save_oldconfig_in_place; done git status | grep modified | awk -F ":" {'print $2'}| xargs git add git commit --signoff - Move patches from 5.10.5 -> 5.10.214 - Add linux kernel hash and version under modules/linux - Change board configs accordingly Signed-off-by: Thierry Laurion --- ...MAINTAINED_kgpe-d16_server-whiptail.config | 2 +- .../UNMAINTAINED_kgpe-d16_server.config | 2 +- ...D_kgpe-d16_workstation-usb_keyboard.config | 2 +- .../UNMAINTAINED_kgpe-d16_workstation.config | 2 +- boards/librem_l1um/librem_l1um.config | 2 +- .../qemu-coreboot-fbwhiptail-tpm1-hotp.config | 2 +- .../qemu-coreboot-fbwhiptail-tpm1.config | 2 +- .../qemu-coreboot-fbwhiptail-tpm2-hotp.config | 2 +- .../qemu-coreboot-fbwhiptail-tpm2.config | 2 +- .../qemu-coreboot-whiptail-tpm1-hotp.config | 2 +- .../qemu-coreboot-whiptail-tpm1.config | 2 +- .../qemu-coreboot-whiptail-tpm2-hotp.config | 2 +- .../qemu-coreboot-whiptail-tpm2.config | 2 +- .../t420-hotp-maximized.config | 2 +- boards/t420-maximized/t420-maximized.config | 2 +- .../t430-hotp-maximized.config | 2 +- boards/t430-maximized/t430-maximized.config | 2 +- boards/t440p-maximized/t440p-maximized.config | 2 +- .../t530-hotp-maximized.config | 2 +- boards/t530-maximized/t530-maximized.config | 2 +- .../w530-hotp-maximized.config | 2 +- boards/w530-maximized/w530-maximized.config | 2 +- boards/w541-maximized/w541-maximized.config | 2 +- .../x220-hotp-maximized.config | 2 +- boards/x220-maximized/x220-maximized.config | 2 +- .../x230-hotp-maximized-fhd_edp.config | 2 +- .../x230-hotp-maximized.config | 2 +- .../x230-hotp-maximized_usb-kb.config | 2 +- .../x230-maximized-fhd_edp.config | 2 +- boards/x230-maximized/x230-maximized.config | 2 +- .../z220-cmt-maximized.config | 2 +- config/linux-c216.config | 62 ++-- config/linux-kgpe-d16_server-whiptail.config | 274 +++++++++++++++-- config/linux-kgpe-d16_server.config | 277 ++++++++++++++++-- config/linux-kgpe-d16_workstation.config | 62 ++-- config/linux-librem_common.config | 60 ++-- config/linux-qemu.config | 67 +++-- config/linux-t440p.config | 62 ++-- config/linux-talos-2.config | 2 +- config/linux-w541.config | 62 ++-- config/linux-x230-flash.config | 45 ++- config/linux-x230-legacy.config | 60 ++-- config/linux-x230-maximized.config | 63 ++-- modules/linux | 6 +- .../0001-fake-acpi.patch | 0 .../0002-nmi-squelch.patch | 0 .../0003-fake-trampoline.patch | 0 .../0010-winterfell-ahci.patch | 0 patches/linux-5.10.214/shebangs.patch | 40 +++ ...ubcmd_Fix_use-after-free-for-realloc.patch | 64 ---- patches/linux-5.10.5/shebangs.patch | 100 ------- 51 files changed, 940 insertions(+), 428 deletions(-) rename patches/{linux-5.10.5 => linux-5.10.214}/0001-fake-acpi.patch (100%) rename patches/{linux-5.10.5 => linux-5.10.214}/0002-nmi-squelch.patch (100%) rename patches/{linux-5.10.5 => linux-5.10.214}/0003-fake-trampoline.patch (100%) rename patches/{linux-5.10.5 => linux-5.10.214}/0010-winterfell-ahci.patch (100%) create mode 100644 patches/linux-5.10.214/shebangs.patch delete mode 100644 patches/linux-5.10.5/0004-libsubcmd_Fix_use-after-free-for-realloc.patch delete mode 100644 patches/linux-5.10.5/shebangs.patch diff --git a/boards/UNMAINTAINED_kgpe-d16_server-whiptail/UNMAINTAINED_kgpe-d16_server-whiptail.config b/boards/UNMAINTAINED_kgpe-d16_server-whiptail/UNMAINTAINED_kgpe-d16_server-whiptail.config index 3a847c26..8fc8b55d 100644 --- a/boards/UNMAINTAINED_kgpe-d16_server-whiptail/UNMAINTAINED_kgpe-d16_server-whiptail.config +++ b/boards/UNMAINTAINED_kgpe-d16_server-whiptail/UNMAINTAINED_kgpe-d16_server-whiptail.config @@ -19,7 +19,7 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.11 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-kgpe-d16_server-whiptail.config CONFIG_LINUX_CONFIG=config/linux-kgpe-d16_server-whiptail.config diff --git a/boards/UNMAINTAINED_kgpe-d16_server/UNMAINTAINED_kgpe-d16_server.config b/boards/UNMAINTAINED_kgpe-d16_server/UNMAINTAINED_kgpe-d16_server.config index 5f363add..7b905ecd 100644 --- a/boards/UNMAINTAINED_kgpe-d16_server/UNMAINTAINED_kgpe-d16_server.config +++ b/boards/UNMAINTAINED_kgpe-d16_server/UNMAINTAINED_kgpe-d16_server.config @@ -17,7 +17,7 @@ # - Please support https://github.com/osresearch/heads/issues/719 export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.11 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-kgpe-d16_server.config CONFIG_LINUX_CONFIG=config/linux-kgpe-d16_server.config diff --git a/boards/UNMAINTAINED_kgpe-d16_workstation-usb_keyboard/UNMAINTAINED_kgpe-d16_workstation-usb_keyboard.config b/boards/UNMAINTAINED_kgpe-d16_workstation-usb_keyboard/UNMAINTAINED_kgpe-d16_workstation-usb_keyboard.config index 235d579a..dbe8b385 100644 --- a/boards/UNMAINTAINED_kgpe-d16_workstation-usb_keyboard/UNMAINTAINED_kgpe-d16_workstation-usb_keyboard.config +++ b/boards/UNMAINTAINED_kgpe-d16_workstation-usb_keyboard/UNMAINTAINED_kgpe-d16_workstation-usb_keyboard.config @@ -13,7 +13,7 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.11 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-kgpe-d16_workstation-usb_keyboard.config CONFIG_LINUX_CONFIG=config/linux-kgpe-d16_workstation.config diff --git a/boards/UNMAINTAINED_kgpe-d16_workstation/UNMAINTAINED_kgpe-d16_workstation.config b/boards/UNMAINTAINED_kgpe-d16_workstation/UNMAINTAINED_kgpe-d16_workstation.config index e927edab..77eae687 100644 --- a/boards/UNMAINTAINED_kgpe-d16_workstation/UNMAINTAINED_kgpe-d16_workstation.config +++ b/boards/UNMAINTAINED_kgpe-d16_workstation/UNMAINTAINED_kgpe-d16_workstation.config @@ -17,7 +17,7 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.11 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-kgpe-d16_workstation.config CONFIG_LINUX_CONFIG=config/linux-kgpe-d16_workstation.config diff --git a/boards/librem_l1um/librem_l1um.config b/boards/librem_l1um/librem_l1um.config index ed8dc176..1b0af69c 100644 --- a/boards/librem_l1um/librem_l1um.config +++ b/boards/librem_l1um/librem_l1um.config @@ -4,7 +4,7 @@ CONFIG_COREBOOT_CONFIG=config/coreboot-librem_l1um.config export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.11 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 export CONFIG_PURISM_BLOBS=y CONFIG_CRYPTSETUP2=y diff --git a/boards/qemu-coreboot-fbwhiptail-tpm1-hotp/qemu-coreboot-fbwhiptail-tpm1-hotp.config b/boards/qemu-coreboot-fbwhiptail-tpm1-hotp/qemu-coreboot-fbwhiptail-tpm1-hotp.config index 665cb0e4..6e406aa0 100644 --- a/boards/qemu-coreboot-fbwhiptail-tpm1-hotp/qemu-coreboot-fbwhiptail-tpm1-hotp.config +++ b/boards/qemu-coreboot-fbwhiptail-tpm1-hotp/qemu-coreboot-fbwhiptail-tpm1-hotp.config @@ -6,7 +6,7 @@ # the VM. export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm1.config CONFIG_LINUX_CONFIG=config/linux-qemu.config diff --git a/boards/qemu-coreboot-fbwhiptail-tpm1/qemu-coreboot-fbwhiptail-tpm1.config b/boards/qemu-coreboot-fbwhiptail-tpm1/qemu-coreboot-fbwhiptail-tpm1.config index 81558e82..0482e20d 100644 --- a/boards/qemu-coreboot-fbwhiptail-tpm1/qemu-coreboot-fbwhiptail-tpm1.config +++ b/boards/qemu-coreboot-fbwhiptail-tpm1/qemu-coreboot-fbwhiptail-tpm1.config @@ -4,7 +4,7 @@ # TPM can be used with a qemu software TPM (TIS, 1.2). export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm2.config CONFIG_LINUX_CONFIG=config/linux-qemu.config diff --git a/boards/qemu-coreboot-fbwhiptail-tpm2-hotp/qemu-coreboot-fbwhiptail-tpm2-hotp.config b/boards/qemu-coreboot-fbwhiptail-tpm2-hotp/qemu-coreboot-fbwhiptail-tpm2-hotp.config index 21750ddc..498b2df8 100644 --- a/boards/qemu-coreboot-fbwhiptail-tpm2-hotp/qemu-coreboot-fbwhiptail-tpm2-hotp.config +++ b/boards/qemu-coreboot-fbwhiptail-tpm2-hotp/qemu-coreboot-fbwhiptail-tpm2-hotp.config @@ -5,7 +5,7 @@ # TPM can be used with a qemu software TPM (TIS, 2.0). export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm2.config CONFIG_LINUX_CONFIG=config/linux-qemu.config diff --git a/boards/qemu-coreboot-fbwhiptail-tpm2/qemu-coreboot-fbwhiptail-tpm2.config b/boards/qemu-coreboot-fbwhiptail-tpm2/qemu-coreboot-fbwhiptail-tpm2.config index 94881db3..f9275f31 100644 --- a/boards/qemu-coreboot-fbwhiptail-tpm2/qemu-coreboot-fbwhiptail-tpm2.config +++ b/boards/qemu-coreboot-fbwhiptail-tpm2/qemu-coreboot-fbwhiptail-tpm2.config @@ -4,7 +4,7 @@ # TPM can be used with a qemu software TPM (TIS, 2.0). export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm2.config CONFIG_LINUX_CONFIG=config/linux-qemu.config diff --git a/boards/qemu-coreboot-whiptail-tpm1-hotp/qemu-coreboot-whiptail-tpm1-hotp.config b/boards/qemu-coreboot-whiptail-tpm1-hotp/qemu-coreboot-whiptail-tpm1-hotp.config index 68f0acf0..f34c8b89 100644 --- a/boards/qemu-coreboot-whiptail-tpm1-hotp/qemu-coreboot-whiptail-tpm1-hotp.config +++ b/boards/qemu-coreboot-whiptail-tpm1-hotp/qemu-coreboot-whiptail-tpm1-hotp.config @@ -6,7 +6,7 @@ # the VM. export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm1.config CONFIG_LINUX_CONFIG=config/linux-qemu.config diff --git a/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config b/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config index c700478c..ec1f6cde 100644 --- a/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config +++ b/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config @@ -4,7 +4,7 @@ # TPM can be used with a qemu software TPM (TIS, 1.2). export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm1.config CONFIG_LINUX_CONFIG=config/linux-qemu.config diff --git a/boards/qemu-coreboot-whiptail-tpm2-hotp/qemu-coreboot-whiptail-tpm2-hotp.config b/boards/qemu-coreboot-whiptail-tpm2-hotp/qemu-coreboot-whiptail-tpm2-hotp.config index 6574dc3e..3fc6fa9f 100644 --- a/boards/qemu-coreboot-whiptail-tpm2-hotp/qemu-coreboot-whiptail-tpm2-hotp.config +++ b/boards/qemu-coreboot-whiptail-tpm2-hotp/qemu-coreboot-whiptail-tpm2-hotp.config @@ -5,7 +5,7 @@ # TPM can be used with a qemu software TPM (TIS, 2.0). export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm2.config CONFIG_LINUX_CONFIG=config/linux-qemu.config diff --git a/boards/qemu-coreboot-whiptail-tpm2/qemu-coreboot-whiptail-tpm2.config b/boards/qemu-coreboot-whiptail-tpm2/qemu-coreboot-whiptail-tpm2.config index 01952122..2b4b3caa 100644 --- a/boards/qemu-coreboot-whiptail-tpm2/qemu-coreboot-whiptail-tpm2.config +++ b/boards/qemu-coreboot-whiptail-tpm2/qemu-coreboot-whiptail-tpm2.config @@ -4,7 +4,7 @@ # TPM can be used with a qemu software TPM (TIS, 2.0). export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm2.config CONFIG_LINUX_CONFIG=config/linux-qemu.config diff --git a/boards/t420-hotp-maximized/t420-hotp-maximized.config b/boards/t420-hotp-maximized/t420-hotp-maximized.config index dbdeda6a..f3019d2c 100644 --- a/boards/t420-hotp-maximized/t420-hotp-maximized.config +++ b/boards/t420-hotp-maximized/t420-hotp-maximized.config @@ -10,7 +10,7 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-t420-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/t420-maximized/t420-maximized.config b/boards/t420-maximized/t420-maximized.config index 2bd5aaaa..e44175e5 100644 --- a/boards/t420-maximized/t420-maximized.config +++ b/boards/t420-maximized/t420-maximized.config @@ -9,7 +9,7 @@ # - dropbear export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-t420-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/t430-hotp-maximized/t430-hotp-maximized.config b/boards/t430-hotp-maximized/t430-hotp-maximized.config index 1861c64c..c1efccd9 100644 --- a/boards/t430-hotp-maximized/t430-hotp-maximized.config +++ b/boards/t430-hotp-maximized/t430-hotp-maximized.config @@ -8,7 +8,7 @@ # - Includes Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-t430-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/t430-maximized/t430-maximized.config b/boards/t430-maximized/t430-maximized.config index 0a804940..acc7b54f 100644 --- a/boards/t430-maximized/t430-maximized.config +++ b/boards/t430-maximized/t430-maximized.config @@ -8,7 +8,7 @@ # - DOES NOT INCLUDE Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-t430-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/t440p-maximized/t440p-maximized.config b/boards/t440p-maximized/t440p-maximized.config index 22aeb9c6..b6ad3c89 100644 --- a/boards/t440p-maximized/t440p-maximized.config +++ b/boards/t440p-maximized/t440p-maximized.config @@ -5,7 +5,7 @@ CONFIG_LINUX_CONFIG=config/linux-t440p.config export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_CRYPTSETUP2=y CONFIG_FLASHPROG=y diff --git a/boards/t530-hotp-maximized/t530-hotp-maximized.config b/boards/t530-hotp-maximized/t530-hotp-maximized.config index f237b3db..234259db 100644 --- a/boards/t530-hotp-maximized/t530-hotp-maximized.config +++ b/boards/t530-hotp-maximized/t530-hotp-maximized.config @@ -9,7 +9,7 @@ # This board is designed for a t530 without a dGPU. It will work just fine for a board with a dGPU, except you will not be able to use an external monitor via the mini-displayport or the dock's displayport, though external monitors will work via VGA ports. To initialize the dGPU please use one of the dgpu boards. export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-t530-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/t530-maximized/t530-maximized.config b/boards/t530-maximized/t530-maximized.config index 84acd68c..62cda1ab 100644 --- a/boards/t530-maximized/t530-maximized.config +++ b/boards/t530-maximized/t530-maximized.config @@ -9,7 +9,7 @@ # This board is designed for a t530 without a dGPU. It will work just fine for a board with a dGPU, except you will not be able to use an external monitor via the mini-displayport or the dock's displayport, though external monitors will work via VGA ports. To initialize the dGPU please use one of the dgpu boards. export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-t530-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/w530-hotp-maximized/w530-hotp-maximized.config b/boards/w530-hotp-maximized/w530-hotp-maximized.config index 425989a9..02f9f2de 100644 --- a/boards/w530-hotp-maximized/w530-hotp-maximized.config +++ b/boards/w530-hotp-maximized/w530-hotp-maximized.config @@ -9,7 +9,7 @@ # This board ignores the in-built dGPU that comes with all w530's. In doing so the dGPU will not be initialized. This has some benefits in terms of reduced complexity in working with OS's with poor support for NVIDIA, better battery life and lower heat (making use of the thicker heatsink from a dGPU). Conversely, if you do not initialize the dGPU you will be unable to use an external monitor. To initialize the dGPU please use the dGPU boards that corresponds with the model of dGPU included with your device. export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-w530-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/w530-maximized/w530-maximized.config b/boards/w530-maximized/w530-maximized.config index 26c88bb6..952d5dd1 100644 --- a/boards/w530-maximized/w530-maximized.config +++ b/boards/w530-maximized/w530-maximized.config @@ -9,7 +9,7 @@ # This board ignores the in-built dGPU that comes with all w530's. In doing so the dGPU will not be initialized. This has some benefits in terms of reduced complexity in working with OS's with poor support for NVIDIA, better battery life and lower heat (making use of the thicker heatsink from a dGPU). Conversely, if you do not initialize the dGPU you will be unable to use an external monitor. To initialize the dGPU please use the dGPU boards that corresponds with the model of dGPU included with your device. export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-w530-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/w541-maximized/w541-maximized.config b/boards/w541-maximized/w541-maximized.config index 881beae0..d031350b 100644 --- a/boards/w541-maximized/w541-maximized.config +++ b/boards/w541-maximized/w541-maximized.config @@ -5,7 +5,7 @@ CONFIG_LINUX_CONFIG=config/linux-w541.config export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_CRYPTSETUP2=y CONFIG_FLASHPROG=y diff --git a/boards/x220-hotp-maximized/x220-hotp-maximized.config b/boards/x220-hotp-maximized/x220-hotp-maximized.config index 33637c7d..1090bab8 100644 --- a/boards/x220-hotp-maximized/x220-hotp-maximized.config +++ b/boards/x220-hotp-maximized/x220-hotp-maximized.config @@ -10,7 +10,7 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-x220-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/x220-maximized/x220-maximized.config b/boards/x220-maximized/x220-maximized.config index c752635c..66bf251b 100644 --- a/boards/x220-maximized/x220-maximized.config +++ b/boards/x220-maximized/x220-maximized.config @@ -10,7 +10,7 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-x220-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/x230-hotp-maximized-fhd_edp/x230-hotp-maximized-fhd_edp.config b/boards/x230-hotp-maximized-fhd_edp/x230-hotp-maximized-fhd_edp.config index 853118fb..ad48e56a 100644 --- a/boards/x230-hotp-maximized-fhd_edp/x230-hotp-maximized-fhd_edp.config +++ b/boards/x230-hotp-maximized-fhd_edp/x230-hotp-maximized-fhd_edp.config @@ -20,7 +20,7 @@ # - Includes: Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-x230-maximized-fhd_edp.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/x230-hotp-maximized/x230-hotp-maximized.config b/boards/x230-hotp-maximized/x230-hotp-maximized.config index 50042591..d29cb62b 100644 --- a/boards/x230-hotp-maximized/x230-hotp-maximized.config +++ b/boards/x230-hotp-maximized/x230-hotp-maximized.config @@ -8,7 +8,7 @@ # - Includes: Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-x230-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/x230-hotp-maximized_usb-kb/x230-hotp-maximized_usb-kb.config b/boards/x230-hotp-maximized_usb-kb/x230-hotp-maximized_usb-kb.config index 74171f22..082b5c97 100644 --- a/boards/x230-hotp-maximized_usb-kb/x230-hotp-maximized_usb-kb.config +++ b/boards/x230-hotp-maximized_usb-kb/x230-hotp-maximized_usb-kb.config @@ -10,7 +10,7 @@ # USB Keyboard support export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-x230-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/x230-maximized-fhd_edp/x230-maximized-fhd_edp.config b/boards/x230-maximized-fhd_edp/x230-maximized-fhd_edp.config index ce7a66e1..d1b8c628 100644 --- a/boards/x230-maximized-fhd_edp/x230-maximized-fhd_edp.config +++ b/boards/x230-maximized-fhd_edp/x230-maximized-fhd_edp.config @@ -20,7 +20,7 @@ # - DOES NOT INCLUDE Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-x230-maximized-fhd_edp.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/x230-maximized/x230-maximized.config b/boards/x230-maximized/x230-maximized.config index 6c270689..5ca4e1e5 100644 --- a/boards/x230-maximized/x230-maximized.config +++ b/boards/x230-maximized/x230-maximized.config @@ -8,7 +8,7 @@ # - DOES NOT INCLUDE Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-x230-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/z220-cmt-maximized/z220-cmt-maximized.config b/boards/z220-cmt-maximized/z220-cmt-maximized.config index 35f38901..736b512b 100644 --- a/boards/z220-cmt-maximized/z220-cmt-maximized.config +++ b/boards/z220-cmt-maximized/z220-cmt-maximized.config @@ -26,7 +26,7 @@ CONFIG_COREBOOT_CONFIG=config/coreboot-z220-cmt.config export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_CRYPTSETUP2=y CONFIG_FLASHPROG=y diff --git a/config/linux-c216.config b/config/linux-c216.config index dbd963ea..8a5b7638 100644 --- a/config/linux-c216.config +++ b/config/linux-c216.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -188,6 +190,7 @@ CONFIG_MEMBARRIER=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +# CONFIG_KCMP is not set # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y @@ -258,7 +261,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -CONFIG_RETPOLINE=y # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -320,7 +322,6 @@ CONFIG_X86_THERMAL_VECTOR=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_IOPL_IOPERM=y -# CONFIG_I8K is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -369,6 +370,13 @@ CONFIG_LEGACY_VSYSCALL_NONE=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +# CONFIG_PAGE_TABLE_ISOLATION is not set +CONFIG_RETPOLINE=y +CONFIG_RETHUNK=y +CONFIG_CPU_IBRS_ENTRY=y +# CONFIG_GDS_FORCE_MITIGATION is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -560,6 +568,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -612,6 +621,7 @@ CONFIG_STRICT_KERNEL_RWX=y CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y CONFIG_STRICT_MODULE_RWX=y CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y CONFIG_ARCH_HAS_MEM_ENCRYPT=y CONFIG_HAVE_STATIC_CALL=y CONFIG_HAVE_STATIC_CALL_INLINE=y @@ -624,6 +634,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -758,6 +772,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -779,7 +794,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -962,7 +976,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -1316,7 +1329,6 @@ CONFIG_USB_NET_CDC_SUBSET=m # CONFIG_FUJITSU_ES is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1500,10 +1512,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1628,6 +1639,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y @@ -1718,7 +1730,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1849,6 +1860,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2583,7 +2595,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SECURITYFS is not set -# CONFIG_PAGE_TABLE_ISOLATION is not set CONFIG_INTEL_TXT=y CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y @@ -2603,6 +2614,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2779,18 +2794,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2815,6 +2818,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-kgpe-d16_server-whiptail.config b/config/linux-kgpe-d16_server-whiptail.config index eccb00b3..d79a5aa8 100644 --- a/config/linux-kgpe-d16_server-whiptail.config +++ b/config/linux-kgpe-d16_server-whiptail.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -194,6 +196,7 @@ CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_KCMP=y CONFIG_RSEQ=y # CONFIG_DEBUG_RSEQ is not set CONFIG_EMBEDDED=y @@ -264,7 +267,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -CONFIG_RETPOLINE=y # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -369,6 +371,8 @@ CONFIG_LEGACY_VSYSCALL_XONLY=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +# CONFIG_SPECULATION_MITIGATIONS is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -539,6 +543,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -605,6 +610,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -617,7 +626,8 @@ CONFIG_MODULES=y # CONFIG_MODULE_SIG is not set # CONFIG_MODULE_COMPRESS is not set # CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set -CONFIG_UNUSED_SYMBOLS=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_MODULES_TREE_LOOKUP=y CONFIG_BLOCK=y CONFIG_BLK_SCSI_REQUEST=y @@ -738,6 +748,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -759,7 +770,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -948,7 +958,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -1333,7 +1342,6 @@ CONFIG_NET_VENDOR_XILINX=y # CONFIG_NETDEVSIM is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1495,10 +1503,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1616,6 +1623,7 @@ CONFIG_I2C_SLAVE=y # CONFIG_POWER_RESET is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_POWER_SUPPLY_HWMON=y # CONFIG_PDA_POWER is not set # CONFIG_TEST_POWER is not set # CONFIG_CHARGER_ADP5061 is not set @@ -1633,12 +1641,162 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set -# CONFIG_HWMON is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM1177 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_AS370 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_AXI_FAN_CONTROL is not set +# CONFIG_SENSORS_K8TEMP is not set +# CONFIG_SENSORS_K10TEMP is not set +# CONFIG_SENSORS_FAM15H_POWER is not set +# CONFIG_SENSORS_AMD_ENERGY is not set +# CONFIG_SENSORS_APPLESMC is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ASPEED is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_DRIVETEMP is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DELL_SMM is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_FSCHMD is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_I5500 is not set +# CONFIG_SENSORS_CORETEMP is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2947_I2C is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX31730 is not set +# CONFIG_SENSORS_MAX6621 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_MR75203 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_VIA_CPUTEMP is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83773G is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_XGENE is not set + +# +# ACPI drivers +# +# CONFIG_SENSORS_ACPI_POWER is not set +# CONFIG_SENSORS_ATK0110 is not set CONFIG_THERMAL=y # CONFIG_THERMAL_NETLINK is not set # CONFIG_THERMAL_STATISTICS is not set CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y # CONFIG_THERMAL_WRITABLE_TRIPS is not set CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set @@ -1693,6 +1851,7 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_LPC_SCH is not set # CONFIG_MFD_INTEL_LPSS_ACPI is not set # CONFIG_MFD_INTEL_LPSS_PCI is not set +# CONFIG_MFD_INTEL_PMC_BXT is not set # CONFIG_MFD_IQS62X is not set # CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_KEMPLD is not set @@ -1721,7 +1880,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1917,6 +2075,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2307,7 +2466,68 @@ CONFIG_VHOST_MENU=y # CONFIG_GREYBUS is not set # CONFIG_STAGING is not set -# CONFIG_X86_PLATFORM_DEVICES is not set +CONFIG_X86_PLATFORM_DEVICES=y +CONFIG_ACPI_WMI=y +CONFIG_WMI_BMOF=y +# CONFIG_HUAWEI_WMI is not set +# CONFIG_INTEL_WMI_SBL_FW_UPDATE is not set +# CONFIG_INTEL_WMI_THUNDERBOLT is not set +CONFIG_MXM_WMI=y +# CONFIG_PEAQ_WMI is not set +# CONFIG_XIAOMI_WMI is not set +# CONFIG_ACERHDF is not set +# CONFIG_ACER_WIRELESS is not set +# CONFIG_ACER_WMI is not set +# CONFIG_APPLE_GMUX is not set +# CONFIG_ASUS_LAPTOP is not set +# CONFIG_ASUS_WIRELESS is not set +# CONFIG_DCDBAS is not set +# CONFIG_DELL_SMBIOS is not set +# CONFIG_DELL_RBU is not set +# CONFIG_DELL_SMO8800 is not set +# CONFIG_DELL_WMI_AIO is not set +# CONFIG_FUJITSU_LAPTOP is not set +# CONFIG_FUJITSU_TABLET is not set +# CONFIG_GPD_POCKET_FAN is not set +# CONFIG_HP_ACCEL is not set +# CONFIG_HP_WIRELESS is not set +# CONFIG_HP_WMI is not set +# CONFIG_IBM_RTL is not set +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_THINKPAD_ACPI is not set +# CONFIG_INTEL_HID_EVENT is not set +# CONFIG_INTEL_MENLOW is not set +# CONFIG_INTEL_VBTN is not set +# CONFIG_SURFACE_3_POWER_OPREGION is not set +# CONFIG_SURFACE_PRO3_BUTTON is not set +# CONFIG_MSI_WMI is not set +# CONFIG_SAMSUNG_LAPTOP is not set +# CONFIG_SAMSUNG_Q10 is not set +# CONFIG_TOSHIBA_BT_RFKILL is not set +# CONFIG_TOSHIBA_HAPS is not set +# CONFIG_TOSHIBA_WMI is not set +# CONFIG_ACPI_CMPC is not set +# CONFIG_LG_LAPTOP is not set +# CONFIG_PANASONIC_LAPTOP is not set +# CONFIG_SYSTEM76_ACPI is not set +# CONFIG_TOPSTAR_LAPTOP is not set +# CONFIG_I2C_MULTI_INSTANTIATE is not set +# CONFIG_MLX_PLATFORM is not set +# CONFIG_INTEL_IPS is not set +# CONFIG_INTEL_RST is not set +# CONFIG_INTEL_SMARTCONNECT is not set + +# +# Intel Speed Select Technology interface support +# +# CONFIG_INTEL_SPEED_SELECT_INTERFACE is not set +# end of Intel Speed Select Technology interface support + +# CONFIG_INTEL_UNCORE_FREQ_CONTROL is not set +# CONFIG_INTEL_PMC_CORE is not set +# CONFIG_INTEL_PUNIT_IPC is not set +# CONFIG_INTEL_SCU_PCI is not set +# CONFIG_INTEL_SCU_PLATFORM is not set CONFIG_PMC_ATOM=y # CONFIG_CHROME_PLATFORMS is not set # CONFIG_MELLANOX_PLATFORM is not set @@ -2628,7 +2848,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITYFS=y -CONFIG_PAGE_TABLE_ISOLATION=y CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY_FALLBACK=y @@ -2646,6 +2865,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2820,18 +3043,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2856,6 +3067,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-kgpe-d16_server.config b/config/linux-kgpe-d16_server.config index eccb00b3..2ca92f0c 100644 --- a/config/linux-kgpe-d16_server.config +++ b/config/linux-kgpe-d16_server.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -194,6 +196,7 @@ CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_KCMP=y CONFIG_RSEQ=y # CONFIG_DEBUG_RSEQ is not set CONFIG_EMBEDDED=y @@ -264,7 +267,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -CONFIG_RETPOLINE=y # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -369,6 +371,14 @@ CONFIG_LEGACY_VSYSCALL_XONLY=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +CONFIG_PAGE_TABLE_ISOLATION=y +CONFIG_RETPOLINE=y +CONFIG_RETHUNK=y +CONFIG_CPU_UNRET_ENTRY=y +CONFIG_CPU_IBPB_ENTRY=y +CONFIG_CPU_SRSO=y CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -539,6 +549,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -605,6 +616,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -738,6 +753,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -759,7 +775,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -948,7 +963,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -1333,7 +1347,6 @@ CONFIG_NET_VENDOR_XILINX=y # CONFIG_NETDEVSIM is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1495,10 +1508,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1616,6 +1628,7 @@ CONFIG_I2C_SLAVE=y # CONFIG_POWER_RESET is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_POWER_SUPPLY_HWMON=y # CONFIG_PDA_POWER is not set # CONFIG_TEST_POWER is not set # CONFIG_CHARGER_ADP5061 is not set @@ -1633,12 +1646,162 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set -# CONFIG_HWMON is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM1177 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_AS370 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_AXI_FAN_CONTROL is not set +# CONFIG_SENSORS_K8TEMP is not set +# CONFIG_SENSORS_K10TEMP is not set +# CONFIG_SENSORS_FAM15H_POWER is not set +# CONFIG_SENSORS_AMD_ENERGY is not set +# CONFIG_SENSORS_APPLESMC is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ASPEED is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_DRIVETEMP is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DELL_SMM is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_FSCHMD is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_I5500 is not set +# CONFIG_SENSORS_CORETEMP is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2947_I2C is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX31730 is not set +# CONFIG_SENSORS_MAX6621 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_MR75203 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_VIA_CPUTEMP is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83773G is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_XGENE is not set + +# +# ACPI drivers +# +# CONFIG_SENSORS_ACPI_POWER is not set +# CONFIG_SENSORS_ATK0110 is not set CONFIG_THERMAL=y # CONFIG_THERMAL_NETLINK is not set # CONFIG_THERMAL_STATISTICS is not set CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y # CONFIG_THERMAL_WRITABLE_TRIPS is not set CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set @@ -1693,6 +1856,7 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_LPC_SCH is not set # CONFIG_MFD_INTEL_LPSS_ACPI is not set # CONFIG_MFD_INTEL_LPSS_PCI is not set +# CONFIG_MFD_INTEL_PMC_BXT is not set # CONFIG_MFD_IQS62X is not set # CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_KEMPLD is not set @@ -1721,7 +1885,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1917,6 +2080,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2307,7 +2471,68 @@ CONFIG_VHOST_MENU=y # CONFIG_GREYBUS is not set # CONFIG_STAGING is not set -# CONFIG_X86_PLATFORM_DEVICES is not set +CONFIG_X86_PLATFORM_DEVICES=y +CONFIG_ACPI_WMI=y +CONFIG_WMI_BMOF=y +# CONFIG_HUAWEI_WMI is not set +# CONFIG_INTEL_WMI_SBL_FW_UPDATE is not set +# CONFIG_INTEL_WMI_THUNDERBOLT is not set +CONFIG_MXM_WMI=y +# CONFIG_PEAQ_WMI is not set +# CONFIG_XIAOMI_WMI is not set +# CONFIG_ACERHDF is not set +# CONFIG_ACER_WIRELESS is not set +# CONFIG_ACER_WMI is not set +# CONFIG_APPLE_GMUX is not set +# CONFIG_ASUS_LAPTOP is not set +# CONFIG_ASUS_WIRELESS is not set +# CONFIG_DCDBAS is not set +# CONFIG_DELL_SMBIOS is not set +# CONFIG_DELL_RBU is not set +# CONFIG_DELL_SMO8800 is not set +# CONFIG_DELL_WMI_AIO is not set +# CONFIG_FUJITSU_LAPTOP is not set +# CONFIG_FUJITSU_TABLET is not set +# CONFIG_GPD_POCKET_FAN is not set +# CONFIG_HP_ACCEL is not set +# CONFIG_HP_WIRELESS is not set +# CONFIG_HP_WMI is not set +# CONFIG_IBM_RTL is not set +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_THINKPAD_ACPI is not set +# CONFIG_INTEL_HID_EVENT is not set +# CONFIG_INTEL_MENLOW is not set +# CONFIG_INTEL_VBTN is not set +# CONFIG_SURFACE_3_POWER_OPREGION is not set +# CONFIG_SURFACE_PRO3_BUTTON is not set +# CONFIG_MSI_WMI is not set +# CONFIG_SAMSUNG_LAPTOP is not set +# CONFIG_SAMSUNG_Q10 is not set +# CONFIG_TOSHIBA_BT_RFKILL is not set +# CONFIG_TOSHIBA_HAPS is not set +# CONFIG_TOSHIBA_WMI is not set +# CONFIG_ACPI_CMPC is not set +# CONFIG_LG_LAPTOP is not set +# CONFIG_PANASONIC_LAPTOP is not set +# CONFIG_SYSTEM76_ACPI is not set +# CONFIG_TOPSTAR_LAPTOP is not set +# CONFIG_I2C_MULTI_INSTANTIATE is not set +# CONFIG_MLX_PLATFORM is not set +# CONFIG_INTEL_IPS is not set +# CONFIG_INTEL_RST is not set +# CONFIG_INTEL_SMARTCONNECT is not set + +# +# Intel Speed Select Technology interface support +# +# CONFIG_INTEL_SPEED_SELECT_INTERFACE is not set +# end of Intel Speed Select Technology interface support + +# CONFIG_INTEL_UNCORE_FREQ_CONTROL is not set +# CONFIG_INTEL_PMC_CORE is not set +# CONFIG_INTEL_PUNIT_IPC is not set +# CONFIG_INTEL_SCU_PCI is not set +# CONFIG_INTEL_SCU_PLATFORM is not set CONFIG_PMC_ATOM=y # CONFIG_CHROME_PLATFORMS is not set # CONFIG_MELLANOX_PLATFORM is not set @@ -2628,7 +2853,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITYFS=y -CONFIG_PAGE_TABLE_ISOLATION=y CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY_FALLBACK=y @@ -2646,6 +2870,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2820,18 +3048,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2856,6 +3072,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-kgpe-d16_workstation.config b/config/linux-kgpe-d16_workstation.config index fe9d92f2..53bf4c2e 100644 --- a/config/linux-kgpe-d16_workstation.config +++ b/config/linux-kgpe-d16_workstation.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -194,6 +196,7 @@ CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_KCMP=y CONFIG_RSEQ=y # CONFIG_DEBUG_RSEQ is not set CONFIG_EMBEDDED=y @@ -264,7 +267,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -CONFIG_RETPOLINE=y # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -369,6 +371,14 @@ CONFIG_LEGACY_VSYSCALL_XONLY=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +CONFIG_PAGE_TABLE_ISOLATION=y +CONFIG_RETPOLINE=y +CONFIG_RETHUNK=y +CONFIG_CPU_UNRET_ENTRY=y +CONFIG_CPU_IBPB_ENTRY=y +CONFIG_CPU_SRSO=y CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -539,6 +549,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -605,6 +616,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -738,6 +753,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -759,7 +775,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -948,7 +963,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -1333,7 +1347,6 @@ CONFIG_NET_VENDOR_XILINX=y # CONFIG_NETDEVSIM is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1495,10 +1508,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1634,6 +1646,7 @@ CONFIG_POWER_SUPPLY_HWMON=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1872,7 +1885,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1964,7 +1976,6 @@ CONFIG_DRM_AMD_DC=y CONFIG_DRM_AMD_DC_DCN=y # CONFIG_DRM_AMD_DC_DCN3_0 is not set # CONFIG_DRM_AMD_DC_HDCP is not set -# CONFIG_DRM_AMD_DC_SI is not set # end of Display Engine Configuration # CONFIG_HSA_AMD is not set @@ -2104,6 +2115,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2876,7 +2888,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITYFS=y -CONFIG_PAGE_TABLE_ISOLATION=y CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY_FALLBACK=y @@ -2894,6 +2905,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -3068,18 +3083,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -3104,6 +3107,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-librem_common.config b/config/linux-librem_common.config index e65f907d..65311e1f 100644 --- a/config/linux-librem_common.config +++ b/config/linux-librem_common.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -188,6 +190,7 @@ CONFIG_MEMBARRIER=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_KCMP=y # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y @@ -258,7 +261,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -# CONFIG_RETPOLINE is not set # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -320,7 +322,6 @@ CONFIG_X86_THERMAL_VECTOR=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_IOPL_IOPERM=y -# CONFIG_I8K is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -368,6 +369,12 @@ CONFIG_LEGACY_VSYSCALL_NONE=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +CONFIG_PAGE_TABLE_ISOLATION=y +# CONFIG_RETPOLINE is not set +CONFIG_CPU_IBRS_ENTRY=y +# CONFIG_GDS_FORCE_MITIGATION is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -536,6 +543,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -600,6 +608,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -735,6 +747,7 @@ CONFIG_INET=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -756,7 +769,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -943,7 +955,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -1350,7 +1361,6 @@ CONFIG_USB_NET_CDC_SUBSET=m # CONFIG_FUJITSU_ES is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1510,10 +1520,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1648,6 +1657,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y @@ -1738,7 +1748,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1970,6 +1979,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2682,7 +2692,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITYFS=y -CONFIG_PAGE_TABLE_ISOLATION=y # CONFIG_INTEL_TXT is not set CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y @@ -2701,6 +2710,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2877,18 +2890,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2913,6 +2914,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-qemu.config b/config/linux-qemu.config index 113e0ae0..e16a5917 100644 --- a/config/linux-qemu.config +++ b/config/linux-qemu.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -211,6 +213,7 @@ CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +# CONFIG_KCMP is not set CONFIG_RSEQ=y # CONFIG_DEBUG_RSEQ is not set CONFIG_EMBEDDED=y @@ -284,7 +287,6 @@ CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_X2APIC is not set # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -CONFIG_RETPOLINE=y # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -348,11 +350,10 @@ CONFIG_PERF_EVENTS_INTEL_CSTATE=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_IOPL_IOPERM=y -# CONFIG_I8K is not set CONFIG_MICROCODE=y CONFIG_MICROCODE_INTEL=y CONFIG_MICROCODE_AMD=y -# CONFIG_MICROCODE_OLD_INTERFACE is not set +# CONFIG_MICROCODE_LATE_LOADING is not set CONFIG_X86_MSR=y CONFIG_X86_CPUID=y # CONFIG_X86_5LEVEL is not set @@ -407,6 +408,16 @@ CONFIG_LEGACY_VSYSCALL_NONE=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +CONFIG_PAGE_TABLE_ISOLATION=y +CONFIG_RETPOLINE=y +CONFIG_RETHUNK=y +CONFIG_CPU_UNRET_ENTRY=y +CONFIG_CPU_IBPB_ENTRY=y +CONFIG_CPU_IBRS_ENTRY=y +CONFIG_CPU_SRSO=y +# CONFIG_GDS_FORCE_MITIGATION is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -601,6 +612,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -668,6 +680,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -808,6 +824,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -829,7 +846,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -1020,7 +1036,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -1035,6 +1050,7 @@ CONFIG_VIRTIO_BLK=y # # CONFIG_BLK_DEV_NVME is not set # CONFIG_NVME_FC is not set +# CONFIG_NVME_TCP is not set # CONFIG_NVME_TARGET is not set # end of NVME Support @@ -1394,7 +1410,6 @@ CONFIG_IGB=m # CONFIG_NETDEVSIM is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1563,10 +1578,9 @@ CONFIG_TCG_TIS_ST33ZP24=y CONFIG_TCG_TIS_ST33ZP24_I2C=y # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1691,6 +1705,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y @@ -1783,7 +1798,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1904,6 +1918,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2636,7 +2651,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITYFS=y -CONFIG_PAGE_TABLE_ISOLATION=y # CONFIG_INTEL_TXT is not set CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y @@ -2656,6 +2670,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2832,18 +2850,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2868,6 +2874,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-t440p.config b/config/linux-t440p.config index 2ba0a56a..ab90c312 100644 --- a/config/linux-t440p.config +++ b/config/linux-t440p.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -188,6 +190,7 @@ CONFIG_MEMBARRIER=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +# CONFIG_KCMP is not set # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y @@ -258,7 +261,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -# CONFIG_RETPOLINE is not set # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -320,7 +322,6 @@ CONFIG_X86_THERMAL_VECTOR=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_IOPL_IOPERM=y -# CONFIG_I8K is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -369,6 +370,12 @@ CONFIG_LEGACY_VSYSCALL_NONE=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +CONFIG_PAGE_TABLE_ISOLATION=y +# CONFIG_RETPOLINE is not set +CONFIG_CPU_IBRS_ENTRY=y +# CONFIG_GDS_FORCE_MITIGATION is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -561,6 +568,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -613,6 +621,7 @@ CONFIG_STRICT_KERNEL_RWX=y CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y CONFIG_STRICT_MODULE_RWX=y CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y CONFIG_ARCH_HAS_MEM_ENCRYPT=y CONFIG_HAVE_STATIC_CALL=y CONFIG_HAVE_STATIC_CALL_INLINE=y @@ -625,6 +634,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -759,6 +772,7 @@ CONFIG_INET=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -780,7 +794,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -967,7 +980,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -981,6 +993,7 @@ CONFIG_BLK_DEV_RAM_SIZE=65536 # # CONFIG_BLK_DEV_NVME is not set # CONFIG_NVME_FC is not set +# CONFIG_NVME_TCP is not set # end of NVME Support # @@ -1370,7 +1383,6 @@ CONFIG_USB_NET_CDC_SUBSET=m # CONFIG_FUJITSU_ES is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1530,10 +1542,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1668,6 +1679,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y @@ -1758,7 +1770,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1889,6 +1900,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2597,7 +2609,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITYFS=y -CONFIG_PAGE_TABLE_ISOLATION=y # CONFIG_INTEL_TXT is not set CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y @@ -2617,6 +2628,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2793,18 +2808,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2829,6 +2832,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-talos-2.config b/config/linux-talos-2.config index 0aa3ac5b..cee4cb74 100644 --- a/config/linux-talos-2.config +++ b/config/linux-talos-2.config @@ -162,7 +162,7 @@ CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_AIO=y +CONFIG_AIO is not set CONFIG_IO_URING=y CONFIG_ADVISE_SYSCALLS=y CONFIG_MEMBARRIER=y diff --git a/config/linux-w541.config b/config/linux-w541.config index 2ba0a56a..ab90c312 100644 --- a/config/linux-w541.config +++ b/config/linux-w541.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -188,6 +190,7 @@ CONFIG_MEMBARRIER=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +# CONFIG_KCMP is not set # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y @@ -258,7 +261,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -# CONFIG_RETPOLINE is not set # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -320,7 +322,6 @@ CONFIG_X86_THERMAL_VECTOR=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_IOPL_IOPERM=y -# CONFIG_I8K is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -369,6 +370,12 @@ CONFIG_LEGACY_VSYSCALL_NONE=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +CONFIG_PAGE_TABLE_ISOLATION=y +# CONFIG_RETPOLINE is not set +CONFIG_CPU_IBRS_ENTRY=y +# CONFIG_GDS_FORCE_MITIGATION is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -561,6 +568,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -613,6 +621,7 @@ CONFIG_STRICT_KERNEL_RWX=y CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y CONFIG_STRICT_MODULE_RWX=y CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y CONFIG_ARCH_HAS_MEM_ENCRYPT=y CONFIG_HAVE_STATIC_CALL=y CONFIG_HAVE_STATIC_CALL_INLINE=y @@ -625,6 +634,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -759,6 +772,7 @@ CONFIG_INET=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -780,7 +794,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -967,7 +980,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -981,6 +993,7 @@ CONFIG_BLK_DEV_RAM_SIZE=65536 # # CONFIG_BLK_DEV_NVME is not set # CONFIG_NVME_FC is not set +# CONFIG_NVME_TCP is not set # end of NVME Support # @@ -1370,7 +1383,6 @@ CONFIG_USB_NET_CDC_SUBSET=m # CONFIG_FUJITSU_ES is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1530,10 +1542,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1668,6 +1679,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y @@ -1758,7 +1770,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1889,6 +1900,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2597,7 +2609,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITYFS=y -CONFIG_PAGE_TABLE_ISOLATION=y # CONFIG_INTEL_TXT is not set CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y @@ -2617,6 +2628,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2793,18 +2808,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2829,6 +2832,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-x230-flash.config b/config/linux-x230-flash.config index e5030ebc..94aa7145 100644 --- a/config/linux-x230-flash.config +++ b/config/linux-x230-flash.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -184,6 +186,7 @@ CONFIG_MEMBARRIER=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +# CONFIG_KCMP is not set # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y @@ -313,7 +316,6 @@ CONFIG_X86_THERMAL_VECTOR=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_IOPL_IOPERM=y -# CONFIG_I8K is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -360,6 +362,13 @@ CONFIG_LEGACY_VSYSCALL_NONE=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +# CONFIG_PAGE_TABLE_ISOLATION is not set +CONFIG_RETPOLINE=y +CONFIG_RETHUNK=y +CONFIG_CPU_IBRS_ENTRY=y +# CONFIG_GDS_FORCE_MITIGATION is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -549,6 +558,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -601,6 +611,7 @@ CONFIG_STRICT_KERNEL_RWX=y CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y CONFIG_STRICT_MODULE_RWX=y CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y CONFIG_ARCH_HAS_MEM_ENCRYPT=y CONFIG_HAVE_STATIC_CALL=y CONFIG_HAVE_STATIC_CALL_INLINE=y @@ -613,6 +624,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -855,7 +870,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # DRBD disabled because PROC_FS or INET not selected # # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -1153,10 +1167,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1280,6 +1293,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y @@ -1369,7 +1383,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1500,6 +1513,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2221,6 +2235,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2420,6 +2438,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-x230-legacy.config b/config/linux-x230-legacy.config index 792edc79..f7e55ad7 100644 --- a/config/linux-x230-legacy.config +++ b/config/linux-x230-legacy.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -188,6 +190,7 @@ CONFIG_MEMBARRIER=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +# CONFIG_KCMP is not set # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y @@ -258,7 +261,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -CONFIG_RETPOLINE=y # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -320,7 +322,6 @@ CONFIG_X86_THERMAL_VECTOR=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_IOPL_IOPERM=y -# CONFIG_I8K is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -369,6 +370,13 @@ CONFIG_LEGACY_VSYSCALL_NONE=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +# CONFIG_PAGE_TABLE_ISOLATION is not set +CONFIG_RETPOLINE=y +CONFIG_RETHUNK=y +CONFIG_CPU_IBRS_ENTRY=y +# CONFIG_GDS_FORCE_MITIGATION is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -560,6 +568,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -612,6 +621,7 @@ CONFIG_STRICT_KERNEL_RWX=y CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y CONFIG_STRICT_MODULE_RWX=y CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y CONFIG_ARCH_HAS_MEM_ENCRYPT=y CONFIG_HAVE_STATIC_CALL=y CONFIG_HAVE_STATIC_CALL_INLINE=y @@ -624,6 +634,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -750,7 +764,6 @@ CONFIG_UNIX_SCM=y # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -928,7 +941,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -1264,10 +1276,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1392,6 +1403,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y @@ -1482,7 +1494,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1613,6 +1624,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2318,7 +2330,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SECURITYFS is not set -# CONFIG_PAGE_TABLE_ISOLATION is not set CONFIG_INTEL_TXT=y CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y @@ -2338,6 +2349,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2514,18 +2529,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2550,6 +2553,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/config/linux-x230-maximized.config b/config/linux-x230-maximized.config index 2ebbc178..1b553408 100644 --- a/config/linux-x230-maximized.config +++ b/config/linux-x230-maximized.config @@ -1,12 +1,14 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.10.5 Kernel Configuration +# Linux/x86 5.10.214 Kernel Configuration # CONFIG_CC_VERSION_TEXT="x86_64-linux-musl-gcc (GCC) 8.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=80300 CONFIG_LD_VERSION=232000000 CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=23200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -188,6 +190,7 @@ CONFIG_MEMBARRIER=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +# CONFIG_KCMP is not set # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y @@ -258,7 +261,6 @@ CONFIG_SMP=y CONFIG_X86_FEATURE_NAMES=y # CONFIG_X86_MPPARSE is not set # CONFIG_GOLDFISH is not set -CONFIG_RETPOLINE=y # CONFIG_X86_CPU_RESCTRL is not set # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set @@ -320,7 +322,6 @@ CONFIG_X86_THERMAL_VECTOR=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_IOPL_IOPERM=y -# CONFIG_I8K is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -369,6 +370,13 @@ CONFIG_LEGACY_VSYSCALL_NONE=y CONFIG_HAVE_LIVEPATCH=y # end of Processor type and features +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_SPECULATION_MITIGATIONS=y +# CONFIG_PAGE_TABLE_ISOLATION is not set +CONFIG_RETPOLINE=y +CONFIG_RETHUNK=y +CONFIG_CPU_IBRS_ENTRY=y +# CONFIG_GDS_FORCE_MITIGATION is not set CONFIG_ARCH_HAS_ADD_PAGES=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y @@ -560,6 +568,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y CONFIG_HAVE_ASM_MODVERSIONS=y @@ -612,6 +621,7 @@ CONFIG_STRICT_KERNEL_RWX=y CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y CONFIG_STRICT_MODULE_RWX=y CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y CONFIG_ARCH_HAS_MEM_ENCRYPT=y CONFIG_HAVE_STATIC_CALL=y CONFIG_HAVE_STATIC_CALL_INLINE=y @@ -624,6 +634,10 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_GCC_PLUGINS=y +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -758,6 +772,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -779,7 +794,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -962,7 +976,6 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 @@ -976,6 +989,7 @@ CONFIG_BLK_DEV_RAM_SIZE=65536 # # CONFIG_BLK_DEV_NVME is not set # CONFIG_NVME_FC is not set +# CONFIG_NVME_TCP is not set # end of NVME Support # @@ -1313,7 +1327,6 @@ CONFIG_USB_NET_CDC_SUBSET=m # CONFIG_FUJITSU_ES is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1497,10 +1510,9 @@ CONFIG_TCG_TIS=y # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TELCLOCK is not set # CONFIG_XILLYBUS is not set -# end of Character devices - CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# end of Character devices # # I2C support @@ -1625,6 +1637,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y @@ -1715,7 +1728,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SKY81452 is not set # CONFIG_ABX500_CORE is not set CONFIG_MFD_SYSCON=y -# CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_TI_LMU is not set @@ -1846,6 +1858,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set @@ -2580,7 +2593,6 @@ CONFIG_IO_WQ=y # CONFIG_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SECURITYFS is not set -# CONFIG_PAGE_TABLE_ISOLATION is not set CONFIG_INTEL_TXT=y CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y @@ -2600,6 +2612,10 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" # Memory initialization # CONFIG_INIT_STACK_NONE=y +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STACKLEAK is not set # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization @@ -2776,18 +2792,6 @@ CONFIG_CRYPTO_USER_API_AEAD=y # CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set # CONFIG_CRYPTO_STATS is not set CONFIG_CRYPTO_HASH_INFO=y - -# -# Crypto library routines -# -CONFIG_CRYPTO_LIB_AES=y -# CONFIG_CRYPTO_LIB_BLAKE2S is not set -# CONFIG_CRYPTO_LIB_CHACHA is not set -# CONFIG_CRYPTO_LIB_CURVE25519 is not set -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 -# CONFIG_CRYPTO_LIB_POLY1305 is not set -# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_LIB_SHA256=y # CONFIG_CRYPTO_HW is not set # @@ -2812,6 +2816,21 @@ CONFIG_GENERIC_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_LIB_MEMNEQ=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set diff --git a/modules/linux b/modules/linux index ea08916d..23ddcec8 100644 --- a/modules/linux +++ b/modules/linux @@ -28,9 +28,9 @@ linux_hash := a6fbd4ee903c128367892c2393ee0d9657b6ed3ea90016d4dc6f1f6da20b2330 # been done. This is because `0000-efi_bds.patch` did not cleanly port # from 5.4.69 to 5.10.5 which directly affects linuxboot systems. # -else ifeq "$(CONFIG_LINUX_VERSION)" "5.10.5" -linux_version := 5.10.5 -linux_hash := 3991a9e16a187d78d5f414d89236ae5d7f404a69e60c4c42a9d262ee19612ef4 +else ifeq "$(CONFIG_LINUX_VERSION)" "5.10.214" +linux_version := 5.10.214 +linux_hash := 40f014d53e81f204f6d2a364aae4201ae07970dd1b70dc602d7c66c1a140f558 else ifeq "$(CONFIG_LINUX_VERSION)" "6.1.8" linux_version := 6.1.8 linux_hash := b60bb53ab8ba370a270454b11e93d41af29126fc72bd6ede517673e2e57b816d diff --git a/patches/linux-5.10.5/0001-fake-acpi.patch b/patches/linux-5.10.214/0001-fake-acpi.patch similarity index 100% rename from patches/linux-5.10.5/0001-fake-acpi.patch rename to patches/linux-5.10.214/0001-fake-acpi.patch diff --git a/patches/linux-5.10.5/0002-nmi-squelch.patch b/patches/linux-5.10.214/0002-nmi-squelch.patch similarity index 100% rename from patches/linux-5.10.5/0002-nmi-squelch.patch rename to patches/linux-5.10.214/0002-nmi-squelch.patch diff --git a/patches/linux-5.10.5/0003-fake-trampoline.patch b/patches/linux-5.10.214/0003-fake-trampoline.patch similarity index 100% rename from patches/linux-5.10.5/0003-fake-trampoline.patch rename to patches/linux-5.10.214/0003-fake-trampoline.patch diff --git a/patches/linux-5.10.5/0010-winterfell-ahci.patch b/patches/linux-5.10.214/0010-winterfell-ahci.patch similarity index 100% rename from patches/linux-5.10.5/0010-winterfell-ahci.patch rename to patches/linux-5.10.214/0010-winterfell-ahci.patch diff --git a/patches/linux-5.10.214/shebangs.patch b/patches/linux-5.10.214/shebangs.patch new file mode 100644 index 00000000..34164d29 --- /dev/null +++ b/patches/linux-5.10.214/shebangs.patch @@ -0,0 +1,40 @@ +diff --git a/scripts/check-sysctl-docs b/scripts/check-sysctl-docs +index 8bcb9e26c7bc..90137319c50a 100755 +--- a/scripts/check-sysctl-docs ++++ b/scripts/check-sysctl-docs +@@ -1,4 +1,4 @@ +-#!/usr/bin/gawk -f ++#!/usr/bin/env -S gawk -f + # SPDX-License-Identifier: GPL-2.0 + + # Script to check sysctl documentation against source files +diff --git a/scripts/ld-version.sh b/scripts/ld-version.sh +index f2be0ff9a738..7a5b546ece16 100755 +--- a/scripts/ld-version.sh ++++ b/scripts/ld-version.sh +@@ -1,4 +1,4 @@ +-#!/usr/bin/awk -f ++#!/usr/bin/env -S awk -f + # SPDX-License-Identifier: GPL-2.0 + # extract linker version number from stdin and turn into single number + { +diff --git a/scripts/parse-maintainers.pl b/scripts/parse-maintainers.pl +index 2ca4eb3f190d..9515765158fa 100755 +--- a/scripts/parse-maintainers.pl ++++ b/scripts/parse-maintainers.pl +@@ -1,4 +1,4 @@ +-#!/usr/bin/perl -w ++#!/usr/bin/env -S perl -w + # SPDX-License-Identifier: GPL-2.0 + + use strict; +diff --git a/scripts/ver_linux b/scripts/ver_linux +index 0968a3070eff..345b92f71d2d 100755 +--- a/scripts/ver_linux ++++ b/scripts/ver_linux +@@ -1,4 +1,4 @@ +-#!/usr/bin/awk -f ++#!/usr/bin/env -S awk -f + # SPDX-License-Identifier: GPL-2.0 + # Before running this script please ensure that your PATH is + # typical as you use for compilation/installation. I use diff --git a/patches/linux-5.10.5/0004-libsubcmd_Fix_use-after-free-for-realloc.patch b/patches/linux-5.10.5/0004-libsubcmd_Fix_use-after-free-for-realloc.patch deleted file mode 100644 index 57d0d503..00000000 --- a/patches/linux-5.10.5/0004-libsubcmd_Fix_use-after-free-for-realloc.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 52a9dab6d892763b2a8334a568bd4e2c1a6fde66 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Sun, 13 Feb 2022 10:24:43 -0800 -Subject: [PATCH] libsubcmd: Fix use-after-free for realloc(..., 0) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -GCC 12 correctly reports a potential use-after-free condition in the -xrealloc helper. Fix the warning by avoiding an implicit "free(ptr)" -when size == 0: - -In file included from help.c:12: -In function 'xrealloc', - inlined from 'add_cmdname' at help.c:24:2: subcmd-util.h:56:23: error: pointer may be used after 'realloc' [-Werror=use-after-free] - 56 | ret = realloc(ptr, size); - | ^~~~~~~~~~~~~~~~~~ -subcmd-util.h:52:21: note: call to 'realloc' here - 52 | void *ret = realloc(ptr, size); - | ^~~~~~~~~~~~~~~~~~ -subcmd-util.h:58:31: error: pointer may be used after 'realloc' [-Werror=use-after-free] - 58 | ret = realloc(ptr, 1); - | ^~~~~~~~~~~~~~~ -subcmd-util.h:52:21: note: call to 'realloc' here - 52 | void *ret = realloc(ptr, size); - | ^~~~~~~~~~~~~~~~~~ - -Fixes: 2f4ce5ec1d447beb ("perf tools: Finalize subcmd independence") -Reported-by: Valdis Klētnieks -Signed-off-by: Kees Kook -Tested-by: Valdis Klētnieks -Tested-by: Justin M. Forbes -Acked-by: Josh Poimboeuf -Cc: linux-hardening@vger.kernel.org -Cc: Valdis Klētnieks -Link: http://lore.kernel.org/lkml/20220213182443.4037039-1-keescook@chromium.org -Signed-off-by: Arnaldo Carvalho de Melo ---- - tools/lib/subcmd/subcmd-util.h | 11 ++--------- - 1 file changed, 2 insertions(+), 9 deletions(-) - -diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h -index 794a375dad3601..b2aec04fce8f67 100644 ---- a/tools/lib/subcmd/subcmd-util.h -+++ b/tools/lib/subcmd/subcmd-util.h -@@ -50,15 +50,8 @@ static NORETURN inline void die(const char *err, ...) - static inline void *xrealloc(void *ptr, size_t size) - { - void *ret = realloc(ptr, size); -- if (!ret && !size) -- ret = realloc(ptr, 1); -- if (!ret) { -- ret = realloc(ptr, size); -- if (!ret && !size) -- ret = realloc(ptr, 1); -- if (!ret) -- die("Out of memory, realloc failed"); -- } -+ if (!ret) -+ die("Out of memory, realloc failed"); - return ret; - } - - diff --git a/patches/linux-5.10.5/shebangs.patch b/patches/linux-5.10.5/shebangs.patch deleted file mode 100644 index 76a73b5d..00000000 --- a/patches/linux-5.10.5/shebangs.patch +++ /dev/null @@ -1,100 +0,0 @@ -diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter -index d7ca46c612b3..652e9542043f 100755 ---- a/scripts/bloat-o-meter -+++ b/scripts/bloat-o-meter -@@ -1,4 +1,4 @@ --#!/usr/bin/python -+#!/usr/bin/env python - # - # Copyright 2004 Matt Mackall - # -diff --git a/scripts/check-sysctl-docs b/scripts/check-sysctl-docs -index 8bcb9e26c7bc..90137319c50a 100755 ---- a/scripts/check-sysctl-docs -+++ b/scripts/check-sysctl-docs -@@ -1,4 +1,4 @@ --#!/usr/bin/gawk -f -+#!/usr/bin/env -S gawk -f - # SPDX-License-Identifier: GPL-2.0 - - # Script to check sysctl documentation against source files -diff --git a/scripts/diffconfig b/scripts/diffconfig -index 89abf777f197..627eba5849b5 100755 ---- a/scripts/diffconfig -+++ b/scripts/diffconfig -@@ -1,4 +1,4 @@ --#!/usr/bin/python -+#!/usr/bin/env python - # SPDX-License-Identifier: GPL-2.0 - # - # diffconfig - a tool to compare .config files. -diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl -index 68dab828a722..92d9aa6cc4f5 100755 ---- a/scripts/get_abi.pl -+++ b/scripts/get_abi.pl -@@ -1,4 +1,4 @@ --#!/usr/bin/perl -+#!/usr/bin/env perl - # SPDX-License-Identifier: GPL-2.0 - - use strict; -diff --git a/scripts/ld-version.sh b/scripts/ld-version.sh -index f2be0ff9a738..7a5b546ece16 100755 ---- a/scripts/ld-version.sh -+++ b/scripts/ld-version.sh -@@ -1,4 +1,4 @@ --#!/usr/bin/awk -f -+#!/usr/bin/env -S awk -f - # SPDX-License-Identifier: GPL-2.0 - # extract linker version number from stdin and turn into single number - { -diff --git a/scripts/parse-maintainers.pl b/scripts/parse-maintainers.pl -index 2ca4eb3f190d..9515765158fa 100755 ---- a/scripts/parse-maintainers.pl -+++ b/scripts/parse-maintainers.pl -@@ -1,4 +1,4 @@ --#!/usr/bin/perl -w -+#!/usr/bin/env -S perl -w - # SPDX-License-Identifier: GPL-2.0 - - use strict; -diff --git a/scripts/show_delta b/scripts/show_delta -index 264399307c4f..28e67e178194 100755 ---- a/scripts/show_delta -+++ b/scripts/show_delta -@@ -1,4 +1,4 @@ --#!/usr/bin/python -+#!/usr/bin/env python - # SPDX-License-Identifier: GPL-2.0-only - # - # show_deltas: Read list of printk messages instrumented with -diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install -index 40fa6923e80a..828a8615a918 100755 ---- a/scripts/sphinx-pre-install -+++ b/scripts/sphinx-pre-install -@@ -1,4 +1,4 @@ --#!/usr/bin/perl -+#!/usr/bin/env perl - # SPDX-License-Identifier: GPL-2.0-or-later - use strict; - -diff --git a/scripts/split-man.pl b/scripts/split-man.pl -index c3db607ee9ec..96bd99dc977a 100755 ---- a/scripts/split-man.pl -+++ b/scripts/split-man.pl -@@ -1,4 +1,4 @@ --#!/usr/bin/perl -+#!/usr/bin/env perl - # SPDX-License-Identifier: GPL-2.0 - # - # Author: Mauro Carvalho Chehab -diff --git a/scripts/ver_linux b/scripts/ver_linux -index 0968a3070eff..345b92f71d2d 100755 ---- a/scripts/ver_linux -+++ b/scripts/ver_linux -@@ -1,4 +1,4 @@ --#!/usr/bin/awk -f -+#!/usr/bin/env -S awk -f - # SPDX-License-Identifier: GPL-2.0 - # Before running this script please ensure that your PATH is - # typical as you use for compilation/installation. I use From 0cef8e1edc9bf3606b983acc11035ae3430c133f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 16 Aug 2024 15:20:11 -0400 Subject: [PATCH 06/17] cryptsetup2 toolstack version bump and script fixes to support multi-LUKS containers (BTRFS QubesOS 4.2) cryptsetup2 2.6.1 is a new release that supports reencryption of Q4.2 release LUKS2 volumes created at installation. This is a critical feature for the Qubes OS 4.2 release for added data at rest protection Cryptsetup 2.6.x internal changes: - Argon2 used externally and internally: requires a lot of RAM and CPU to derivate passphrase to key validated in key slots. - This is used to rate limit efficiently bruteforcing of LUKS key slots, requiring each offline brute force attempt to consume ~15-30 seconds per attempt - OF course, strong passphrases are still recommended, but bruteforcing LUKSv2 containers with Argon2 would require immense time, ram and CPU even to bruteforce low entropy passphrase/PINs. - passphrase change doesn't permit LUKS key slot specification anymore: key slot rotates (new one consusumed per op: then old one wiped internally. EG: LUKS key slot 1 created, then 0 deleted) - reencryption doesn't permit old call arguments. No more direct-io; inadmissively slow through AIO (async) calls, need workarounds for good enough perfs (arguments + newer kernel with cloudfare fixes in tree) cryptsetup 2.6.1 requires: - lvm2 2.03.23, which is also included in this PR. - requires libaio, which is also included in this PR (could be hacked out but deep dependency at first sight: left in) - requires util-linux 2.39 - patches for reproducible builds are included for above 3 packages. luks-functions was updated to support the new cryptsetup2 version calls/changes - reencryption happen in direct-io, offline mode and without locking, requiring linux 5.10.9+ to bypass linux queues - from tests, this is best for performance and reliability in single-user mode - LUKS container ops now validate Disk Recovery Key (DRK) passphrase prior and DRK key slot prior of going forward if needed, failing early. - Heads don't expect DRK to be in static key slot anymore, and finds the DRK key slot dynamically. - If reencrytipn/passphrase change: make sure all LUKS containers on same block device can be unlocked with same DRK - Reencryption: requires to know which key slot to reencrypt. - Find LUKS key slot that unlocks with DRK passphrase unlock prior of reencrypt call - Passphrase change: no slot can be passed, but key slot of DRK rotates. kexec-seal-key - TPM LUKS Disk Unlock Key key slots have changed to be set in max slots per LUKS version (LUKSv1:7 /LUKSv2: 31) - If key slot != default LUKS version's keyslot outside of DRK key slot: prompt the user before wiping that key slot, otherwise wipe automatically - This takes for granted that the DRK key slot alone is needed on the system and Heads controls the LUKS key slots. - If user has something else going on, ie: Using USB Security dongle + TPM DUK, then the user will need to say no when wiping keys. - It was suggested to leave LUKS key slots outside of DRK alone, but then: what to do when all key slots would be used? - Alternative implementation could be to only prompt users to wipe keyslots other then DRK when key slots are all used (LUKSv1: 0-7, LUKSv2: 0-31) - But then cleanup would need to happen prior of operations (LUKS passphrase change, TPM DUK setup) and could be problematic. - LUKS containers now checked to be same LUKS version prior of permitting to set TPM DUK and will refuse to go forward of different versions. TODO: - async (AIO) calls are not used. direct-io is used instead. libaio could be hacked out - this could be subject to future work Notes: - time to deprecated legacy boards the do not enough space for the new space requirements - x230-legacy, x230-legacy-flash, x230-hotp-legacy - t430-legacy, t430-legacy-flash, t430-hotp-legacy already deprecated Unrelated: - typos fixes found along the way Signed-off-by: Thierry Laurion --- initrd/bin/kexec-save-default | 7 +- initrd/bin/kexec-seal-key | 229 +++++++---- initrd/bin/oem-factory-reset | 25 +- initrd/etc/gui_functions | 3 + initrd/etc/luks-functions | 374 ++++++++++++------ initrd/init | 2 + modules/cryptsetup2 | 17 +- modules/libaio | 19 + modules/lvm2 | 42 +- modules/util-linux | 6 +- ...p2-2.3.3.patch => cryptsetup2-2.6.1.patch} | 362 ++++++++++++----- patches/lvm2-2.03.23.patch | 150 +++++++ patches/util-linux-2.29.2.patch | 139 ------- patches/util-linux-2.39.patch | 276 +++++++++++++ .../x230-hotp-legacy/x230-hotp-legacy.config | 73 ++++ .../x230-legacy-flash.config | 36 ++ .../x230-legacy/x230-legacy.config | 66 ++++ 17 files changed, 1360 insertions(+), 466 deletions(-) create mode 100644 modules/libaio rename patches/{cryptsetup2-2.3.3.patch => cryptsetup2-2.6.1.patch} (72%) create mode 100644 patches/lvm2-2.03.23.patch delete mode 100644 patches/util-linux-2.29.2.patch create mode 100644 patches/util-linux-2.39.patch create mode 100644 unmaintained_boards/x230-hotp-legacy/x230-hotp-legacy.config create mode 100644 unmaintained_boards/x230-legacy-flash/x230-legacy-flash.config create mode 100644 unmaintained_boards/x230-legacy/x230-legacy.config diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index c7a4f04f..828e7d98 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -218,16 +218,17 @@ if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" != "y" ] && [ save_key="y" fi else - DEBUG "No previous LUKS TPM Disk Unlock Key was set up, confirming to add a Disk Encryption Key to the TPM" + DEBUG "No previous LUKS TPM Disk Unlock Key was set up, confirming to add a Disk Unlock Key (DUK) to the TPM" read \ -n 1 \ - -p "Do you wish to add a disk encryption to the TPM [y/N]: " \ + -p "Do you wish to add a disk encryption key to the TPM [y/N]: " \ add_key_confirm + #TODO: still not convinced: disk encryption key? decryption key? everywhere TPM Disk Unlock Key. Confusing even more? echo if [ "$add_key_confirm" = "y" \ -o "$add_key_confirm" = "Y" ]; then - DEBUG "User confirmed desire to add a Disk Encryption Key to the TPM" + DEBUG "User confirmed desire to add a Disk Unlock Key (DUK) to the TPM" save_key="y" fi fi diff --git a/initrd/bin/kexec-seal-key b/initrd/bin/kexec-seal-key index 0481ebb2..0765d8b9 100755 --- a/initrd/bin/kexec-seal-key +++ b/initrd/bin/kexec-seal-key @@ -1,15 +1,33 @@ #!/bin/bash -# This will generate a disk encryption key and seal / ecncrypt +# This will generate a disk encryption key and seal / encrypt # with the current PCRs and then store it in the TPM NVRAM. # It will then need to be bundled into initrd that is booted. set -e -o pipefail . /etc/functions +find_drk_key_slot() { + local temp_drk_key_slot="" + local keyslot + + for keyslot in "${luks_used_keyslots[@]}"; do + if [ -z "$temp_drk_key_slot" ]; then + DEBUG "Testing LUKS key slot $keyslot against $DISK_RECOVERY_KEY_FILE for Disk Recovery Key slot..." + if DO_WITH_DEBUG cryptsetup open --test-passphrase --key-slot "$keyslot" --key-file "$DISK_RECOVERY_KEY_FILE" "$dev"; then + temp_drk_key_slot="$keyslot" + DEBUG "Disk Recovery key slot is $temp_drk_key_slot" + break + fi + fi + done + + echo "$temp_drk_key_slot" +} + TPM_INDEX=3 TPM_SIZE=312 -KEY_FILE="/tmp/secret/secret.key" +DUK_KEY_FILE="/tmp/secret/secret.key" TPM_SEALED="/tmp/secret/secret.sealed" -RECOVERY_KEY="/tmp/secret/recovery.key" +DISK_RECOVERY_KEY_FILE="/tmp/secret/recovery.key" . /etc/functions . /tmp/config @@ -23,11 +41,12 @@ fi KEY_DEVICES="$paramsdir/kexec_key_devices.txt" KEY_LVM="$paramsdir/kexec_key_lvm.txt" +key_devices=$(cat "$KEY_DEVICES" | cut -d\ -f1 | tr '\n' ' ') if [ ! -r "$KEY_DEVICES" ]; then die "No devices defined for disk encryption" else - DEBUG "Devices defined for disk encryption: $(cat "$KEY_DEVICES" | cut -d\ -f1 | tr '\n' ' ')" + DEBUG "Devices defined for disk encryption: $key_devices" fi if [ -r "$KEY_LVM" ]; then @@ -44,92 +63,160 @@ fi DEBUG "$(pcrs)" -# LUKS Key slot 0 is the manual recovery pass phrase -# that they user entered when they installed OS, -# key slot 1 is the one that we've generated. -read -s -p "Enter LUKS Disk Recovery Key/passphrase: " disk_password -echo -n "$disk_password" >"$RECOVERY_KEY" -echo -read -s -p "New LUKS TPM Disk Unlock Key passphrase for booting: " key_password -echo -read -s -p "Repeat LUKS TPM Disk Unlock Key passphrase for booting: " key_password2 -echo +luks_drk_passphrase_valid=0 +for dev in $key_devices ; do + attempts=0 + while [ $attempts -lt 3 ]; do + if [ "$luks_drk_passphrase_valid" == "0" ]; then + # Ask for the passphrase only once + read -s -p "Enter LUKS Disk Recovery Key (DRK) passphrase that can unlock: $key_devices: " disk_recovery_key_passphrase + #Using he provided passphrase as the DRK "keyfile" for unattended operations + echo -n "$disk_recovery_key_passphrase" >"$DISK_RECOVERY_KEY_FILE" + echo + fi -if [ "$key_password" != "$key_password2" ]; then - die "Key passphrases do not match" -fi + DEBUG "Testing $DISK_RECOVERY_KEY_FILE keyfile created from provided passphrase against $dev individual key slots" + if cryptsetup open $dev --test-passphrase --key-file "$DISK_RECOVERY_KEY_FILE" >/dev/null 2>&1; then + DEBUG "LUKS device $dev unlocked successfully with the DRK passphrase" + luks_drk_passphrase_valid=1 + break + else + attempts=$((attempts + 1)) + if [ "$attempts" == "3" ] && [ "$luks_drk_passphrase_valid" == "0" ]; then + die "Failed to unlock LUKS device $dev with the provided passphrase. Exiting..." + elif [ "$attempts" != "3" ] && [ "$luks_drk_passphrase_valid" == "1" ]; then + #We failed unlocking with DRK passphrase another LUKS container + die "LUKS device $key_devices cannot all be unlocked with same passphrase. Please make $key_devices devices unlockable with the same passphrase. Exiting" + else + warn "Failed to unlock LUKS device $dev with the provided passphrase. Please try again." + fi + fi + done +done + +attempts=0 +while [ $attempts -lt 3 ]; do + read -s -p "New LUKS TPM Disk Unlock Key passphrase (DUK) for booting: " key_password + echo + read -s -p "Repeat LUKS TPM Disk Unlock Key (DUK) passphrase for booting: " key_password2 + echo + if [ "$key_password" != "$key_password2" ]; then + attempts=$((attempts + 1)) + if [ "$attempts" == "3" ]; then + die "Disk Unlock Key passphrases do not match. Exiting..." + else + warn "Disk Unlock Key passphrases do not match. Please try again." + fi + else + break + fi +done # Generate key file echo "++++++ Generating new randomized 128 bytes key file that will be sealed/unsealed by LUKS TPM Disk Unlock Key passphrase" dd \ if=/dev/urandom \ - of="$KEY_FILE" \ + of="$DUK_KEY_FILE" \ bs=1 \ count=128 \ 2>/dev/null || die "Unable to generate 128 random bytes" -# Count the number of slots used on each device -for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do - DEBUG "Checking number of slots used on $dev LUKS header" - #check if the device is a LUKS device with luks[1,2] - # Get the number of key slots used on the LUKS header. - # LUKS1 Format is : - # Slot 0: ENABLED - # Slot 1: ENABLED - # Slot 2: DISABLED - # Slot 3: DISABLED - #... - # Slot 7: DISABLED - # Luks2 only reports on enabled slots. - # luks2 Format is : - # 0: luks2 - # 1: luks2 - # Meaning that the number of slots used is the number of lines returned by a grep on the LUKS2 above format. - # We need to count the number of ENABLED slots for both LUKS1 and LUKS2 - # create regex pattern for both LUKS1 and LUKS2 - regex="Slot [0-9]*: ENABLED" - regex+="\|" - regex+="[0-9]*: luks2" - slots_used=$(cryptsetup luksDump "$dev" | grep -c "$regex" || die "Unable to get number of slots used on $dev") - - DEBUG "Number of slots used on $dev LUKS header: $slots_used" - # If slot1 is the only one used, warn and die with proper messages - if [ "$slots_used" -eq 1 ]; then - # Check if slot 1 is the only one existing - if [ "$(cryptsetup luksDump "$dev" | grep -c "Slot 1: ENABLED")" -eq 1 ] || [ "$(cryptsetup luksDump "$dev" | grep -c "1: luks2")" -eq 1 ]; then - warn "Slot 1 is the only one existing on $dev LUKS header. Heads cannot use it to store TPM sealed LUKS Disk Unlock Key" - warn "Slot 1 should not be the only slot existing on $dev LUKS header. Slot 0 should be used to store LUKS Disk Recovery Key/passphrase" - die "You can safely fix this before continuing through Heads recovery shell: cryptsetup luksAddKey $dev" - fi - else - DEBUG "Slot 1 is not the only existing slot on $dev LUKS header." - DEBUG "$dev LUKS header's slot 1 will store LUKS Disk Unlock Key that TPM will seal/unseal with LUKS TPM Disk Unlock Key passphrase" +previous_luks_header_version=0 +for dev in $key_devices; do + # Check and store LUKS version of the devices to be used later + luks_version=$(cryptsetup luksDump "$dev" | grep "Version" | cut -d: -f2 | tr -d '[:space:]') + if [ "$luks_version" == "2" ] && [ "$previous_luks_header_version" == "1" ]; then + die "$dev: LUKSv2 device detected while LUKSv1 device was detected previously. Exiting..." fi -done -# Remove all the old keys from slot 1 -for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do - echo "++++++ $dev: Removing old LUKS TPM Disk Unlock Key in LUKS slot 1" - cryptsetup luksKillSlot \ - --key-file "$RECOVERY_KEY" \ - $dev 1 || - warn "$dev: removal of LUKS TPM Disk Unlock Key in LUKS slot 1 failed: might not exist. Continuing" + if [ "$luks_version" == "1" ] && [ "$previous_luks_header_version" == "2" ]; then + die "$dev: LUKSv1 device detected while LUKSv2 device was detected previously. Exiting..." + fi - echo "++++++ $dev: Adding LUKS TPM Disk Unlock Key to LUKS slot 1" - cryptsetup luksAddKey \ - --key-file "$RECOVERY_KEY" \ - --key-slot 1 \ - $dev "$KEY_FILE" || - die "$dev: Unable to add LUKS TPM Disk Unlock Key to LUKS slot 1" + if [ "$luks_version" == "2" ]; then + # LUKSv2 last key slot is 31 + duk_keyslot=31 + regex="^\s+([0-9]+):\s*luks2" + sed_command="s/^\s\+\([0-9]\+\):\s*luks2/\1/g" + previous_luks_header_version=2 + DEBUG "$dev: LUKSv2 device detected" + elif [ "$luks_version" == "1" ]; then + # LUKSv1 last key slot is 7 + duk_keyslot=7 + regex="Key Slot ([0-9]+): ENABLED" + sed_command='s/Key Slot \([0-9]\+\): ENABLED/\1/' + previous_luks_header_version=1 + DEBUG "$dev: LUKSv1 device detected" + else + die "$dev: Unsupported LUKS version $luks_version" + fi + + # drk_key_slot will be the slot number where the passphrase was tested against as valid. We will keep that slot + drk_key_slot="-1" + + # Get all the key slots that are used on $dev + luks_used_keyslots=($(cryptsetup luksDump "$dev" | grep -E "$regex" | sed "$sed_command")) + DEBUG "$dev LUKS key slots: ${luks_used_keyslots[*]}" + + #Find the key slot that can be unlocked with the provided passphrase + drk_key_slot=$(find_drk_key_slot) + + # If we didn't find the DRK key slot, we exit (this should never happen) + if [ "$drk_key_slot" == "-1" ]; then + die "$dev: Unable to find a key slot that can be unlocked with provided passphrase. Exiting..." + fi + + # If the key slot is not the expected DUK o FRK key slot, we will ask the user to confirm the wipe + for keyslot in "${luks_used_keyslots[@]}"; do + if [ "$keyslot" != "$drk_key_slot" ]; then + #set wipe_desired to no by default + wipe_desired="no" + + if [ "$keyslot" != "$drk_key_slot" ] && [ "$keyslot" == "1" ]; then + wipe_desired="yes" + DEBUG "LUKS key slot $keyslot not DRK. Will wipe this DUK key slot silently" + elif [ "$keyslot" != "$drk_key_slot" ] && [ "$keyslot" != "$duk_keyslot" ]; then + # Heads expects key slot LUKSv1:7 or LUKSv2:31 to be used for TPM DUK setup. + # Ask user to confirm otherwise + warn "LUKS key slot $keyslot is not typical ($duk_keyslot expected) for TPM Disk Unlock Key setup" + read -p "Are you sure you want to wipe it? [y/N] " -n 1 -r + echo + # If user does not confirm, skip this slot + if [[ $REPLY =~ ^[Yy]$ ]]; then + wipe_desired="yes" + fi + elif [ "$keyslot" == "$duk_keyslot" ]; then + # If key slot is the expected DUK keyslot, we wipe it silently + DEBUG "LUKS key slot $keyslot is the expected DUK key slot. Will wipe this DUK key slot silently" + wipe_desired="yes" + fi + + if [ "$wipe_desired" == "yes" ] && [ "$keyslot" != "$drk_key_slot" ]; then + echo "++++++ $dev: Wiping LUKS key slot $keyslot" + DO_WITH_DEBUG cryptsetup luksKillSlot \ + --key-file "$DISK_RECOVERY_KEY_FILE" \ + $dev $keyslot || + warn "$dev: removal of LUKS slot $keyslot failed: Continuing" + fi + fi + done + + + echo "++++++ $dev: Adding LUKS TPM Disk Unlock Key to LUKS key slot $duk_keyslot" + DO_WITH_DEBUG cryptsetup luksAddKey \ + --key-file "$DISK_RECOVERY_KEY_FILE" \ + --new-key-slot $duk_keyslot \ + $dev "$DUK_KEY_FILE" || + die "$dev: Unable to add LUKS TPM Disk Unlock Key to LUKS key slot $duk_keyslot" done # Now that we have setup the new keys, measure the PCRs # We don't care what ends up in PCR 6; we just want # to get the /tmp/luksDump.txt file. We use PCR16 # since it should still be zero -cat "$KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks || +echo "$key_devices" | xargs /bin/qubes-measure-luks || die "Unable to measure the LUKS headers" pcrf="/tmp/secret/pcrf.bin" @@ -155,13 +242,13 @@ tpmr calcfuturepcr 6 "/tmp/luksDump.txt" >>"$pcrf" tpmr pcrread -a 7 "$pcrf" DO_WITH_DEBUG --mask-position 7 \ - tpmr seal "$KEY_FILE" "$TPM_INDEX" 0,1,2,3,4,5,6,7 "$pcrf" \ + tpmr seal "$DUK_KEY_FILE" "$TPM_INDEX" 0,1,2,3,4,5,6,7 "$pcrf" \ "$TPM_SIZE" "$key_password" || die "Unable to write LUKS TPM Disk Unlock Key to NVRAM" # should be okay if this fails shred -n 10 -z -u "$pcrf" 2>/dev/null || warn "Failed to delete pcrf file - continuing" -shred -n 10 -z -u "$KEY_FILE" 2>/dev/null || +shred -n 10 -z -u "$DUK_KEY_FILE" 2>/dev/null || warn "Failed to delete key file - continuing" mount -o rw,remount $paramsdir || warn "Failed to remount $paramsdir in RW - continuing" diff --git a/initrd/bin/oem-factory-reset b/initrd/bin/oem-factory-reset index 35e41ac3..ca000e50 100755 --- a/initrd/bin/oem-factory-reset +++ b/initrd/bin/oem-factory-reset @@ -44,6 +44,12 @@ GPG_ALGO="RSA" # Default RSA key length is 3072 bits for OEM key gen. 4096 are way longer to generate in smartcard RSA_KEY_LENGTH=3072 +#Override RSA_KEY_LENGTH to 2048 bits for Canokey under qemu testing boards until canokey fixes +if [[ "$CONFIG_BOARD_NAME" == qemu-* ]]; then + DEBUG "Overriding RSA_KEY_LENGTH to 2048 bits for Canokey under qemu testing boards" + RSA_KEY_LENGTH=2048 +fi + GPG_USER_NAME="OEM Key" GPG_KEY_NAME=$(date +%Y%m%d%H%M%S) GPG_USER_MAIL="oem-${GPG_KEY_NAME}@example.com" @@ -266,20 +272,20 @@ keytocard_subkeys_to_smartcard() { { echo "key 1" #Toggle on Signature key in --edit-key mode on local keyring echo "keytocard" #Move Signature key to smartcard - echo "1" #Select Signature key keyslot on smartcard + echo "1" #Select Signature key key slot on smartcard echo "${ADMIN_PIN}" #Local keyring Subkey PIN echo "${ADMIN_PIN_DEF}" #Smartcard Admin PIN echo "0" #No expiration date echo "key 1" #Toggle off Signature key echo "key 2" #Toggle on Encryption key echo "keytocard" #Move Encryption key to smartcard - echo "2" #Select Encryption key keyslot on smartcard + echo "2" #Select Encryption key key slot on smartcard echo "${ADMIN_PIN}" #Local keyring Subkey PIN echo "${ADMIN_PIN_DEF}" #Smartcard Admin PIN echo "key 2" #Toggle off Encryption key echo "key 3" #Toggle on Authentication key echo "keytocard" #Move Authentication key to smartcard - echo "3" #Select Authentication key keyslot on smartcard + echo "3" #Select Authentication key slot on smartcard echo "${ADMIN_PIN}" #Local keyring Subkey PIN echo "${ADMIN_PIN_DEF}" #Smartcard Admin PIN echo "key 3" #Toggle off Authentication key @@ -383,6 +389,7 @@ export_public_key_to_thumbdrive_public_partition() { #pass non-empty arguments to --pass, --mountpoint, --device, --mode mount-usb --device "$device" --mode "$mode" --mountpoint "$mountpoint" || die "Error mounting thumb drive's public partition" + #TODO: reuse "Obtain GPG key ID" so that pubkey on public thumb drive partition is named after key ID gpg --export --armor "${GPG_USER_MAIL}" >"$mountpoint"/pubkey.asc || die "Error exporting public key to thumb drive's public partition" umount "$mountpoint" || die "Error unmounting thumb drive's public partition" @@ -879,6 +886,7 @@ report_integrity_measurements clear #Prompt user for use of default configuration options +TRACE_FUNC echo -e -n "Would you like to use default configuration options?\nIf N, you will be prompted for each option [Y/n]: " read -n 1 use_defaults @@ -907,6 +915,7 @@ if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then echo if [ "$prompt_output" == "y" \ -o "$prompt_output" == "Y" ]; then + TRACE_FUNC test_luks_current_disk_recovery_key_passphrase luks_new_Disk_Recovery_Key_desired=1 echo -e "\n" @@ -970,8 +979,7 @@ if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then echo if [ "$prompt_output" == "y" \ -o "$prompt_output" == "Y" ]; then - echo -e "\nThe chosen custom password must be between 8 and $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n" - echo + echo -e "\nThe chosen custom password must be between 8 and $MAX_HOTP_GPG_PIN_LENGTH characters in length." while [[ ${#CUSTOM_SINGLE_PASS} -lt 8 ]] || [[ ${#CUSTOM_SINGLE_PASS} -gt $MAX_HOTP_GPG_PIN_LENGTH ]]; do echo -e -n "Enter the custom password: " read CUSTOM_SINGLE_PASS @@ -999,8 +1007,8 @@ if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then read TPM_PASS done fi - while [[ ${#ADMIN_PIN} -lt 8 ]] || [[ ${#ADMIN_PIN} -gt $MAX_HOTP_GPG_PIN_LENGTH ]]; do - echo -e -n "\nThis PIN should be between 8 to $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n" + while [[ ${#ADMIN_PIN} -lt 6 ]] || [[ ${#ADMIN_PIN} -gt $MAX_HOTP_GPG_PIN_LENGTH ]]; do + echo -e -n "\nThis PIN should be between 6 to $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n" echo -e -n "Enter desired GPG Admin PIN: " read ADMIN_PIN done @@ -1028,6 +1036,7 @@ if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then } done #We test that current LUKS Disk Recovery Key passphrase is known prior of going further + TRACE_FUNC test_luks_current_disk_recovery_key_passphrase echo -e "\n" fi @@ -1147,8 +1156,8 @@ fi if [ -n "$luks_new_Disk_Recovery_Key_desired" -a -n "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then #Reencryption of disk, LUKS Disk Recovery Key and LUKS Disk Recovery Key passphrase change is requested - luks_change_passphrase luks_reencrypt + luks_change_passphrase elif [ -n "$luks_new_Disk_Recovery_Key_desired" -a -z "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then #Reencryption of disk was requested but not passphrase change luks_reencrypt diff --git a/initrd/etc/gui_functions b/initrd/etc/gui_functions index 38958b1a..e4b7ed4d 100755 --- a/initrd/etc/gui_functions +++ b/initrd/etc/gui_functions @@ -37,6 +37,7 @@ mount_usb() # -- Display related functions -- # Produce a whiptail prompt with 'warning' background, works for fbwhiptail and newt whiptail_warning() { + #TODO: Cannot be called as is under luks_functions with string expension in title: why? if [ -x /bin/fbwhiptail ]; then whiptail $BG_COLOR_WARNING "$@" else @@ -46,6 +47,7 @@ whiptail_warning() { # Produce a whiptail prompt with 'error' background, works for fbwhiptail and newt whiptail_error() { + #TODO: Cannot be called as is under luks_functions with string expension in title: why? if [ -x /bin/fbwhiptail ]; then whiptail $BG_COLOR_ERROR "$@" else @@ -55,6 +57,7 @@ whiptail_error() { # Produce a whiptail prompt of the given type - 'error', 'warning', or 'normal' whiptail_type() { + TRACE_FUNC local TYPE="$1" shift case "$TYPE" in diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index 30e0c4ab..b7765a7b 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -7,6 +7,7 @@ #List all LUKS devices on the system list_luks_devices() { + TRACE_FUNC #generate a list of devices to choose from that contain a LUKS header lvm vgscan || true blkid | cut -d ':' -f 1 | while read device; do @@ -267,12 +268,15 @@ prepare_thumb_drive() select_luks_container() { + #TODO: extend logic to prompt for block devices with model if multiple LUKS are found on block device instead of partitions + # Then feed luks with those partitions so that reencrypt and passphrase change can use passphrase to test all selected TRACE_FUNC if [ -s /boot/kexec_key_devices.txt ]; then DEBUG "Reusing known good LUKS container device from /boot/kexec_key_devices.txt" - DEBUG "LUKS container device: $(cut -d ' ' -f1 /boot/kexec_key_devices.txt)" - LUKS=$(cut -d ' ' -f1 /boot/kexec_key_devices.txt) - else + LUKS=$(cut -d ' ' -f1 /boot/kexec_key_devices.txt) + DEBUG "LUKS container device: $(echo $LUKS)" + # LUKS variable not exported yet, prompt for LUKS device + elif [ -z "$LUKS" ]; then list_luks_devices > /tmp/luks_devices.txt #if /tmp/luks_devices.txt exists and is not empty if [ -s /tmp/luks_devices.txt ]; then @@ -280,11 +284,21 @@ select_luks_container() if [ "$FILE" == "" ]; then return 1 else - LUKS=$FILE - detect_boot_device - mount -o remount,rw /boot - echo "$LUKS $(cryptsetup luksUUID $LUKS)" >/boot/kexec_key_devices.txt - mount -o remount,ro /boot + #TODO: What about BRTFS multi LUKS setup of QubesOS? + # if multiple LUKS containers are found on same block device + # select all of the luks containers on same block device instead of just one + # note that block devices for example under /dev/sda will be /dev/sda1, /dev/sda2, etc + # so we need to select all of the partitions on the same block device from /tmp/luks_devices.txt + # and then export them to LUKS variable + # then reencrypt and passphrase change functions will loop on all of the LUKS containers + # and test passphrase on all of them + if grep -q "$(echo $FILE | sed 's/[0-9]*$//')" /tmp/luks_devices.txt; then + DEBUG "Multiple LUKS containers found on same block device, selecting them all" + LUKS=$(grep $(echo $FILE | sed 's/[0-9]*$//') /tmp/luks_devices.txt) + else + DEBUG "Single LUKS container found on block device, assigning to LUKS variable" + LUKS=$FILE + fi fi else warn "No encrypted device found" @@ -295,41 +309,79 @@ select_luks_container() test_luks_current_disk_recovery_key_passphrase() { + #TODO: reuse/generalize usage of this function. Tests for LUKS are still done 4 times independently of this helper TRACE_FUNC while :; do select_luks_container || return 1 + + # LUKS contains multiline string of LUKS containers on same block device + # transform it into words of a same string separated by space + PRINTABLE_LUKS=$(echo $LUKS) + + TRACE_FUNC if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then - #if no external provisioning provides current LUKS Disk Recovery Key passphrase + # if no external provisioning provides current LUKS Disk Recovery Key passphrase echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" read -r luks_current_Disk_Recovery_Key_passphrase echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase - warn "Testing opening "$LUKS" LUKS encrypted drive content with the current LUKS Disk Recovery Key passphrase..." - cryptsetup open $LUKS test --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase else echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase - warn "Testing opening "$LUKS" LUKS encrypted drive content with the current LUKS Disk Recovery Key passphrase..." - cryptsetup open $LUKS test --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase fi - #Validate past cryptsetup-reencrypt attempts - if [ $? -eq 0 ]; then - whiptail --title 'Invalid Actual LUKS Disk Recovery Key passphrase?' --msgbox \ - "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 30 60 - shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null - #unsetting luks_current_Disk_Recovery_Key_passphrase so we prompt for it again LUKS Disk Recovery Key passphrase prompt on next round - unset luks_current_Disk_Recovery_Key_passphrase - #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. - #maybe the container was not the right one - detect_boot_device - mount -o remount,rw /boot - rm -f /boot/kexec_key_devices.txt - mount -o remount,ro /boot - else - #LuksOpen test was successful. Cleanup should be called only when done - #Exporting successfully used passphrase possibly reused by oem-factory-reset - #We close the volume - cryptsetup close test - export luks_current_Disk_Recovery_Key_passphrase + # test all LUKS containers on same block device as returned by select_luks_container + echo -e "\n$PRINTABLE_LUKS: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." + + # Loop on all LUKS containers on same block device + for luks_container in $LUKS; do + DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." + DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase + # Validate past cryptsetup reencrypt attempts + if [ $? -ne 0 ]; then + # if we have more than one LUKS container and passphrase test unsuccessful, tell user how to change passphrase + if [ $(echo $LUKS | wc -w) -gt 1 ]; then + #TODO remove this once whiptail_error whiptail_warning can take titles with double quotes + #whiptail_warning --title 'tes' --msgbox 'test' 0 80 + #whiptail_error --title 'error' --msgbox 'error' 0 80 + #Neither work today. Not related to this PR... Using whiptail without coloring. + + msg=$(echo -e "All $PRINTABLE_LUKS must unlock with the same Disk Recovery Key passphrase for the current operation to succeed.\n\nTo change individual LUKS container passphrase, do so from 'Options-> Change LUKS Disk Recovery Key passphrase'\n\nThen retry this operation." | fold -w 70 -s) + whiptail --title "$luks_container"': Wrong current LUKS Disk Recovery Key passphrase?' \ + --msgbox "$msg" 0 80 + + TRACE_FUNC + luks_secrets_cleanup + die "$PRINTABLE_LUKS individual containers NEED to share the same Disk Recovery Key passphrase" + # We exited to caller, LUKS still set. TODO: problem? Should we call all cleaning functions on die? + fi + + whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + TRACE_FUNC + + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + # remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. + # maybe the container was not the right one + unset LUKS + else + # LuksOpen test was successful. Cleanup should be called only when done + # Exporting successfully used passphrase possibly reused by oem-factory-reset + echo "$luks_container: unlocking LUKS container with current Disk Recovery Key passphrase successful" + + # Exporting successfully used passphrase possibly reused by oem-factory-reset + export luks_current_Disk_Recovery_Key_passphrase + fi + done + + # exit while loop if LUKS variable is not empty + if [ -n "$LUKS" ]; then + # We export the LUKS volume(s) that was/were validated via passphrase test + export LUKS + TRACE_FUNC + DEBUG "$LUKS exported to be reused" break; fi done @@ -337,12 +389,16 @@ test_luks_current_disk_recovery_key_passphrase() luks_reencrypt() { TRACE_FUNC - while :; do - select_luks_container || return 1 - #If the user just set a new LUKS Disk Recovery Key passphrase - if [ -n "$luks_new_Disk_Recovery_Key_passphrase" ]; then - luks_current_Disk_Recovery_Key_passphrase="$luks_new_Disk_Recovery_Key_passphrase" - fi + #TODO: REFACTOR This and luks passphrase change function needs to loop on same drive discovered luks containers so that reencrypt/passwd change is done on all luks containers of same drive + # Ideal would be to list luks devices and then try keep and append LUKS devices to a list of devices to reencrypt or change passphrase + # then loop on that list of devices that could be opened and reencrypt/change passphrase for all the devices that could be tested opened with that passphrase + select_luks_container || return 1 + + # Count the number of containers to be reencrypted + num_containers=$(echo "$LUKS" | wc -w) + reencrypted_containers=0 + + while [ $reencrypted_containers -lt $num_containers ]; do if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then #if no external provisioning provides current LUKS Disk Recovery Key passphrase msg=$(echo -e "This will replace the encrypted container content and its LUKS Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user under the following conditions:\n 1-Every boot if no Disk Unlock Key was added to the TPM\n 2-If the TPM fails (hardware failure)\n 3-If the firmware has been tampered with/modified by the user\n\nThis process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to the LUKS device container.\n\nHit Enter to continue." | fold -w 70 -s) @@ -351,97 +407,185 @@ luks_reencrypt() { echo -e "\nEnter the current LUKS Disk Recovery Key passphrase:" read -r luks_current_Disk_Recovery_Key_passphrase echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase - warn "Reencrypting "$LUKS" LUKS encrypted drive content with a new LUKS Disk Recovery Key. Do NOT shut down or reboot!" - cryptsetup-reencrypt -B 64 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase else echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase - warn "Reencrypting "$LUKS" LUKS encrypted drive content with a new LUKS Disk Recovery Key. Do NOT shut down or reboot!" - cryptsetup-reencrypt -B 64 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase - fi - #Validate past cryptsetup-reencrypt attempts - if [ $(echo $?) -ne 0 ]; then - whiptail --title 'Invalid Actual LUKS Disk Recovery Key passphrase?' --msgbox \ - "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 30 60 - shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null - #unsetting luks_current_Disk_Recovery_Key_passphrase so we prompt for it again LUKS Disk Recovery Key passphrase prompt on next round - unset luks_current_Disk_Recovery_Key_passphrase - #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. - #maybe the container was not the right one - detect_boot_device - mount -o remount,rw /boot - rm -f /boot/kexec_key_devices.txt - mount -o remount,ro /boot - else - #Reencryption was successful. Cleanup should be called only when done - #Exporting successfully used passphrase possibly reused by oem-factory-reset - export luks_current_Disk_Recovery_Key_passphrase - break; fi + + # Split the $LUKS variable into an array of LUKS containers + luks_containers=($LUKS) + TRACE_FUNC + DEBUG "luks_containers: $luks_containers" + + # Loop through each LUKS container + for luks_container in "${luks_containers[@]}"; do + DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." + if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. + # Maybe the container was not the right one + TRACE_FUNC + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + unset LUKS + continue + fi + done + + DEBUG "Test opening ${luks_containers[@]} successful. Now testing key slots to determine which holds master key" + for luks_container in "${luks_containers[@]}"; do + # First obtain which luks1/luks2 key-slot can be unlocked with the key-file + DRK_KEYSLOT=-1 + DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." + for i in $(seq 0 31); do + if DO_WITH_DEBUG cryptsetup open --test-passphrase $luks_container --key-slot $i --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + DRK_KEYSLOT=$i + DEBUG "$luks_container: Found key-slot $DRK_KEYSLOT that can be unlocked with the current passphrase. breaking loop" + break + fi + done + + # Validate if a key slot was found + if [ $DRK_KEYSLOT -eq -1 ]; then + whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. + # Maybe the container was not the right one + TRACE_FUNC + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + unset LUKS + continue + fi + + # Now reencrypt the LUKS container with the same key slot + # Warn and launch actual reencryption + echo -e "\nReencrypting $luks_container LUKS encrypted drive content with current Recovery Disk Key passphrase..." + warn "DO NOT POWER DOWN MACHINE, UNPLUG AC OR REMOVE BATTERY DURING REENCRYPTION PROCESS" + + # --perf-no_read_workqueue and/or --perf-no_write_workqueue improve encryption/reencrypton performance on kernel 5.10.9+ + # bypassing dm-crypt queues. + # Ref https://github.com/cloudflare/linux/issues/1#issuecomment-729695518 + # --resilience=none disables the resilience feature of cryptsetup, which is enabled by default + # --force-offline-reencrypt forces the reencryption to be done offline (no read/write operations on the device) + # --disable-locks disables the lock feature of cryptsetup, which is enabled by default + + if ! DO_WITH_DEBUG cryptsetup reencrypt \ + --perf-no_read_workqueue --perf-no_write_workqueue \ + --resilience=none --force-offline-reencrypt --disable-locks \ + "$luks_container" --key-slot "$DRK_KEYSLOT" \ + --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase; then + whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + + TRACE_FUNC + + #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. + #maybe the container was not the right one + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + unset LUKS + else + #Reencryption was successful. Cleanup should be called only when done + #Exporting successfully used passphrase possibly reused by oem-factory-reset + export luks_current_Disk_Recovery_Key_passphrase + export LUKS + + # Increment the count of reencrypted containers + reencrypted_containers=$((reencrypted_containers + 1)) + fi + done done } -luks_change_passphrase() -{ - TRACE_FUNC - while :; do - select_luks_container || return 1 - #if actual or new LUKS Disk Recovery Key is not provisioned by oem-provisioning file - if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ] || [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then - whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \ - "Please enter the current LUKS Disk Recovery Key passphrase (slot 0).\nThen choose a strong passphrase of your own.\n\n**DICEWARE passphrase methodology is STRONGLY ADVISED.**\n\nHit Enter to continue" 30 60 - if [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then - echo -e "\nEnter your desired replacement for the actual LUKS Disk Recovery Key passphrase (At least 8 characters long):" - while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do - { - read -r luks_new_Disk_Recovery_Key_passphrase - };done - fi - if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then - echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" - read -r luks_current_Disk_Recovery_Key_passphrase - fi - export luks_current_Disk_Recovery_Key_passphrase - export luks_new_Disk_Recovery_Key_passphrase - echo -n "$luks_new_Disk_Recovery_Key_passphrase" >/tmp/luks_new_Disk_Recovery_Key_passphrase - echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase - warn "Changing "$LUKS" LUKS encrypted disk passphrase to the new LUKS Disk Recovery Key passphrase..." - cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/luks_current_Disk_Recovery_Key_passphrase /tmp/luks_new_Disk_Recovery_Key_passphrase - else - #If current and new LUKS Disk Recovery Key were exported - echo -n "$luks_new_Disk_Recovery_Key_passphrase" >/tmp/luks_new_Disk_Recovery_Key_passphrase - echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase - warn "Changing "$LUKS" LUKS encrypted disk passphrase to the new LUKS Disk Recovery Key passphrase..." - cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/luks_current_Disk_Recovery_Key_passphrase /tmp/luks_new_Disk_Recovery_Key_passphrase - fi +luks_change_passphrase() { + TRACE_FUNC - #Validate past cryptsetup attempts - if [ $(echo $?) -ne 0 ]; then - #Cryptsetup luksChangeKey was unsuccessful - whiptail --title 'Invalid LUKS passphrase?' --msgbox \ - "The LUKS Disk Recovery Key passphrase was provided to you by the OEM over\n a secure communication channel.\n\nIf you previously changed it and do not remember it,\n you will have to reinstall the OS from a USB drive.\nTo do so, put OS ISO file and it's signature file on root of a USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 - unset luks_current_Disk_Recovery_Key_passphrase - unset luks_new_Disk_Recovery_Key_passphrase - #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. - #maybe the container was not the right one - detect_boot_device - mount -o remount,rw /boot - rm -f /boot/kexec_key_devices.txt - mount -o remount,ro /boot - else - #Cryptsetup was successful. - #Cleanup should be called seperately. - #Exporting successfully used passphrase possibly reused by oem-factory-reset - export luks_new_Disk_Recovery_Key_passphrase - break; - fi - done + select_luks_container || return 1 + + # Count the number of containers to be processed + num_containers=$(echo "$LUKS" | wc -w) + changed_containers=0 + + # Split the $LUKS variable into an array of LUKS containers + IFS=' ' read -ra luks_containers <<< "$LUKS" + + for luks_container in "${luks_containers[@]}"; do + if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ] || [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then + whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \ + "Please enter the current LUKS Disk Recovery Key passphrase (slot 0).\nThen choose a strong passphrase of your own.\n\n**DICEWARE passphrase methodology is STRONGLY ADVISED.**\n\nHit Enter to continue" 0 80 + + if [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then + echo -e "\nEnter your desired replacement for the actual LUKS Disk Recovery Key passphrase (At least 8 characters long):" + while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do + read -r luks_new_Disk_Recovery_Key_passphrase + done + fi + + if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then + echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" + read -r luks_current_Disk_Recovery_Key_passphrase + fi + fi + + echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_new_Disk_Recovery_Key_passphrase" > /tmp/luks_new_Disk_Recovery_Key_passphrase + + DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." + if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to\n reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + TRACE_FUNC + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + unset LUKS + continue + fi + + echo -e "\nChanging $luks_container LUKS encrypted disk passphrase to the new LUKS Disk Recovery Key passphrase..." + if ! DO_WITH_DEBUG cryptsetup luksChangeKey "$luks_container" --key-file=/tmp/luks_current_Disk_Recovery_Key_passphrase /tmp/luks_new_Disk_Recovery_Key_passphrase; then + whiptail --title 'Failed to change LUKS passphrase' --msgbox \ + "Failed to change the passphrase for $luks_container.\nPlease try again." 0 80 + continue + fi + + echo "Success changing passphrase for $luks_container." + changed_containers=$((changed_containers + 1)) + done + + if [ $changed_containers -eq $num_containers ]; then + # All containers processed successfully + luks_current_Disk_Recovery_Key_passphrase=$luks_new_Disk_Recovery_Key_passphrase + export luks_current_Disk_Recovery_Key_passphrase + export luks_new_Disk_Recovery_Key_passphrase + export LUKS + fi } luks_secrets_cleanup() { + TRACE_FUNC + #Cleanup shred -n 10 -z -u /tmp/luks_new_Disk_Recovery_Key_passphrase 2>/dev/null || true shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null || true + + #Unset variables (when in same boot) unset luks_current_Disk_Recovery_Key_passphrase unset luks_new_Disk_Recovery_Key_passphrase + + #TODO: refactor logic of selec_luks_conatainer, where to put + #unset LUKS } diff --git a/initrd/init b/initrd/init index 55a894a7..847f9e2a 100755 --- a/initrd/init +++ b/initrd/init @@ -103,10 +103,12 @@ fi #Specify whiptail background colors cues under FBWhiptail only if [ -x /bin/fbwhiptail ]; then + DEBUG "fbwhiptail BG_COLOR_* exported" export BG_COLOR_WARNING="${CONFIG_WARNING_BG_COLOR:-"--background-gradient 0 0 0 150 125 0"}" export BG_COLOR_ERROR="${CONFIG_ERROR_BG_COLOR:-"--background-gradient 0 0 0 150 0 0"}" export BG_COLOR_MAIN_MENU="normal" else + DEBUG "whiptail TEXT_BG_COLOR_* exported" export TEXT_BG_COLOR_WARNING="${CONFIG_WARNING_TEXT_BG_COLOR:-"yellow"}" export TEXT_BG_COLOR_ERROR="${CONFIG_ERROR_TEXT_BG_COLOR:-"red"}" export BG_COLOR_MAIN_MENU="normal" diff --git a/modules/cryptsetup2 b/modules/cryptsetup2 index 6becf6db..ff98639b 100644 --- a/modules/cryptsetup2 +++ b/modules/cryptsetup2 @@ -2,11 +2,11 @@ modules-$(CONFIG_CRYPTSETUP2) += cryptsetup2 cryptsetup2_depends := util-linux popt lvm2 json-c $(musl_dep) -cryptsetup2_version := 2.3.3 +cryptsetup2_version := 2.6.1 cryptsetup2_dir := cryptsetup-$(cryptsetup2_version) cryptsetup2_tar := cryptsetup-$(cryptsetup2_version).tar.xz -cryptsetup2_url := https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-$(cryptsetup2_version).tar.xz -cryptsetup2_hash := 3bca4ffe39e2f94cef50f6ea65acb873a6dbce5db34fc6bcefe38b6d095e82df +cryptsetup2_url := https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-$(cryptsetup2_version).tar.xz +cryptsetup2_hash := 410ded65a1072ab9c8e41added37b9729c087fef4d2db02bb4ef529ad6da4693 # Use an empty prefix so that the executables will not include the # build path. @@ -16,9 +16,15 @@ cryptsetup2_configure := \ ./configure \ --host $(MUSL_ARCH)-elf-linux \ --prefix "/" \ - --disable-gcrypt-pbkdf2 \ + --enable-internal-sse-argon2 \ --disable-rpath \ - --enable-cryptsetup-reencrypt \ + --disable-gcrypt-pbkdf2 \ + --disable-ssh-token \ + --disable-asciidoc \ + --disable-nls \ + --disable-selinux \ + --disable-udev \ + --disable-external-tokens \ --with-crypto_backend=kernel \ --with-tmpfilesdir=$(INSTALL)/lib/tmpfiles.d @@ -33,7 +39,6 @@ cryptsetup2_target := \ cryptsetup2_output := \ .libs/cryptsetup \ - .libs/cryptsetup-reencrypt \ .libs/veritysetup \ cryptsetup2_libraries := \ diff --git a/modules/libaio b/modules/libaio new file mode 100644 index 00000000..bf83fb90 --- /dev/null +++ b/modules/libaio @@ -0,0 +1,19 @@ +modules-$(CONFIG_LVM2) += libaio + +libaio_version := 0.3.113 +libaio_dir := libaio-$(libaio_version) +libaio_tar := libaio_$(libaio_version).orig.tar.gz +libaio_url := https://deb.debian.org/debian/pool/main/liba/libaio/$(libaio_tar) +libaio_hash := 2c44d1c5fd0d43752287c9ae1eb9c023f04ef848ea8d4aafa46e9aedb678200b + +libaio_target := \ + DESTDIR="$(INSTALL)" \ + prefix="/" \ + $(CROSS_TOOLS) \ + install \ + && mv $(build)/$(libaio_dir)/src/libaio.so.1.0.2 $(build)/$(libaio_dir)/src/libaio.so.1 \ + +libaio_libraries:= src/libaio.so.1 + +libaio_depends := $(musl_dep) + diff --git a/modules/lvm2 b/modules/lvm2 index e51292d6..6df76284 100644 --- a/modules/lvm2 +++ b/modules/lvm2 @@ -1,37 +1,39 @@ modules-$(CONFIG_LVM2) += lvm2 -lvm2_version := 2.02.168 +lvm2_version := 2.03.23 lvm2_dir := lvm2.$(lvm2_version) lvm2_tar := LVM2.$(lvm2_version).tgz lvm2_url := https://mirrors.kernel.org/sourceware/lvm2/$(lvm2_tar) -lvm2_hash := 23a3d1cddd41b3ef51812ebf83e9fa491f502fe74130d4263be327a91914660d +lvm2_hash := 74e794a9e9dee1bcf8a2065f65b9196c44fdf321e22d63b98ed7de8c9aa17a5d # cross compiling test assumes malloc/realloc aren't glibc compat # so we force it via the configure cache. lvm2_configure := \ $(CROSS_TOOLS) \ - CFLAGS="-Os" \ - PKG_CONFIG=/bin/false \ - MODPROBE_CMD=/bin/false \ ac_cv_func_malloc_0_nonnull=yes \ ac_cv_func_realloc_0_nonnull=yes \ ./configure \ --host $(MUSL_ARCH)-elf-linux \ - --prefix "/" \ - --disable-blkid_wiping \ - --disable-cache_check_needs_check \ - --disable-cmirrord \ - --disable-dmeventd \ - --disable-lvmetad \ - --disable-lvmpolld \ - --disable-realtime \ + --prefix "" \ + --libexecdir "/bin" \ + --with-optimisation=-Os \ + --enable-devmapper \ --disable-selinux \ - --disable-thin_check_needs_check \ - --disable-udev-systemd-background-jobs \ - --disable-use-lvmetad \ + --without-systemd \ + --disable-lvmimportvdo \ + --disable-realtime \ + --disable-dmfilemapd \ + --disable-dmeventd \ + --disable-lvmpolld \ + --disable-readline \ + --disable-udev_sync \ + --enable-static_link \ --disable-use-lvmlockd \ --disable-use-lvmpolld \ - --enable-devmapper \ + --disable-dmfilemapd \ + --disable-cmirrord \ + --disable-cache_check_needs_check \ + --disable-thin_check_needs_check \ --with-cluster=none \ --with-thin-check= \ @@ -49,10 +51,10 @@ lvm2_target := \ DESTDIR="$(INSTALL)" \ install_device-mapper \ -lvm2_libraries := libdm/libdevmapper.so.1.02 +lvm2_libraries := libdm/ioctl/libdevmapper.so.1.02 lvm2_output := \ - tools/dmsetup \ + ./libdm/dm-tools/dmsetup \ tools/lvm \ -lvm2_depends := util-linux $(musl_dep) +lvm2_depends := util-linux libaio $(musl_dep) diff --git a/modules/util-linux b/modules/util-linux index 9ab8dae5..bb359d74 100644 --- a/modules/util-linux +++ b/modules/util-linux @@ -1,10 +1,10 @@ modules-$(CONFIG_UTIL_LINUX) += util-linux -util-linux_version := 2.29.2 +util-linux_version := 2.39 util-linux_dir := util-linux-$(util-linux_version) util-linux_tar := util-linux-$(util-linux_version).tar.xz -util-linux_url := https://www.kernel.org/pub/linux/utils/util-linux/v2.29/$(util-linux_tar) -util-linux_hash := accea4d678209f97f634f40a93b7e9fcad5915d1f4749f6c47bee6bf110fe8e3 +util-linux_url := https://www.kernel.org/pub/linux/utils/util-linux/v2.39/$(util-linux_tar) +util-linux_hash := 32b30a336cda903182ed61feb3e9b908b762a5e66fe14e43efb88d37162075cb util-linux_configure := \ $(CROSS_TOOLS) \ diff --git a/patches/cryptsetup2-2.3.3.patch b/patches/cryptsetup2-2.6.1.patch similarity index 72% rename from patches/cryptsetup2-2.3.3.patch rename to patches/cryptsetup2-2.6.1.patch index 8a673ef8..036aa007 100644 --- a/patches/cryptsetup2-2.3.3.patch +++ b/patches/cryptsetup2-2.6.1.patch @@ -1,7 +1,7 @@ -diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure ---- cryptsetup-2.3.3-clean/configure 2020-06-10 14:05:45.784925972 +0200 -+++ cryptsetup-2.3.3/configure 2020-06-10 14:12:03.811651237 +0200 -@@ -10206,7 +10206,7 @@ +diff -u -r cryptsetup-2.4.3-clean/configure cryptsetup-2.4.3/configure +--- cryptsetup-2.4.3-clean/configure 2022-01-13 17:24:34.000000000 +0800 ++++ cryptsetup-2.4.3/configure 2022-01-16 14:08:37.088258763 +0800 +@@ -11056,7 +11056,7 @@ hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no @@ -10,7 +10,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported -@@ -10290,7 +10290,7 @@ +@@ -11140,7 +11140,7 @@ # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH @@ -19,7 +19,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then -@@ -10336,7 +10336,7 @@ +@@ -11186,7 +11186,7 @@ ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' @@ -28,7 +28,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_minus_L=yes ;; esac -@@ -10356,7 +10356,7 @@ +@@ -11206,7 +11206,7 @@ cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. @@ -37,7 +37,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no -@@ -10386,7 +10386,7 @@ +@@ -11236,7 +11236,7 @@ ;; os2*) @@ -46,7 +46,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll -@@ -10416,7 +10416,7 @@ +@@ -11266,7 +11266,7 @@ interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no @@ -55,7 +55,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by -@@ -10492,7 +10492,7 @@ +@@ -11342,7 +11342,7 @@ xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' @@ -64,7 +64,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ -@@ -10559,7 +10559,7 @@ +@@ -11409,7 +11409,7 @@ # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then @@ -73,7 +73,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else -@@ -10588,7 +10588,7 @@ +@@ -11438,7 +11438,7 @@ if test no = "$ld_shlibs"; then runpath_var= @@ -82,7 +82,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure export_dynamic_flag_spec= whole_archive_flag_spec= fi -@@ -10706,7 +10706,7 @@ +@@ -11556,7 +11556,7 @@ # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes @@ -91,7 +91,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator= fi ;; -@@ -10790,11 +10790,11 @@ +@@ -11642,11 +11642,11 @@ aix_libpath=$lt_cv_aix_libpath_ fi @@ -105,7 +105,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else -@@ -10843,7 +10843,7 @@ +@@ -11697,7 +11697,7 @@ aix_libpath=$lt_cv_aix_libpath_ fi @@ -114,7 +114,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' -@@ -10883,7 +10883,7 @@ +@@ -11737,7 +11737,7 @@ ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' @@ -123,25 +123,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_minus_L=yes ;; esac -@@ -10901,7 +10901,7 @@ - case $cc_basename in - cl*) - # Native MSVC -- hardcode_libdir_flag_spec=' ' -+ hardcode_libdir_flag_spec=" " - allow_undefined_flag=unsupported - always_export_symbols=yes - file_list_spec='@' -@@ -10942,7 +10942,7 @@ - ;; - *) - # Assume MSVC wrapper -- hardcode_libdir_flag_spec=' ' -+ hardcode_libdir_flag_spec=" " - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib -@@ -10993,7 +10993,7 @@ +@@ -11847,7 +11847,7 @@ dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' @@ -150,7 +132,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_shlibpath_var=no ;; -@@ -11003,7 +11003,7 @@ +@@ -11857,7 +11857,7 @@ # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' @@ -159,16 +141,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_direct=yes hardcode_shlibpath_var=no ;; -@@ -11019,7 +11019,7 @@ - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' -- hardcode_libdir_flag_spec='-R$libdir' -+ hardcode_libdir_flag_spec=" " - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; -@@ -11030,7 +11030,7 @@ +@@ -11884,7 +11884,7 @@ else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi @@ -177,7 +150,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator=: hardcode_direct=yes -@@ -11047,7 +11047,7 @@ +@@ -11901,7 +11901,7 @@ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then @@ -186,7 +159,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes -@@ -11124,7 +11124,7 @@ +@@ -11979,7 +11979,7 @@ esac fi if test no = "$with_gnu_ld"; then @@ -195,7 +168,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator=: case $host_cpu in -@@ -11183,7 +11183,7 @@ +@@ -12040,7 +12040,7 @@ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' @@ -204,7 +177,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes -@@ -11205,7 +11205,7 @@ +@@ -12062,7 +12062,7 @@ else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi @@ -213,7 +186,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_direct=yes hardcode_shlibpath_var=no ;; -@@ -11213,7 +11213,7 @@ +@@ -12070,7 +12070,7 @@ newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes @@ -222,7 +195,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; -@@ -11229,11 +11229,11 @@ +@@ -12086,11 +12086,11 @@ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' @@ -236,7 +209,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure fi else ld_shlibs=no -@@ -11241,7 +11241,7 @@ +@@ -12098,7 +12098,7 @@ ;; os2*) @@ -245,7 +218,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll -@@ -11277,7 +11277,7 @@ +@@ -12134,7 +12134,7 @@ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' @@ -254,7 +227,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator=: ;; -@@ -11285,7 +11285,7 @@ +@@ -12142,7 +12142,7 @@ if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' @@ -263,7 +236,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' -@@ -11293,7 +11293,7 @@ +@@ -12150,7 +12150,7 @@ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly @@ -272,7 +245,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure fi archive_cmds_need_lc='no' hardcode_libdir_separator=: -@@ -11322,7 +11322,7 @@ +@@ -12179,7 +12179,7 @@ ;; esac fi @@ -281,7 +254,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; -@@ -11349,7 +11349,7 @@ +@@ -12206,7 +12206,7 @@ else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -290,7 +263,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no -@@ -11419,7 +11419,7 @@ +@@ -12276,7 +12276,7 @@ allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no @@ -299,7 +272,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' -@@ -11436,7 +11436,7 @@ +@@ -12293,7 +12293,7 @@ uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' @@ -308,7 +281,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_shlibpath_var=no ;; -@@ -11804,7 +11804,7 @@ +@@ -12662,7 +12662,7 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no @@ -317,7 +290,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' -@@ -12094,16 +12094,16 @@ +@@ -12952,16 +12952,16 @@ ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes @@ -337,7 +310,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure ;; esac ;; -@@ -12118,7 +12118,7 @@ +@@ -12976,7 +12976,7 @@ shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' @@ -346,7 +319,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure ;; hpux9* | hpux10* | hpux11*) -@@ -12130,7 +12130,7 @@ +@@ -12988,7 +12988,7 @@ case $host_cpu in ia64*) shrext_cmds='.so' @@ -355,7 +328,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. -@@ -12146,7 +12146,7 @@ +@@ -13004,7 +13004,7 @@ ;; hppa*64*) shrext_cmds='.sl' @@ -364,7 +337,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. -@@ -12179,7 +12179,7 @@ +@@ -13037,7 +13037,7 @@ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -373,7 +346,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure ;; irix5* | irix6* | nonstopux*) -@@ -12216,7 +12216,7 @@ +@@ -13074,7 +13074,7 @@ shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" @@ -382,7 +355,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure ;; # No shared lib support for Linux oldld, aout, or coff. -@@ -12237,11 +12237,11 @@ +@@ -13095,11 +13095,11 @@ # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. @@ -396,7 +369,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure ;; # This must be glibc/ELF. -@@ -12292,7 +12292,7 @@ +@@ -13153,7 +13153,7 @@ # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. @@ -405,7 +378,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not -@@ -12322,7 +12322,7 @@ +@@ -13183,7 +13183,7 @@ soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -414,7 +387,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure dynamic_linker='NetBSD ld.elf_so' ;; -@@ -12341,7 +12341,7 @@ +@@ -13202,7 +13202,7 @@ fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes @@ -423,7 +396,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure ;; newsos6) -@@ -12359,7 +12359,7 @@ +@@ -13220,7 +13220,7 @@ soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -432,7 +405,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure dynamic_linker='ldqnx.so' ;; -@@ -12431,7 +12431,7 @@ +@@ -13292,7 +13292,7 @@ soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes @@ -441,7 +414,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; -@@ -12488,7 +12488,7 @@ +@@ -13349,7 +13349,7 @@ soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes @@ -450,7 +423,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else -@@ -12510,7 +12510,7 @@ +@@ -13371,7 +13371,7 @@ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -459,7 +432,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure ;; uts4*) -@@ -13610,7 +13610,7 @@ +@@ -14490,7 +14490,7 @@ acl_shlibext="$acl_cv_shlibext" acl_libname_spec="$acl_cv_libname_spec" acl_library_names_spec="$acl_cv_library_names_spec" @@ -468,7 +441,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" acl_hardcode_direct="$acl_cv_hardcode_direct" acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" -@@ -21296,7 +21296,7 @@ +@@ -22538,7 +22538,7 @@ with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' @@ -477,7 +450,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' -@@ -21327,7 +21327,7 @@ +@@ -22569,7 +22569,7 @@ postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' @@ -486,7 +459,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' -@@ -22485,7 +22485,7 @@ +@@ -23727,7 +23727,7 @@ finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. @@ -495,7 +468,7 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec -@@ -22582,7 +22582,7 @@ +@@ -23824,7 +23824,7 @@ # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist @@ -504,10 +477,10 @@ diff -u -r cryptsetup-2.3.3-clean/configure cryptsetup-2.3.3/configure # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator -diff -u -r cryptsetup-2.3.3-clean/Makefile.in cryptsetup-2.3.3/Makefile.in ---- cryptsetup-2.3.3-clean/Makefile.in 2020-06-10 14:05:45.781594282 +0200 -+++ cryptsetup-2.3.3/Makefile.in 2020-06-10 14:30:09.512375745 +0200 -@@ -1032,6 +1032,8 @@ +diff -u -r cryptsetup-2.4.3-clean/Makefile.in cryptsetup-2.4.3/Makefile.in +--- cryptsetup-2.4.3-clean/Makefile.in 2022-01-13 17:24:33.000000000 +0800 ++++ cryptsetup-2.4.3/Makefile.in 2022-01-16 14:08:37.096258854 +0800 +@@ -1115,6 +1115,8 @@ @CRYPTSETUP_TRUE@cryptsetup_LDADD = $(LDADD) \ @CRYPTSETUP_TRUE@ libcryptsetup.la \ @CRYPTSETUP_TRUE@ @POPT_LIBS@ \ @@ -516,31 +489,218 @@ diff -u -r cryptsetup-2.3.3-clean/Makefile.in cryptsetup-2.3.3/Makefile.in @CRYPTSETUP_TRUE@ @PWQUALITY_LIBS@ \ @CRYPTSETUP_TRUE@ @PASSWDQC_LIBS@ \ @CRYPTSETUP_TRUE@ @UUID_LIBS@ \ -@@ -1060,6 +1062,9 @@ +@@ -1147,6 +1149,9 @@ @VERITYSETUP_TRUE@veritysetup_LDADD = $(LDADD) \ @VERITYSETUP_TRUE@ libcryptsetup.la \ @VERITYSETUP_TRUE@ @POPT_LIBS@ \ -+@VERITYSETUP_TRUE@ @UUID_LIBS@ \ -+@VERITYSETUP_TRUE@ @DEVMAPPER_LIBS@ \ -+@VERITYSETUP_TRUE@ @JSON_C_LIBS@ \ - @VERITYSETUP_TRUE@ @PWQUALITY_LIBS@ \ - @VERITYSETUP_TRUE@ @PASSWDQC_LIBS@ \ ++@VERITYSETUP_TRUE@ @UUID_LIBS@ \ ++@VERITYSETUP_TRUE@ @DEVMAPPER_LIBS@ \ ++@VERITYSETUP_TRUE@ @JSON_C_LIBS@ \ @VERITYSETUP_TRUE@ @BLKID_LIBS@ -@@ -1093,6 +1093,8 @@ + + @STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@veritysetup_static_SOURCES = $(veritysetup_SOURCES) +@@ -1177,6 +1182,8 @@ @INTEGRITYSETUP_TRUE@ libcryptsetup.la \ @INTEGRITYSETUP_TRUE@ @POPT_LIBS@ \ @INTEGRITYSETUP_TRUE@ @UUID_LIBS@ \ +@INTEGRITYSETUP_TRUE@ @DEVMAPPER_LIBS@ \ +@INTEGRITYSETUP_TRUE@ @JSON_C_LIBS@ \ @INTEGRITYSETUP_TRUE@ @BLKID_LIBS@ - - @INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@integritysetup_static_SOURCES = $(integritysetup_SOURCES) -@@ -1122,6 +1122,8 @@ - @REENCRYPT_TRUE@ @POPT_LIBS@ \ - @REENCRYPT_TRUE@ @PWQUALITY_LIBS@ \ - @REENCRYPT_TRUE@ @PASSWDQC_LIBS@ \ -+@REENCRYPT_TRUE@ @DEVMAPPER_LIBS@ \ -+@REENCRYPT_TRUE@ @JSON_C_LIBS@ \ - @REENCRYPT_TRUE@ @UUID_LIBS@ \ - @REENCRYPT_TRUE@ @BLKID_LIBS@ + @INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@integritysetup_static_SOURCES = $(integritysetup_SOURCES) + +--- ./configure.orig 2023-11-26 14:22:30.912000000 -0500 ++++ ./configure 2023-11-26 14:26:21.714000000 -0500 +@@ -12336,7 +12336,7 @@ + + case $cc_basename in + tcc*) +- hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' ++ hardcode_libdir_flag_spec=" " + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) +@@ -12755,7 +12755,7 @@ + case $cc_basename in + cl* | icl*) + # Native MSVC or ICC +- hardcode_libdir_flag_spec=' ' ++ hardcode_libdir_flag_spec=" " + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' +@@ -12796,7 +12796,7 @@ + ;; + *) + # Assume MSVC and ICC wrapper +- hardcode_libdir_flag_spec=' ' ++ hardcode_libdir_flag_spec=" " + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib +@@ -12873,7 +12873,7 @@ + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly* | midnightbsd*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- hardcode_libdir_flag_spec='-R$libdir' ++ hardcode_libdir_flag_spec=" " + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; +@@ -13052,7 +13052,7 @@ + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' ++ hardcode_libdir_flag_spec=" " + ;; + esac + ;; +--- ./configure.mod 2023-11-26 14:46:49.779000000 -0500 ++++ ./configure 2023-11-26 14:47:56.962000000 -0500 +@@ -17670,7 +17670,7 @@ + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' +@@ -17958,16 +17958,16 @@ + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + esac + ;; +@@ -17982,7 +17982,7 @@ + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + hpux9* | hpux10* | hpux11*) +@@ -17994,7 +17994,7 @@ + case $host_cpu in + ia64*) + shrext_cmds='.so' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. +@@ -18010,7 +18010,7 @@ + ;; + hppa*64*) + shrext_cmds='.sl' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. +@@ -18043,7 +18043,7 @@ + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + irix5* | irix6* | nonstopux*) +@@ -18080,7 +18080,7 @@ + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + # No shared lib support for Linux oldld, aout, or coff. +@@ -18101,7 +18101,7 @@ + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. +- hardcode_into_libs=yes ++ hardcode_into_libs=no + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. +@@ -18159,7 +18159,7 @@ + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. +- hardcode_into_libs=yes ++ hardcode_into_libs=no + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not +@@ -18189,7 +18189,7 @@ + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker='NetBSD ld.elf_so' + ;; + +@@ -18208,7 +18208,7 @@ + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + newsos6) +@@ -18226,7 +18226,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker='ldqnx.so' + ;; + +@@ -18298,7 +18298,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; +@@ -18355,7 +18355,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else +@@ -18377,7 +18377,7 @@ + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + uts4*) diff --git a/patches/lvm2-2.03.23.patch b/patches/lvm2-2.03.23.patch new file mode 100644 index 00000000..587e1bb6 --- /dev/null +++ b/patches/lvm2-2.03.23.patch @@ -0,0 +1,150 @@ +--- ./lib/mm/memlock.c.orig 2023-11-27 13:52:46.281000000 -0500 ++++ ./lib/mm/memlock.c 2023-11-27 13:56:35.656000000 -0500 +@@ -160,6 +160,7 @@ + + static void _allocate_memory(void) + { ++#if 0 + #if defined(__GLIBC__) && !defined(VALGRIND_POOL) + /* Memory allocation is currently only tested with glibc + * for different C libraries, some other mechanisms might be needed +@@ -233,11 +234,14 @@ + for (i = 0; i < area; ++i) + free(areas[i]); + #endif ++#endif + } + + static void _release_memory(void) + { ++#if 0 + free(_malloc_mem); ++#endif + } + + /* +@@ -313,7 +317,7 @@ + + if (lock == LVM_MLOCK) { + if (mlock((const void*)from, sz) < 0) { +- log_sys_error("mlock", line); ++ //log_sys_error("mlock", line); + return 0; + } + } else { +--- ./libdm/libdm-stats.c.orig 2023-11-27 13:59:40.677000000 -0500 ++++ ./libdm/libdm-stats.c 2023-11-27 14:07:28.655000000 -0500 +@@ -18,7 +18,23 @@ + #include "libdm/misc/dmlib.h" + #include "libdm/misc/kdev_t.h" + ++#if 0 + #include "math.h" /* log10() */ ++#else ++static int ilog10(double x) ++{ ++ int e = 0; ++ ++ while(x > 10) ++ { ++ e++; ++ x = x / 10; ++ } ++ ++ return e; ++} ++#endif ++ + + #include + #include +@@ -556,7 +572,12 @@ + while(entry >= bins) { + value = (double) (entry--)->upper; + /* Use lround to avoid size_t -> double cast warning. */ ++#if 0 + hist_len += 1 + (size_t) lround(log10(value / scale)); ++#else ++ hist_len += 1 + ilog10(value / scale); ++#endif ++ + if (entry != bins) + hist_len++; /* ',' */ + } +@@ -1863,7 +1884,12 @@ + i = dm_bit_get_first(regions); + for (; i >= 0; i = dm_bit_get_next(regions, i)) { + /* length of region_id or range start in characters */ ++#if 0 + id_len = (i) ? 1 + (size_t) log10(i) : 1; ++#else ++ id_len = (i) ? 1 + ilog10(i) : 1; ++#endif ++ + buflen += id_len; + j = i; + do +@@ -1878,7 +1904,11 @@ + /* handle range */ + if (i != j) { + /* j is always > i, which is always >= 0 */ ++#if 0 + id_len = 1 + (size_t) log10(j); ++#else ++ id_len = 1 + ilog10(j); ++#endif + buflen += id_len + 1; /* range end plus "-" */ + } + buflen++; + +--- ./tools/lvmcmdline.c.orig 2023-11-27 14:12:46.649000000 -0500 ++++ ./tools/lvmcmdline.c 2023-11-27 14:15:47.563000000 -0500 +@@ -3438,7 +3438,7 @@ + static int _check_standard_fds(void) + { + int err = is_valid_fd(STDERR_FILENO); +- ++#if 0 + if (!is_valid_fd(STDIN_FILENO) && + !(stdin = fopen(_PATH_DEVNULL, "r"))) { + if (err) +@@ -3463,7 +3463,7 @@ + strerror(errno)); + return 0; + } +- ++#endif + return 1; + } + +@@ -3644,7 +3644,7 @@ + */ + dm_set_name_mangling_mode(DM_STRING_MANGLING_NONE); + +- if (!(cmd = create_toolcontext(0, NULL, 1, threaded, set_connections, set_filters))) { ++ if (!(cmd = create_toolcontext(0, NULL, 0, threaded, set_connections, set_filters))) { + return_NULL; + } + +--- ./make.tmpl.orig 2023-11-28 13:29:11.744000000 -0500 ++++ ./make.tmpl.in 2023-11-28 13:29:36.716000000 -0500 +@@ -210,7 +210,7 @@ + M_INSTALL_PROGRAM = -m 555 + M_INSTALL_DATA = -m 444 + endif +-INSTALL_PROGRAM = $(INSTALL) $(M_INSTALL_PROGRAM) $(STRIP) ++INSTALL_PROGRAM = $(INSTALL) $(M_INSTALL_PROGRAM) + INSTALL_DATA = $(INSTALL) -p $(M_INSTALL_DATA) + INSTALL_WDATA = $(INSTALL) -p -m 644 + +--- ./libdm/make.tmpl.orig 2023-11-28 13:29:52.760000000 -0500 ++++ ./libdm/make.tmpl.in 2023-11-28 13:30:22.336000000 -0500 +@@ -173,7 +173,7 @@ + M_INSTALL_PROGRAM = -m 555 + M_INSTALL_DATA = -m 444 + endif +-INSTALL_PROGRAM = $(INSTALL) $(M_INSTALL_PROGRAM) $(STRIP) ++INSTALL_PROGRAM = $(INSTALL) $(M_INSTALL_PROGRAM) + INSTALL_DATA = $(INSTALL) -p $(M_INSTALL_DATA) + INSTALL_WDATA = $(INSTALL) -p -m 644 + diff --git a/patches/util-linux-2.29.2.patch b/patches/util-linux-2.29.2.patch deleted file mode 100644 index 5a54b26f..00000000 --- a/patches/util-linux-2.29.2.patch +++ /dev/null @@ -1,139 +0,0 @@ ---- ./configure 2017-02-22 07:07:46.595740152 -0500 -+++ ./configure 2023-02-27 13:34:27.068000000 -0500 -@@ -13408,7 +13408,7 @@ - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no -- hardcode_into_libs=yes -+ hardcode_into_libs=no - if test ia64 = "$host_cpu"; then - # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' -@@ -13698,16 +13698,16 @@ - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes -- hardcode_into_libs=yes -+ hardcode_into_libs=no - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no -- hardcode_into_libs=yes -+ hardcode_into_libs=no - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes -- hardcode_into_libs=yes -+ hardcode_into_libs=no - ;; - esac - ;; -@@ -13722,7 +13722,7 @@ - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' -- hardcode_into_libs=yes -+ hardcode_into_libs=no - ;; - - hpux9* | hpux10* | hpux11*) -@@ -13734,7 +13734,7 @@ - case $host_cpu in - ia64*) - shrext_cmds='.so' -- hardcode_into_libs=yes -+ hardcode_into_libs=no - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. -@@ -13750,7 +13750,7 @@ - ;; - hppa*64*) - shrext_cmds='.sl' -- hardcode_into_libs=yes -+ hardcode_into_libs=no - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. -@@ -13783,7 +13783,7 @@ - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no -- hardcode_into_libs=yes -+ hardcode_into_libs=no - ;; - - irix5* | irix6* | nonstopux*) -@@ -13820,7 +13820,7 @@ - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" -- hardcode_into_libs=yes -+ hardcode_into_libs=no - ;; - - # No shared lib support for Linux oldld, aout, or coff. -@@ -13841,7 +13841,7 @@ - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. -- hardcode_into_libs=yes -+ hardcode_into_libs=no - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. -@@ -13896,7 +13896,7 @@ - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. -- hardcode_into_libs=yes -+ hardcode_into_libs=no - - # Add ABI-specific directories to the system library path. - sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" -@@ -13936,7 +13936,7 @@ - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes -- hardcode_into_libs=yes -+ hardcode_into_libs=no - ;; - - newsos6) -@@ -13954,7 +13954,7 @@ - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no -- hardcode_into_libs=yes -+ hardcode_into_libs=no - dynamic_linker='ldqnx.so' - ;; - -@@ -14026,7 +14026,7 @@ - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes -- hardcode_into_libs=yes -+ hardcode_into_libs=no - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; -@@ -14083,7 +14083,7 @@ - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes -- hardcode_into_libs=yes -+ hardcode_into_libs=no - if test yes = "$with_gnu_ld"; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else -@@ -14105,7 +14105,7 @@ - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no -- hardcode_into_libs=yes -+ hardcode_into_libs=no - ;; - - uts4*) diff --git a/patches/util-linux-2.39.patch b/patches/util-linux-2.39.patch new file mode 100644 index 00000000..e39fcfc5 --- /dev/null +++ b/patches/util-linux-2.39.patch @@ -0,0 +1,276 @@ +--- ./configure.orig 2023-05-17 06:53:16.721284360 -0400 ++++ ./configure 2023-11-28 13:57:50.012000000 -0500 +@@ -16580,7 +16580,7 @@ + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' +@@ -16870,16 +16870,16 @@ + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + esac + ;; +@@ -16894,7 +16894,7 @@ + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + hpux9* | hpux10* | hpux11*) +@@ -16906,7 +16906,7 @@ + case $host_cpu in + ia64*) + shrext_cmds='.so' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. +@@ -16922,7 +16922,7 @@ + ;; + hppa*64*) + shrext_cmds='.sl' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. +@@ -16955,7 +16955,7 @@ + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + irix5* | irix6* | nonstopux*) +@@ -16992,7 +16992,7 @@ + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + # No shared lib support for Linux oldld, aout, or coff. +@@ -17013,7 +17013,7 @@ + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. +- hardcode_into_libs=yes ++ hardcode_into_libs=no + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. +@@ -17071,7 +17071,7 @@ + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. +- hardcode_into_libs=yes ++ hardcode_into_libs=no + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" +@@ -17111,7 +17111,7 @@ + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + newsos6) +@@ -17129,7 +17129,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker='ldqnx.so' + ;; + +@@ -17201,7 +17201,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; +@@ -17258,7 +17258,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else +@@ -17280,7 +17280,7 @@ + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + uts4*) +@@ -20574,7 +20574,7 @@ + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' +@@ -20862,16 +20862,16 @@ + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + esac + ;; +@@ -20886,7 +20886,7 @@ + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + hpux9* | hpux10* | hpux11*) +@@ -20898,7 +20898,7 @@ + case $host_cpu in + ia64*) + shrext_cmds='.so' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. +@@ -20914,7 +20914,7 @@ + ;; + hppa*64*) + shrext_cmds='.sl' +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. +@@ -20947,7 +20947,7 @@ + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + irix5* | irix6* | nonstopux*) +@@ -20984,7 +20984,7 @@ + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + # No shared lib support for Linux oldld, aout, or coff. +@@ -21005,7 +21005,7 @@ + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. +- hardcode_into_libs=yes ++ hardcode_into_libs=no + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. +@@ -21063,7 +21063,7 @@ + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. +- hardcode_into_libs=yes ++ hardcode_into_libs=no + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" +@@ -21103,7 +21103,7 @@ + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + newsos6) +@@ -21121,7 +21121,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + dynamic_linker='ldqnx.so' + ;; + +@@ -21193,7 +21193,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; +@@ -21250,7 +21250,7 @@ + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +- hardcode_into_libs=yes ++ hardcode_into_libs=no + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else +@@ -21272,7 +21272,7 @@ + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +- hardcode_into_libs=yes ++ hardcode_into_libs=no + ;; + + uts4*) diff --git a/unmaintained_boards/x230-hotp-legacy/x230-hotp-legacy.config b/unmaintained_boards/x230-hotp-legacy/x230-hotp-legacy.config new file mode 100644 index 00000000..1d6233d7 --- /dev/null +++ b/unmaintained_boards/x230-hotp-legacy/x230-hotp-legacy.config @@ -0,0 +1,73 @@ +# Configuration for a x230 with HOTP (Nitrokey/Purism USB Security dongle enabled HOTP support) +# running Qubes 4.1 and other OSes. +# +# Deactivated to fit in coreboot's CONFIG_CBFS_SIZE=0x700000 : +# dropbear support(ssh client/server) +# e1000e (ethernet driver) +# +# Addition vs standard x230 board config: +# HOTP_KEY: HOTP challenge for currently supported USB Security dongles +export CONFIG_COREBOOT=y +export CONFIG_COREBOOT_VERSION=24.02.01 +export CONFIG_LINUX_VERSION=5.10.5 + +CONFIG_COREBOOT_CONFIG=config/coreboot-x230-legacy.config +CONFIG_LINUX_CONFIG=config/linux-x230-legacy.config + +#Additional hardware support +CONFIG_LINUX_USB=y +CONFIG_LINUX_E1000E=n + +CONFIG_CRYPTSETUP2=y +CONFIG_FLASHPROG=y +CONFIG_FLASHTOOLS=y +CONFIG_GPG2=y +CONFIG_KEXEC=y +CONFIG_UTIL_LINUX=y +CONFIG_LVM2=y +CONFIG_MBEDTLS=y +CONFIG_PCIUTILS=y + +#Remote attestation support +#TPM based requirements +export CONFIG_TPM=y +CONFIG_POPT=y +CONFIG_QRENCODE=y +CONFIG_TPMTOTP=y +#HOTP based remote attestation for supported USB Security dongle +#With/Without TPM support +CONFIG_HOTPKEY=y +export CONFIG_AUTO_BOOT_TIMEOUT=5 + +#Nitrokey Storage admin tool +CONFIG_NKSTORECLI=n + +#GUI Support +#Console based Whiptail support(Console based, no FB): +CONFIG_SLANG=y +CONFIG_NEWT=y +#FBWhiptail based (Graphical): +#CONFIG_CAIRO=y +#CONFIG_FBWHIPTAIL=y + +#Additional tools: +#SSH server (requires ethernet drivers, eg: CONFIG_LINUX_E1000E) +CONFIG_DROPBEAR=n +#Ethernet driver (Heads only) +CONFIG_LINUX_E1000E=n + +export CONFIG_BOOTSCRIPT=/bin/gui-init +export CONFIG_BOOT_REQ_HASH=n +export CONFIG_BOOT_REQ_ROLLBACK=n +export CONFIG_BOOT_KERNEL_ADD="" +export CONFIG_BOOT_KERNEL_REMOVE="intel_iommu=on intel_iommu=igfx_off" +export CONFIG_BOARD_NAME="Thinkpad X230-hotp-legacy" +export CONFIG_FLASH_OPTIONS="flashprog --progress --programmer internal --ifd --image bios" + +# This board has two SPI flash chips, an 8 MB that holds the IFD, +# the ME image and part of the coreboot image, and a 4 MB one that +# has the rest of the coreboot and the reset vector. +# +# Only flashing to the bios region is safe to do. The easiest is to +# flash internally when the IFD is unlocked for writing, and x230-flash +# is installed first. diff --git a/unmaintained_boards/x230-legacy-flash/x230-legacy-flash.config b/unmaintained_boards/x230-legacy-flash/x230-legacy-flash.config new file mode 100644 index 00000000..ed0e7990 --- /dev/null +++ b/unmaintained_boards/x230-legacy-flash/x230-legacy-flash.config @@ -0,0 +1,36 @@ +# Minimal configuration for a x230 to support flashrom and USB +# This top SPI flash image needed to flash legacy board counterpart internally +# This image can be flashed through 1vyrain and skulls +# IDEALLY you should flash maximized top and bottom rom images exteranlly once instead. + +export CONFIG_COREBOOT=y +export CONFIG_COREBOOT_VERSION=24.02.01 +export CONFIG_LINUX_VERSION=5.10.5 + +CONFIG_COREBOOT_CONFIG=config/coreboot-UNMAINTAINED_x230-legacy-flash.config +CONFIG_LINUX_CONFIG=config/linux-x230-flash.config + +#Add bare minimal tools for flashing boards +CONFIG_BASH=n +CONFIG_FLASHPROG=y +CONFIG_ZSTD=n +#CONFIG_GPG=y +#CONFIG_FLASHTOOLS=y +CONFIG_PCIUTILS=y +#CONFIG_MBEDTLS=y +#CONFIG_QRENCODE=y +#CONFIG_TPMTOTP=y +#CONFIG_DROPBEAR=y + + +#Additional hardware support +CONFIG_LINUX_USB=y +#CONFIG_LINUX_E1000E=y + +export CONFIG_BOOTSCRIPT=/bin/xx30-flash.init +export CONFIG_BOARD_NAME="ThinkPad X230-legacy-flash" +export CONFIG_FLASH_OPTIONS="flashprog --progress --programmer internal --ifd --image bios" + +CONFIG_LEGACY_FLASH=y + +BOARD_TARGETS := legacy_flash diff --git a/unmaintained_boards/x230-legacy/x230-legacy.config b/unmaintained_boards/x230-legacy/x230-legacy.config new file mode 100644 index 00000000..bdd82121 --- /dev/null +++ b/unmaintained_boards/x230-legacy/x230-legacy.config @@ -0,0 +1,66 @@ +# Configuration for a X230 running Qubes 4.1 and other Linux Based OSes (through kexec) +# +# Deactivated to fit in coreboot's CONFIG_CBFS_SIZE=0x700000 : +# dropbear support(ssh client/server) +# e1000e (ethernet driver) +export CONFIG_COREBOOT=y +export CONFIG_COREBOOT_VERSION=24.02.01 +export CONFIG_LINUX_VERSION=5.10.5 + +CONFIG_COREBOOT_CONFIG=config/coreboot-UNMAINTAINED_x230-legacy.config +CONFIG_LINUX_CONFIG=config/linux-UNMAINTAINED_x230-legacy.config + +#Additional hardware support +CONFIG_LINUX_USB=y +CONFIG_LINUX_E1000E=n + +CONFIG_CRYPTSETUP2=y +CONFIG_FLASHPROG=y +CONFIG_FLASHTOOLS=y +CONFIG_GPG2=y +CONFIG_KEXEC=y +CONFIG_UTIL_LINUX=y +CONFIG_LVM2=y +CONFIG_MBEDTLS=y +CONFIG_PCIUTILS=y + +#Remote attestation support +#TPM based requirements +export CONFIG_TPM=y +CONFIG_POPT=y +CONFIG_QRENCODE=y +CONFIG_TPMTOTP=y +#HOTP based remote attestation for supported USB Security dongle +#With/Without TPM support +CONFIG_HOTPKEY=n + +#Nitrokey Storage admin tool +CONFIG_NKSTORECLI=n + +#GUI Support +#Console based Whiptail support(Console based, no FB): +CONFIG_SLANG=y +CONFIG_NEWT=y +#FBWhiptail based (Graphical): +#CONFIG_CAIRO=y +#CONFIG_FBWHIPTAIL=y + +#Additional tools: +#SSH server (requires ethernet drivers, eg: CONFIG_LINUX_E1000E) +CONFIG_DROPBEAR=n + +export CONFIG_BOOTSCRIPT=/bin/gui-init +export CONFIG_BOOT_REQ_HASH=n +export CONFIG_BOOT_REQ_ROLLBACK=n +export CONFIG_BOOT_KERNEL_ADD="" +export CONFIG_BOOT_KERNEL_REMOVE="intel_iommu=on intel_iommu=igfx_off" +export CONFIG_BOARD_NAME="Thinkpad X230-legacy" +export CONFIG_FLASH_OPTIONS="flashprog --progress --programmer internal --ifd --image bios" + +# This board has two SPI flash chips, an 8 MB that holds the IFD, +# the ME image and part of the coreboot image, and a 4 MB one that +# has the rest of the coreboot and the reset vector. +# +# Only flashing to the bios region is safe to do. The easiest is to +# flash internally when the IFD is unlocked for writing, and x230-flash +# is installed first. From 70a7419c0acc32dacf5877581695922ab4c37e87 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 17 Aug 2024 10:59:31 -0400 Subject: [PATCH 07/17] WiP: fake cryptsetup reencrypt call for testing local one last time: seems like luks passphrase change only happens on one of the containers; not all Signed-off-by: Thierry Laurion --- initrd/etc/luks-functions | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index b7765a7b..169c335c 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -476,11 +476,12 @@ luks_reencrypt() { # --force-offline-reencrypt forces the reencryption to be done offline (no read/write operations on the device) # --disable-locks disables the lock feature of cryptsetup, which is enabled by default - if ! DO_WITH_DEBUG cryptsetup reencrypt \ - --perf-no_read_workqueue --perf-no_write_workqueue \ - --resilience=none --force-offline-reencrypt --disable-locks \ - "$luks_container" --key-slot "$DRK_KEYSLOT" \ - --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase; then + #if ! DO_WITH_DEBUG cryptsetup reencrypt \ + #--perf-no_read_workqueue --perf-no_write_workqueue \ + #--resilience=none --force-offline-reencrypt --disable-locks \ + #"$luks_container" --key-slot "$DRK_KEYSLOT" \ + #--key-file /tmp/luks_current_Disk_Recovery_Key_passphrase; then + if ! DO_WITH_DEBUG echo "fake cryptsetup reencrypt call"; then whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 From 03746e3e1183f5b3cfb5adbe178d8c77b139dec0 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 17 Aug 2024 12:00:43 -0400 Subject: [PATCH 08/17] seal-totp: add missing PCR7 DEBUG call for CBFS measured content, add DEBUG for TOTP secret/qrcode output to console Signed-off-by: Thierry Laurion --- initrd/bin/seal-totp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/initrd/bin/seal-totp b/initrd/bin/seal-totp index 0ef5bcfb..1fa24fbc 100755 --- a/initrd/bin/seal-totp +++ b/initrd/bin/seal-totp @@ -46,6 +46,7 @@ DEBUG "Sealing TOTP neglecting PCR5 involvement (Dynamically loaded kernel modul # pcr 6 (drive LUKS header) is not measured at sealing/unsealing of totp DEBUG "Sealing TOTP without PCR6 involvement (LUKS header consistency is not firmware integrity attestation related)" # pcr 7 is containing measurements of user injected stuff in cbfs +DEBUG "Sealing TOTP with actual state of PCR7 (User injected stuff in cbfs)" tpmr pcrread -a 7 "$pcrf" #Make sure we clear the TPM Owner Password from memory in case it failed to be used to seal TOTP tpmr seal "$TOTP_SECRET" "$TPM_NVRAM_SPACE" 0,1,2,3,4,7 "$pcrf" 312 "" "$TPM_PASSWORD" || @@ -56,5 +57,6 @@ shred -n 10 -z -u "$TOTP_SEALED" 2>/dev/null url="otpauth://totp/$HOST?secret=$secret" secret="" +DEBUG "TOTP secret output on screen (both URL and QR code)" qrenc "$url" echo "$url" From 1c8c45c6898c98ef161180074d7887c84634cd21 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 17 Aug 2024 12:01:42 -0400 Subject: [PATCH 09/17] luks-functions: fix luks_change_passphrase which was only occuring on first LUKS volume, not all Remove unneeded loop under luks_reencrypt Signed-off-by: Thierry Laurion --- initrd/etc/luks-functions | 96 ++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 56 deletions(-) diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index 169c335c..0011e0f4 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -381,7 +381,7 @@ test_luks_current_disk_recovery_key_passphrase() # We export the LUKS volume(s) that was/were validated via passphrase test export LUKS TRACE_FUNC - DEBUG "$LUKS exported to be reused" + DEBUG "LUKS container(s) $PRINTABLE_LUKS exported to be reused" break; fi done @@ -394,11 +394,12 @@ luks_reencrypt() { # then loop on that list of devices that could be opened and reencrypt/change passphrase for all the devices that could be tested opened with that passphrase select_luks_container || return 1 - # Count the number of containers to be reencrypted - num_containers=$(echo "$LUKS" | wc -w) - reencrypted_containers=0 + # Split the $LUKS variable into an array of LUKS containers + luks_containers=($LUKS) + TRACE_FUNC + DEBUG "luks_containers: ${luks_containers[@]}" - while [ $reencrypted_containers -lt $num_containers ]; do + for luks_container in "${luks_containers[@]}"; do if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then #if no external provisioning provides current LUKS Disk Recovery Key passphrase msg=$(echo -e "This will replace the encrypted container content and its LUKS Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user under the following conditions:\n 1-Every boot if no Disk Unlock Key was added to the TPM\n 2-If the TPM fails (hardware failure)\n 3-If the firmware has been tampered with/modified by the user\n\nThis process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to the LUKS device container.\n\nHit Enter to continue." | fold -w 70 -s) @@ -411,29 +412,22 @@ luks_reencrypt() { echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase fi - # Split the $LUKS variable into an array of LUKS containers - luks_containers=($LUKS) - TRACE_FUNC - DEBUG "luks_containers: $luks_containers" - - # Loop through each LUKS container - for luks_container in "${luks_containers[@]}"; do - DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then - whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ - "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 - # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. - # Maybe the container was not the right one - TRACE_FUNC - detect_boot_device - mount -o remount,rw /boot - rm -f /boot/kexec_key_devices.txt - mount -o remount,ro /boot - luks_secrets_cleanup - unset LUKS - continue - fi - done + + DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." + if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. + # Maybe the container was not the right one + TRACE_FUNC + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + unset LUKS + continue + fi DEBUG "Test opening ${luks_containers[@]} successful. Now testing key slots to determine which holds master key" for luks_container in "${luks_containers[@]}"; do @@ -500,42 +494,35 @@ luks_reencrypt() { #Exporting successfully used passphrase possibly reused by oem-factory-reset export luks_current_Disk_Recovery_Key_passphrase export LUKS - - # Increment the count of reencrypted containers - reencrypted_containers=$((reencrypted_containers + 1)) fi done done } -luks_change_passphrase() { +luks_change_passphrase() +{ TRACE_FUNC select_luks_container || return 1 - # Count the number of containers to be processed - num_containers=$(echo "$LUKS" | wc -w) - changed_containers=0 - # Split the $LUKS variable into an array of LUKS containers - IFS=' ' read -ra luks_containers <<< "$LUKS" + luks_containers=($LUKS) + TRACE_FUNC + DEBUG "luks_containers: ${luks_containers[@]}" + # Loop through each LUKS container for luks_container in "${luks_containers[@]}"; do if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ] || [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \ "Please enter the current LUKS Disk Recovery Key passphrase (slot 0).\nThen choose a strong passphrase of your own.\n\n**DICEWARE passphrase methodology is STRONGLY ADVISED.**\n\nHit Enter to continue" 0 80 - if [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then - echo -e "\nEnter your desired replacement for the actual LUKS Disk Recovery Key passphrase (At least 8 characters long):" - while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do - read -r luks_new_Disk_Recovery_Key_passphrase - done - fi + echo -e "\nEnter your desired replacement for the actual LUKS Disk Recovery Key passphrase (At least 8 characters long):" + while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do + read -r luks_new_Disk_Recovery_Key_passphrase + done - if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then - echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" - read -r luks_current_Disk_Recovery_Key_passphrase - fi + echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" + read -r luks_current_Disk_Recovery_Key_passphrase fi echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase @@ -551,7 +538,7 @@ luks_change_passphrase() { rm -f /boot/kexec_key_devices.txt mount -o remount,ro /boot luks_secrets_cleanup - unset LUKS + unset LUKS continue fi @@ -563,16 +550,13 @@ luks_change_passphrase() { fi echo "Success changing passphrase for $luks_container." - changed_containers=$((changed_containers + 1)) done - if [ $changed_containers -eq $num_containers ]; then - # All containers processed successfully - luks_current_Disk_Recovery_Key_passphrase=$luks_new_Disk_Recovery_Key_passphrase - export luks_current_Disk_Recovery_Key_passphrase - export luks_new_Disk_Recovery_Key_passphrase - export LUKS - fi + # Export the new passphrase if all containers were processed successfully + luks_current_Disk_Recovery_Key_passphrase=$luks_new_Disk_Recovery_Key_passphrase + export luks_current_Disk_Recovery_Key_passphrase + export luks_new_Disk_Recovery_Key_passphrase + export LUKS } luks_secrets_cleanup() From 0a817887320b93dc65f82af570928c45f08c8e23 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 17 Aug 2024 12:29:59 -0400 Subject: [PATCH 10/17] luks-functions: move secret placement from /tmp to /tmp/secret to be wiped when going to recovery shell and upon automatic cleanup as all other secret Signed-off-by: Thierry Laurion --- initrd/etc/luks-functions | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index 0011e0f4..dd1cd432 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -323,9 +323,9 @@ test_luks_current_disk_recovery_key_passphrase() # if no external provisioning provides current LUKS Disk Recovery Key passphrase echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" read -r luks_current_Disk_Recovery_Key_passphrase - echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase else - echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase fi # test all LUKS containers on same block device as returned by select_luks_container @@ -334,7 +334,7 @@ test_luks_current_disk_recovery_key_passphrase() # Loop on all LUKS containers on same block device for luks_container in $LUKS; do DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase + DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase # Validate past cryptsetup reencrypt attempts if [ $? -ne 0 ]; then # if we have more than one LUKS container and passphrase test unsuccessful, tell user how to change passphrase @@ -407,14 +407,14 @@ luks_reencrypt() { --msgbox "$msg" 0 80 echo -e "\nEnter the current LUKS Disk Recovery Key passphrase:" read -r luks_current_Disk_Recovery_Key_passphrase - echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase else - echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase fi DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. @@ -435,7 +435,7 @@ luks_reencrypt() { DRK_KEYSLOT=-1 DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." for i in $(seq 0 31); do - if DO_WITH_DEBUG cryptsetup open --test-passphrase $luks_container --key-slot $i --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + if DO_WITH_DEBUG cryptsetup open --test-passphrase $luks_container --key-slot $i --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then DRK_KEYSLOT=$i DEBUG "$luks_container: Found key-slot $DRK_KEYSLOT that can be unlocked with the current passphrase. breaking loop" break @@ -474,7 +474,7 @@ luks_reencrypt() { #--perf-no_read_workqueue --perf-no_write_workqueue \ #--resilience=none --force-offline-reencrypt --disable-locks \ #"$luks_container" --key-slot "$DRK_KEYSLOT" \ - #--key-file /tmp/luks_current_Disk_Recovery_Key_passphrase; then + #--key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then if ! DO_WITH_DEBUG echo "fake cryptsetup reencrypt call"; then whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 @@ -525,11 +525,11 @@ luks_change_passphrase() read -r luks_current_Disk_Recovery_Key_passphrase fi - echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase - echo -n "$luks_new_Disk_Recovery_Key_passphrase" > /tmp/luks_new_Disk_Recovery_Key_passphrase + echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_new_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_new_Disk_Recovery_Key_passphrase DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 TRACE_FUNC @@ -543,7 +543,7 @@ luks_change_passphrase() fi echo -e "\nChanging $luks_container LUKS encrypted disk passphrase to the new LUKS Disk Recovery Key passphrase..." - if ! DO_WITH_DEBUG cryptsetup luksChangeKey "$luks_container" --key-file=/tmp/luks_current_Disk_Recovery_Key_passphrase /tmp/luks_new_Disk_Recovery_Key_passphrase; then + if ! DO_WITH_DEBUG cryptsetup luksChangeKey "$luks_container" --key-file=/tmp/secret/luks_current_Disk_Recovery_Key_passphrase /tmp/secret/luks_new_Disk_Recovery_Key_passphrase; then whiptail --title 'Failed to change LUKS passphrase' --msgbox \ "Failed to change the passphrase for $luks_container.\nPlease try again." 0 80 continue @@ -564,8 +564,8 @@ luks_secrets_cleanup() TRACE_FUNC #Cleanup - shred -n 10 -z -u /tmp/luks_new_Disk_Recovery_Key_passphrase 2>/dev/null || true - shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null || true + shred -n 10 -z -u /tmp/secret/luks_new_Disk_Recovery_Key_passphrase 2>/dev/null || true + shred -n 10 -z -u /tmp/secret/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null || true #Unset variables (when in same boot) unset luks_current_Disk_Recovery_Key_passphrase From d2fe615a5e23aa203f0d937cdd297ce7186d01f9 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 17 Aug 2024 12:36:56 -0400 Subject: [PATCH 11/17] luks-functions: wording fixes Signed-off-by: Thierry Laurion Signed-off-by: Thierry Laurion --- initrd/etc/luks-functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index dd1cd432..0510071d 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -344,7 +344,7 @@ test_luks_current_disk_recovery_key_passphrase() #whiptail_error --title 'error' --msgbox 'error' 0 80 #Neither work today. Not related to this PR... Using whiptail without coloring. - msg=$(echo -e "All $PRINTABLE_LUKS must unlock with the same Disk Recovery Key passphrase for the current operation to succeed.\n\nTo change individual LUKS container passphrase, do so from 'Options-> Change LUKS Disk Recovery Key passphrase'\n\nThen retry this operation." | fold -w 70 -s) + msg=$(echo -e "All $PRINTABLE_LUKS LUKS containers must be unlockable by a shared Disk Recovery Key (DRK) passphrase for the current operation to succeed.\n\nTo change individual LUKS container DRK passphrase, do so from 'Options-> Change LUKS Disk Recovery Key passphrase'\n\nThen retry this operation." | fold -w 70 -s) whiptail --title "$luks_container"': Wrong current LUKS Disk Recovery Key passphrase?' \ --msgbox "$msg" 0 80 From 7d3e4fdc0315ca756bc0e2f556f3cb995e61341a Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 17 Aug 2024 13:06:11 -0400 Subject: [PATCH 12/17] Revert+adapt "WiP: fake cryptsetup reencrypt call for testing local one last time: seems like luks passphrase change only happens on one of the containers; not all" This reverts commit 20e9392b97c9ed42b85ae930a163131997640a44. To test this PR without reencryption, just 'git revert' this commit Signed-off-by: Thierry Laurion --- initrd/etc/luks-functions | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index 0510071d..6f95a1c2 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -470,12 +470,11 @@ luks_reencrypt() { # --force-offline-reencrypt forces the reencryption to be done offline (no read/write operations on the device) # --disable-locks disables the lock feature of cryptsetup, which is enabled by default - #if ! DO_WITH_DEBUG cryptsetup reencrypt \ - #--perf-no_read_workqueue --perf-no_write_workqueue \ - #--resilience=none --force-offline-reencrypt --disable-locks \ - #"$luks_container" --key-slot "$DRK_KEYSLOT" \ - #--key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then - if ! DO_WITH_DEBUG echo "fake cryptsetup reencrypt call"; then + if ! DO_WITH_DEBUG cryptsetup reencrypt \ + --perf-no_read_workqueue --perf-no_write_workqueue \ + --resilience=none --force-offline-reencrypt --disable-locks \ + "$luks_container" --key-slot "$DRK_KEYSLOT" \ + --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase; then whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 From 8b51a1f7a81077eb78b9c4e457e07b58bfafb0d4 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 22 Oct 2024 14:45:20 -0400 Subject: [PATCH 13/17] optiplex boards: bumper kernel from 5.10.5 to 5.10.214. No config file changes Signed-off-by: Thierry Laurion --- .../optiplex-7010_9010-hotp-maximized.config | 2 +- .../optiplex-7010_9010-maximized.config | 2 +- .../optiplex-7010_9010_TXT-hotp-maximized.config | 2 +- .../optiplex-7010_9010_TXT-maximized.config | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/optiplex-7010_9010-hotp-maximized/optiplex-7010_9010-hotp-maximized.config b/boards/optiplex-7010_9010-hotp-maximized/optiplex-7010_9010-hotp-maximized.config index 19f83c07..d837daa2 100644 --- a/boards/optiplex-7010_9010-hotp-maximized/optiplex-7010_9010-hotp-maximized.config +++ b/boards/optiplex-7010_9010-hotp-maximized/optiplex-7010_9010-hotp-maximized.config @@ -8,7 +8,7 @@ # - Includes: Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-optiplex-7019_9010-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/optiplex-7010_9010-maximized/optiplex-7010_9010-maximized.config b/boards/optiplex-7010_9010-maximized/optiplex-7010_9010-maximized.config index 7b5e6e71..0b286522 100644 --- a/boards/optiplex-7010_9010-maximized/optiplex-7010_9010-maximized.config +++ b/boards/optiplex-7010_9010-maximized/optiplex-7010_9010-maximized.config @@ -8,7 +8,7 @@ # - DOES NOT INCLUDE Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-optiplex-7019_9010-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/optiplex-7010_9010_TXT-hotp-maximized/optiplex-7010_9010_TXT-hotp-maximized.config b/boards/optiplex-7010_9010_TXT-hotp-maximized/optiplex-7010_9010_TXT-hotp-maximized.config index 194475e0..a5597efd 100644 --- a/boards/optiplex-7010_9010_TXT-hotp-maximized/optiplex-7010_9010_TXT-hotp-maximized.config +++ b/boards/optiplex-7010_9010_TXT-hotp-maximized/optiplex-7010_9010_TXT-hotp-maximized.config @@ -8,7 +8,7 @@ # - Includes: Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-optiplex-7019_9010_TXT-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config diff --git a/boards/optiplex-7010_9010_TXT-maximized/optiplex-7010_9010_TXT-maximized.config b/boards/optiplex-7010_9010_TXT-maximized/optiplex-7010_9010_TXT-maximized.config index 2e62094e..1880e0e0 100644 --- a/boards/optiplex-7010_9010_TXT-maximized/optiplex-7010_9010_TXT-maximized.config +++ b/boards/optiplex-7010_9010_TXT-maximized/optiplex-7010_9010_TXT-maximized.config @@ -8,7 +8,7 @@ # - DOES NOT INCLUDE Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code) export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=24.02.01 -export CONFIG_LINUX_VERSION=5.10.5 +export CONFIG_LINUX_VERSION=5.10.214 CONFIG_COREBOOT_CONFIG=config/coreboot-optiplex-7019_9010_TXT-maximized.config CONFIG_LINUX_CONFIG=config/linux-x230-maximized.config From 67372063ab90c9631fa89df4799f0df6dbe909c3 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 22 Oct 2024 15:29:26 -0400 Subject: [PATCH 14/17] GUI scripts: add whiptail_error and whiptail_warning since https://github.com/linuxboot/heads/pull/1787 fixed the issue Signed-off-by: Thierry Laurion --- initrd/etc/gui_functions | 3 --- initrd/etc/luks-functions | 20 +++++++------------- initrd/init | 2 -- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/initrd/etc/gui_functions b/initrd/etc/gui_functions index e4b7ed4d..38958b1a 100755 --- a/initrd/etc/gui_functions +++ b/initrd/etc/gui_functions @@ -37,7 +37,6 @@ mount_usb() # -- Display related functions -- # Produce a whiptail prompt with 'warning' background, works for fbwhiptail and newt whiptail_warning() { - #TODO: Cannot be called as is under luks_functions with string expension in title: why? if [ -x /bin/fbwhiptail ]; then whiptail $BG_COLOR_WARNING "$@" else @@ -47,7 +46,6 @@ whiptail_warning() { # Produce a whiptail prompt with 'error' background, works for fbwhiptail and newt whiptail_error() { - #TODO: Cannot be called as is under luks_functions with string expension in title: why? if [ -x /bin/fbwhiptail ]; then whiptail $BG_COLOR_ERROR "$@" else @@ -57,7 +55,6 @@ whiptail_error() { # Produce a whiptail prompt of the given type - 'error', 'warning', or 'normal' whiptail_type() { - TRACE_FUNC local TYPE="$1" shift case "$TYPE" in diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index 6f95a1c2..94789a95 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -339,13 +339,8 @@ test_luks_current_disk_recovery_key_passphrase() if [ $? -ne 0 ]; then # if we have more than one LUKS container and passphrase test unsuccessful, tell user how to change passphrase if [ $(echo $LUKS | wc -w) -gt 1 ]; then - #TODO remove this once whiptail_error whiptail_warning can take titles with double quotes - #whiptail_warning --title 'tes' --msgbox 'test' 0 80 - #whiptail_error --title 'error' --msgbox 'error' 0 80 - #Neither work today. Not related to this PR... Using whiptail without coloring. - msg=$(echo -e "All $PRINTABLE_LUKS LUKS containers must be unlockable by a shared Disk Recovery Key (DRK) passphrase for the current operation to succeed.\n\nTo change individual LUKS container DRK passphrase, do so from 'Options-> Change LUKS Disk Recovery Key passphrase'\n\nThen retry this operation." | fold -w 70 -s) - whiptail --title "$luks_container"': Wrong current LUKS Disk Recovery Key passphrase?' \ + whiptail_error --title "$luks_container"': Wrong current LUKS Disk Recovery Key passphrase?' \ --msgbox "$msg" 0 80 TRACE_FUNC @@ -354,7 +349,7 @@ test_luks_current_disk_recovery_key_passphrase() # We exited to caller, LUKS still set. TODO: problem? Should we call all cleaning functions on die? fi - whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 TRACE_FUNC @@ -411,11 +406,10 @@ luks_reencrypt() { else echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase fi - DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then - whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. # Maybe the container was not the right one @@ -444,7 +438,7 @@ luks_reencrypt() { # Validate if a key slot was found if [ $DRK_KEYSLOT -eq -1 ]; then - whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. # Maybe the container was not the right one @@ -475,7 +469,7 @@ luks_reencrypt() { --resilience=none --force-offline-reencrypt --disable-locks \ "$luks_container" --key-slot "$DRK_KEYSLOT" \ --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase; then - whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 TRACE_FUNC @@ -529,7 +523,7 @@ luks_change_passphrase() DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then - whiptail --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 TRACE_FUNC detect_boot_device @@ -543,7 +537,7 @@ luks_change_passphrase() echo -e "\nChanging $luks_container LUKS encrypted disk passphrase to the new LUKS Disk Recovery Key passphrase..." if ! DO_WITH_DEBUG cryptsetup luksChangeKey "$luks_container" --key-file=/tmp/secret/luks_current_Disk_Recovery_Key_passphrase /tmp/secret/luks_new_Disk_Recovery_Key_passphrase; then - whiptail --title 'Failed to change LUKS passphrase' --msgbox \ + whiptail_error --title 'Failed to change LUKS passphrase' --msgbox \ "Failed to change the passphrase for $luks_container.\nPlease try again." 0 80 continue fi diff --git a/initrd/init b/initrd/init index 847f9e2a..55a894a7 100755 --- a/initrd/init +++ b/initrd/init @@ -103,12 +103,10 @@ fi #Specify whiptail background colors cues under FBWhiptail only if [ -x /bin/fbwhiptail ]; then - DEBUG "fbwhiptail BG_COLOR_* exported" export BG_COLOR_WARNING="${CONFIG_WARNING_BG_COLOR:-"--background-gradient 0 0 0 150 125 0"}" export BG_COLOR_ERROR="${CONFIG_ERROR_BG_COLOR:-"--background-gradient 0 0 0 150 0 0"}" export BG_COLOR_MAIN_MENU="normal" else - DEBUG "whiptail TEXT_BG_COLOR_* exported" export TEXT_BG_COLOR_WARNING="${CONFIG_WARNING_TEXT_BG_COLOR:-"yellow"}" export TEXT_BG_COLOR_ERROR="${CONFIG_ERROR_TEXT_BG_COLOR:-"red"}" export BG_COLOR_MAIN_MENU="normal" From 91b88dadabb9e741d5dc09b81076378fd88140e9 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 22 Oct 2024 17:02:18 -0400 Subject: [PATCH 15/17] initrd/etc/luks-functions: fix path to wrong luks key for reencrypt call Signed-off-by: Thierry Laurion --- initrd/etc/luks-functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index 94789a95..de5f41c5 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -468,7 +468,7 @@ luks_reencrypt() { --perf-no_read_workqueue --perf-no_write_workqueue \ --resilience=none --force-offline-reencrypt --disable-locks \ "$luks_container" --key-slot "$DRK_KEYSLOT" \ - --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase; then + --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 From 0f25b064e02ddd81429a9e2071252f52d938f210 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 22 Oct 2024 17:42:47 -0400 Subject: [PATCH 16/17] luks-functions: detect non-usb LUKS partitions that can be unlocked with prompted DRK then ask user to confirm that those are all ok to reencryt/change passphrase onto (oem factory reset/manual, whatever) - cache/reuse that passphrase, used afterward to find which LUKS keyslot contains the DRK, which is used to direct reencryption, also reused for passphrase change. - refactoring detection + testing of prompted LUKS passphrase for discovered LUKS containers that can be unlocked with same passphrase to prompt user for selection TODO: remove duplicate luks passphrase unlocking volumes functions for the moment Signed-off-by: Thierry Laurion --- initrd/etc/luks-functions | 414 ++++++++++++++++++++------------------ 1 file changed, 219 insertions(+), 195 deletions(-) diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index de5f41c5..a6902330 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -1,20 +1,110 @@ #!/bin/bash -# LUKS related functions +# This script contains various functions related to LUKS (Linux Unified Key Setup) encryption management. . /etc/functions . /etc/gui_functions . /tmp/config -#List all LUKS devices on the system -list_luks_devices() { +# List all LUKS devices on the system that are not USB +list_local_luks_devices() { TRACE_FUNC - #generate a list of devices to choose from that contain a LUKS header lvm vgscan || true - blkid | cut -d ':' -f 1 | while read device; do - if cryptsetup isLuks $device; then echo $device; fi + blkid | cut -d ':' -f 1 | while read -r device; do + DEBUG "Checking device: $device" + if cryptsetup isLuks "$device"; then + DEBUG "Device $device is a LUKS device" + dev_name=$(basename "$device") + parent_dev_name=$(echo "$dev_name" | sed 's/[0-9]*$//') + if [ -e "/sys/block/$parent_dev_name" ]; then + DEBUG "Device $device exists in /sys/block" + if ! stat -c %N "/sys/block/$parent_dev_name" 2>/dev/null | grep -q "usb"; then + DEBUG "Device $device is not a USB device" + echo "$device" + else + DEBUG "Device $device is a USB device, skipping" + fi + else + DEBUG "Device $device does not exist in /sys/block, skipping" + fi + else + DEBUG "Device $device is not a LUKS device" + fi done | sort } +# Prompt for LUKS Disk Recovery Key passphrase +prompt_luks_passphrase() { + TRACE_FUNC + while [[ ${#luks_current_Disk_Recovery_Key_passphrase} -lt 8 ]]; do + echo -e "\nEnter the LUKS Disk Recovery Key passphrase (At least 8 characters long):" + read -r luks_current_Disk_Recovery_Key_passphrase + if [[ ${#luks_current_Disk_Recovery_Key_passphrase} -lt 8 ]]; then + echo -e "\nPassphrase must be at least 8 characters long. Please try again." + unset luks_current_Disk_Recovery_Key_passphrase + continue + fi + done + echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase +} + +# Test LUKS passphrase against all found LUKS containers that are not USB +test_luks_passphrase() { + TRACE_FUNC + + list_local_luks_devices >/tmp/luks_devices.txt + if [ ! -s /tmp/luks_devices.txt ]; then + warn "No LUKS devices found" + return 1 + fi + + valid_luks_devices=() + while read -r luks_device; do + DEBUG "Testing passphrase on $luks_device" + if cryptsetup open --test-passphrase "$luks_device" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then + DEBUG "Passphrase valid for $luks_device" + valid_luks_devices+=("$luks_device") + else + DEBUG "Passphrase test failed on $luks_device" + fi + done /tmp/luks_container_size_percent + echo "10" >/tmp/luks_container_size_percent elif [ "$option_index" = "2" ]; then - echo "25" > /tmp/luks_container_size_percent + echo "25" >/tmp/luks_container_size_percent elif [ "$option_index" = "3" ]; then - echo "50" > /tmp/luks_container_size_percent + echo "50" >/tmp/luks_container_size_percent elif [ "$option_index" = "4" ]; then - echo "75" > /tmp/luks_container_size_percent + echo "75" >/tmp/luks_container_size_percent else die "Error selecting LUKS container size percentage of device" fi @@ -55,20 +145,19 @@ select_luks_container_size_percent() { # Partition a device interactively with two partitions: a LUKS container # containing private ext4 partition and second public exFAT partition # Size provisioning is done by percentage of the device -interactive_prepare_thumb_drive() -{ +interactive_prepare_thumb_drive() { TRACE_FUNC #Refactoring: only one parameter needed to be prompted for: the passphrase for LUKS container if not coming from oem-provisioning #If no passphrase was provided, ask user to select passphrase for LUKS container # if no device provided as parameter, we will ask user to select device to partition # if no percentage provided as parameter, we will default to 10% of device to use for LUKS container # we will validate parameters and not make them positional and print a usage function first - + #Set defaults - DEVICE="" #Will list all usb storage devices if not provided as parameter + DEVICE="" #Will list all usb storage devices if not provided as parameter PERCENTAGE="10" #default to 10% of device to use for LUKS container (requires a LUKS partition bigger then 32mb!) - PASSPHRASE="" #Will prompt user for passphrase if not provided as parameter - + PASSPHRASE="" #Will prompt user for passphrase if not provided as parameter + #Parse parameters while [ $# -gt 0 ]; do case "$1" in @@ -101,29 +190,30 @@ interactive_prepare_thumb_drive() #If no passphrase was provided, ask user to select passphrase for LUKS container #console based no whiptail while [[ ${#PASSPHRASE} -lt 8 ]]; do - { - echo -e "\nEnter passphrase for LUKS container (At least 8 characters long):" - #hide passphrase input from read command - read -r -s PASSPHRASE - #skip confirmation if passphrase is less then 8 characters long (continue) - if [[ ${#PASSPHRASE} -lt 8 ]]; then - echo -e "\nPassphrase must be at least 8 characters long. Please try again." - unset PASSPHRASE - continue - fi - #validate passphrase and ask user to re-enter if not at least 8 characters long - #confirm passphrase - echo -e "\nConfirm passphrase for LUKS container:" - #hide passphrase input from read command - read -r -s PASSPHRASE_CONFIRM - #compare passphrase and passphrase confirmation - if [ "$PASSPHRASE" != "$PASSPHRASE_CONFIRM" ]; then - echo -e "\nPassphrases do not match. Please try again." - unset PASSPHRASE - unset PASSPHRASE_CONFIRM - fi + { + echo -e "\nEnter passphrase for LUKS container (At least 8 characters long):" + #hide passphrase input from read command + read -r -s PASSPHRASE + #skip confirmation if passphrase is less then 8 characters long (continue) + if [[ ${#PASSPHRASE} -lt 8 ]]; then + echo -e "\nPassphrase must be at least 8 characters long. Please try again." + unset PASSPHRASE + continue + fi + #validate passphrase and ask user to re-enter if not at least 8 characters long + #confirm passphrase + echo -e "\nConfirm passphrase for LUKS container:" + #hide passphrase input from read command + read -r -s PASSPHRASE_CONFIRM + #compare passphrase and passphrase confirmation + if [ "$PASSPHRASE" != "$PASSPHRASE_CONFIRM" ]; then + echo -e "\nPassphrases do not match. Please try again." + unset PASSPHRASE + unset PASSPHRASE_CONFIRM + fi - };done + } + done fi #If no device was provided, ask user to select device to partition @@ -131,8 +221,8 @@ interactive_prepare_thumb_drive() #warn user to disconnect all external drives if [ -x /bin/whiptail ]; then whiptail_warning --title "WARNING: Disconnect all external drives" --msgbox \ - "WARNING: Please disconnect all external drives before proceeding.\n\nHit Enter to continue." 0 80 \ - || die "User cancelled wiping and repartitioning of $DEVICE" + "WARNING: Please disconnect all external drives before proceeding.\n\nHit Enter to continue." 0 80 || + die "User cancelled wiping and repartitioning of $DEVICE" else echo -e -n "Warning: Please disconnect all external drives before proceeding.\n\nHit Enter to continue?" read -r -p " [Y/n] " response @@ -150,7 +240,7 @@ interactive_prepare_thumb_drive() enable_usb_storage #list all usb storage devices - list_usb_storage disks > /tmp/devices.txt + list_usb_storage disks >/tmp/devices.txt if [ $(cat /tmp/devices.txt | wc -l) -gt 0 ]; then file_selector "/tmp/devices.txt" "Select device to partition" if [ "$FILE" == "" ]; then @@ -187,8 +277,7 @@ interactive_prepare_thumb_drive() # parameters: # $1 - block device of flash drive # $2 - percent of device allocated to LUKS [1-99] -confirm_thumb_drive_format() -{ +confirm_thumb_drive_format() { TRACE_FUNC local DEVICE LUKS_PERCENTAGE DISK_SIZE_BYTES DISK_SIZE_DISPLAY LUKS_PERCENTAGE LUKS_SIZE_MB MSG @@ -229,8 +318,7 @@ confirm_thumb_drive_format() # $1 - block device of flash drive # $2 - percentage of flash drive to allocate to LUKS [1-99] # $3 - passphrase for LUKS container -prepare_thumb_drive() -{ +prepare_thumb_drive() { TRACE_FUNC local DEVICE PERCENTAGE PASSPHRASE DISK_SIZE_BYTES PERCENTAGE_MB @@ -266,61 +354,28 @@ prepare_thumb_drive() echo "Done." } -select_luks_container() -{ - #TODO: extend logic to prompt for block devices with model if multiple LUKS are found on block device instead of partitions - # Then feed luks with those partitions so that reencrypt and passphrase change can use passphrase to test all selected +# Select LUKS container +select_luks_container() { TRACE_FUNC if [ -s /boot/kexec_key_devices.txt ]; then DEBUG "Reusing known good LUKS container device from /boot/kexec_key_devices.txt" - LUKS=$(cut -d ' ' -f1 /boot/kexec_key_devices.txt) + LUKS=$(cut -d ' ' -f1 /boot/kexec_key_devices.txt) DEBUG "LUKS container device: $(echo $LUKS)" - # LUKS variable not exported yet, prompt for LUKS device elif [ -z "$LUKS" ]; then - list_luks_devices > /tmp/luks_devices.txt - #if /tmp/luks_devices.txt exists and is not empty - if [ -s /tmp/luks_devices.txt ]; then - file_selector "/tmp/luks_devices.txt" "Select LUKS container device" - if [ "$FILE" == "" ]; then - return 1 - else - #TODO: What about BRTFS multi LUKS setup of QubesOS? - # if multiple LUKS containers are found on same block device - # select all of the luks containers on same block device instead of just one - # note that block devices for example under /dev/sda will be /dev/sda1, /dev/sda2, etc - # so we need to select all of the partitions on the same block device from /tmp/luks_devices.txt - # and then export them to LUKS variable - # then reencrypt and passphrase change functions will loop on all of the LUKS containers - # and test passphrase on all of them - if grep -q "$(echo $FILE | sed 's/[0-9]*$//')" /tmp/luks_devices.txt; then - DEBUG "Multiple LUKS containers found on same block device, selecting them all" - LUKS=$(grep $(echo $FILE | sed 's/[0-9]*$//') /tmp/luks_devices.txt) - else - DEBUG "Single LUKS container found on block device, assigning to LUKS variable" - LUKS=$FILE - fi - fi - else - warn "No encrypted device found" - return 1 + main_luks_selection fi fi } -test_luks_current_disk_recovery_key_passphrase() -{ - #TODO: reuse/generalize usage of this function. Tests for LUKS are still done 4 times independently of this helper +# Test LUKS current disk recovery key passphrase +test_luks_current_disk_recovery_key_passphrase() { TRACE_FUNC while :; do select_luks_container || return 1 - # LUKS contains multiline string of LUKS containers on same block device - # transform it into words of a same string separated by space PRINTABLE_LUKS=$(echo $LUKS) - TRACE_FUNC if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then - # if no external provisioning provides current LUKS Disk Recovery Key passphrase echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" read -r luks_current_Disk_Recovery_Key_passphrase echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase @@ -328,91 +383,62 @@ test_luks_current_disk_recovery_key_passphrase() echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase fi - # test all LUKS containers on same block device as returned by select_luks_container echo -e "\n$PRINTABLE_LUKS: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - # Loop on all LUKS containers on same block device for luks_container in $LUKS; do DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase - # Validate past cryptsetup reencrypt attempts - if [ $? -ne 0 ]; then - # if we have more than one LUKS container and passphrase test unsuccessful, tell user how to change passphrase - if [ $(echo $LUKS | wc -w) -gt 1 ]; then - msg=$(echo -e "All $PRINTABLE_LUKS LUKS containers must be unlockable by a shared Disk Recovery Key (DRK) passphrase for the current operation to succeed.\n\nTo change individual LUKS container DRK passphrase, do so from 'Options-> Change LUKS Disk Recovery Key passphrase'\n\nThen retry this operation." | fold -w 70 -s) - whiptail_error --title "$luks_container"': Wrong current LUKS Disk Recovery Key passphrase?' \ - --msgbox "$msg" 0 80 - - TRACE_FUNC - luks_secrets_cleanup - die "$PRINTABLE_LUKS individual containers NEED to share the same Disk Recovery Key passphrase" - # We exited to caller, LUKS still set. TODO: problem? Should we call all cleaning functions on die? - fi - + if ! cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ - "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 - TRACE_FUNC - + "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 detect_boot_device mount -o remount,rw /boot rm -f /boot/kexec_key_devices.txt mount -o remount,ro /boot luks_secrets_cleanup - # remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. - # maybe the container was not the right one unset LUKS else - # LuksOpen test was successful. Cleanup should be called only when done - # Exporting successfully used passphrase possibly reused by oem-factory-reset echo "$luks_container: unlocking LUKS container with current Disk Recovery Key passphrase successful" - - # Exporting successfully used passphrase possibly reused by oem-factory-reset export luks_current_Disk_Recovery_Key_passphrase fi done - # exit while loop if LUKS variable is not empty if [ -n "$LUKS" ]; then - # We export the LUKS volume(s) that was/were validated via passphrase test export LUKS TRACE_FUNC DEBUG "LUKS container(s) $PRINTABLE_LUKS exported to be reused" - break; + break fi done } +# Function to re-encrypt LUKS partitions luks_reencrypt() { TRACE_FUNC - #TODO: REFACTOR This and luks passphrase change function needs to loop on same drive discovered luks containers so that reencrypt/passwd change is done on all luks containers of same drive - # Ideal would be to list luks devices and then try keep and append LUKS devices to a list of devices to reencrypt or change passphrase - # then loop on that list of devices that could be opened and reencrypt/change passphrase for all the devices that could be tested opened with that passphrase - select_luks_container || return 1 + test_luks_current_disk_recovery_key_passphrase || return 1 - # Split the $LUKS variable into an array of LUKS containers luks_containers=($LUKS) TRACE_FUNC DEBUG "luks_containers: ${luks_containers[@]}" for luks_container in "${luks_containers[@]}"; do if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then - #if no external provisioning provides current LUKS Disk Recovery Key passphrase - msg=$(echo -e "This will replace the encrypted container content and its LUKS Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user under the following conditions:\n 1-Every boot if no Disk Unlock Key was added to the TPM\n 2-If the TPM fails (hardware failure)\n 3-If the firmware has been tampered with/modified by the user\n\nThis process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to the LUKS device container.\n\nHit Enter to continue." | fold -w 70 -s) - whiptail --title 'Reencrypt LUKS encrypted container ?' \ - --msgbox "$msg" 0 80 - echo -e "\nEnter the current LUKS Disk Recovery Key passphrase:" - read -r luks_current_Disk_Recovery_Key_passphrase - echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase + if [ -f /tmp/secret/luks_current_Disk_Recovery_Key_passphrase ]; then + luks_current_Disk_Recovery_Key_passphrase=$(cat /tmp/secret/luks_current_Disk_Recovery_Key_passphrase) + else + msg=$(echo -e "This will replace the encrypted container content and its LUKS Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user under the following conditions:\n 1-Every boot if no Disk Unlock Key was added to the TPM\n 2-If the TPM fails (hardware failure)\n 3-If the firmware has been tampered with/modified by the user\n\nThis process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to the LUKS device container.\n\nHit Enter to continue." | fold -w 70 -s) + whiptail --title 'Reencrypt LUKS encrypted container ?' --msgbox "$msg" 0 80 + echo -e "\nEnter the current LUKS Disk Recovery Key passphrase:" + read -r -s luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase + fi else - echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase fi - + DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ - "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 - # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. - # Maybe the container was not the right one + "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 TRACE_FUNC detect_boot_device mount -o remount,rw /boot @@ -422,26 +448,25 @@ luks_reencrypt() { unset LUKS continue fi - + DEBUG "Test opening ${luks_containers[@]} successful. Now testing key slots to determine which holds master key" for luks_container in "${luks_containers[@]}"; do - # First obtain which luks1/luks2 key-slot can be unlocked with the key-file DRK_KEYSLOT=-1 DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." for i in $(seq 0 31); do - if DO_WITH_DEBUG cryptsetup open --test-passphrase $luks_container --key-slot $i --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then + DEBUG "Testing key slot $i on $luks_container" + if DO_WITH_DEBUG cryptsetup open --test-passphrase $luks_container --key-slot $i --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then DRK_KEYSLOT=$i DEBUG "$luks_container: Found key-slot $DRK_KEYSLOT that can be unlocked with the current passphrase. breaking loop" break + else + DEBUG "Key slot $i on $luks_container cannot be unlocked with the current passphrase" fi done - # Validate if a key slot was found if [ $DRK_KEYSLOT -eq -1 ]; then whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ - "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 - # Remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. - # Maybe the container was not the right one + "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 TRACE_FUNC detect_boot_device mount -o remount,rw /boot @@ -465,13 +490,12 @@ luks_reencrypt() { # --disable-locks disables the lock feature of cryptsetup, which is enabled by default if ! DO_WITH_DEBUG cryptsetup reencrypt \ - --perf-no_read_workqueue --perf-no_write_workqueue \ - --resilience=none --force-offline-reencrypt --disable-locks \ - "$luks_container" --key-slot "$DRK_KEYSLOT" \ - --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then + --perf-no_read_workqueue --perf-no_write_workqueue \ + --resilience=none --force-offline-reencrypt --disable-locks \ + "$luks_container" --key-slot "$DRK_KEYSLOT" \ + --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ - "If you previously changed it and do not remember it, you will have to\n reinstall the OS from a an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 - + "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 TRACE_FUNC #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. @@ -492,68 +516,70 @@ luks_reencrypt() { done } -luks_change_passphrase() -{ - TRACE_FUNC +# Function to change LUKS passphrase +luks_change_passphrase() { + TRACE_FUNC + test_luks_current_disk_recovery_key_passphrase || return 1 - select_luks_container || return 1 - - # Split the $LUKS variable into an array of LUKS containers luks_containers=($LUKS) TRACE_FUNC DEBUG "luks_containers: ${luks_containers[@]}" - # Loop through each LUKS container - for luks_container in "${luks_containers[@]}"; do - if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ] || [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then - whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \ - "Please enter the current LUKS Disk Recovery Key passphrase (slot 0).\nThen choose a strong passphrase of your own.\n\n**DICEWARE passphrase methodology is STRONGLY ADVISED.**\n\nHit Enter to continue" 0 80 + for luks_container in "${luks_containers[@]}"; do + if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ] || [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then + if [ -f /tmp/secret/luks_current_Disk_Recovery_Key_passphrase ]; then + luks_current_Disk_Recovery_Key_passphrase=$(cat /tmp/secret/luks_current_Disk_Recovery_Key_passphrase) + else + whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \ + "Please enter the current LUKS Disk Recovery Key passphrase (slot 0).\nThen choose a strong passphrase of your own.\n\n**DICEWARE passphrase methodology is STRONGLY ADVISED.**\n\nHit Enter to continue" 0 80 - echo -e "\nEnter your desired replacement for the actual LUKS Disk Recovery Key passphrase (At least 8 characters long):" - while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do - read -r luks_new_Disk_Recovery_Key_passphrase - done + echo -e "\nEnter your desired replacement for the actual LUKS Disk Recovery Key passphrase (At least 8 characters long):" + while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do + read -r luks_new_Disk_Recovery_Key_passphrase + done - echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" - read -r luks_current_Disk_Recovery_Key_passphrase - fi + TRACE_FUNC + echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):" + read -r luks_current_Disk_Recovery_Key_passphrase + fi + fi - echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase - echo -n "$luks_new_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_new_Disk_Recovery_Key_passphrase + echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase + echo -n "$luks_new_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_new_Disk_Recovery_Key_passphrase - DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase > /dev/null 2>&1; then - whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ - "If you previously changed it and do not remember it, you will have to\n reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an\n external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 - TRACE_FUNC - detect_boot_device - mount -o remount,rw /boot - rm -f /boot/kexec_key_devices.txt - mount -o remount,ro /boot - luks_secrets_cleanup - unset LUKS - continue - fi + DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." + if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then + whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + TRACE_FUNC + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + unset LUKS + continue + fi - echo -e "\nChanging $luks_container LUKS encrypted disk passphrase to the new LUKS Disk Recovery Key passphrase..." - if ! DO_WITH_DEBUG cryptsetup luksChangeKey "$luks_container" --key-file=/tmp/secret/luks_current_Disk_Recovery_Key_passphrase /tmp/secret/luks_new_Disk_Recovery_Key_passphrase; then - whiptail_error --title 'Failed to change LUKS passphrase' --msgbox \ - "Failed to change the passphrase for $luks_container.\nPlease try again." 0 80 - continue - fi + echo -e "\nChanging $luks_container LUKS encrypted disk passphrase to the new LUKS Disk Recovery Key passphrase..." + if ! DO_WITH_DEBUG cryptsetup luksChangeKey "$luks_container" --key-file=/tmp/secret/luks_current_Disk_Recovery_Key_passphrase /tmp/secret/luks_new_Disk_Recovery_Key_passphrase; then + whiptail_error --title 'Failed to change LUKS passphrase' --msgbox \ + "Failed to change the passphrase for $luks_container.\nPlease try again." 0 80 + continue + fi - echo "Success changing passphrase for $luks_container." - done + echo "Success changing passphrase for $luks_container." + done - # Export the new passphrase if all containers were processed successfully - luks_current_Disk_Recovery_Key_passphrase=$luks_new_Disk_Recovery_Key_passphrase - export luks_current_Disk_Recovery_Key_passphrase - export luks_new_Disk_Recovery_Key_passphrase - export LUKS + # Export the new passphrase if all containers were processed successfully + luks_current_Disk_Recovery_Key_passphrase=$luks_new_Disk_Recovery_Key_passphrase + export luks_current_Disk_Recovery_Key_passphrase + export luks_new_Disk_Recovery_Key_passphrase + export LUKS } -luks_secrets_cleanup() -{ +# Cleanup LUKS secrets +luks_secrets_cleanup() { TRACE_FUNC #Cleanup @@ -563,7 +589,5 @@ luks_secrets_cleanup() #Unset variables (when in same boot) unset luks_current_Disk_Recovery_Key_passphrase unset luks_new_Disk_Recovery_Key_passphrase - - #TODO: refactor logic of selec_luks_conatainer, where to put - #unset LUKS + unset LUKS } From f43fe1a83631620d2851763a8d60007e44b3cc93 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 29 Oct 2024 09:28:59 -0400 Subject: [PATCH 17/17] initrd/bin/kexec-seal-key initrd/etc/luks-functions: last fixups - fi misplaced - rework reencryption loop - added verbose output on TPM DUK key addition when LUKS container can be unlocked with DRK Current state, left todo for future work: TPM DUK: - TPM DUK setup on defautl boot reuses /boot/kexec_key_devices.txt if present - If not, list all LUKS partitions, asks user for selection and makes sure LUKS passphrase can unlock all - Works on both LUKSv1 and LUKSv2 containers, reusing OS installer settings (Heads doesn't enforce better then OS installer LUKS parameters) LUKS passphrase change/LUKS reencryption: - Reuses /boot/kexec_key_devices.txt if existing - If not, prompts for LUKS passphase, list all LUKS containers not being USB based and attempt to unlock all those, listing only the ones successfully unlocked - Prompts user to reuse found unlockable LUKS partitions with LUKS passphrase, caches and reuse in other LUKS operations (passphrase change as well from oem factory reset/re-ownership) - Deals properly with LUKSv1/LUKSv2/multiple LUKS containers and reencrypt/passphrase changes them all if accepted, otherwise asks user to select individual LUKS container Tested on luksv1,luksv2, btrfs under luks (2x containers) and TPM DUK setup up to booting OS. All good TODO: - LUKS passphrase check is done multiple times across TPM DUK, reencryption and luks passphrase. Could refactor to change this, but since this op is done only one reencrypt+passphrase change) upon hardare reception from OEM, I stopped caring here. Signed-off-by: Thierry Laurion --- initrd/bin/kexec-seal-key | 2 +- initrd/etc/luks-functions | 136 ++++++++++++++++++-------------------- 2 files changed, 64 insertions(+), 74 deletions(-) diff --git a/initrd/bin/kexec-seal-key b/initrd/bin/kexec-seal-key index 0765d8b9..bd35fe35 100755 --- a/initrd/bin/kexec-seal-key +++ b/initrd/bin/kexec-seal-key @@ -78,7 +78,7 @@ for dev in $key_devices ; do DEBUG "Testing $DISK_RECOVERY_KEY_FILE keyfile created from provided passphrase against $dev individual key slots" if cryptsetup open $dev --test-passphrase --key-file "$DISK_RECOVERY_KEY_FILE" >/dev/null 2>&1; then - DEBUG "LUKS device $dev unlocked successfully with the DRK passphrase" + echo "++++++ $dev: LUKS device unlocked successfully with the DRK passphrase" luks_drk_passphrase_valid=1 break else diff --git a/initrd/etc/luks-functions b/initrd/etc/luks-functions index a6902330..eb2d1fb6 100644 --- a/initrd/etc/luks-functions +++ b/initrd/etc/luks-functions @@ -363,7 +363,6 @@ select_luks_container() { DEBUG "LUKS container device: $(echo $LUKS)" elif [ -z "$LUKS" ]; then main_luks_selection - fi fi } @@ -420,21 +419,21 @@ luks_reencrypt() { TRACE_FUNC DEBUG "luks_containers: ${luks_containers[@]}" - for luks_container in "${luks_containers[@]}"; do - if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then - if [ -f /tmp/secret/luks_current_Disk_Recovery_Key_passphrase ]; then - luks_current_Disk_Recovery_Key_passphrase=$(cat /tmp/secret/luks_current_Disk_Recovery_Key_passphrase) - else - msg=$(echo -e "This will replace the encrypted container content and its LUKS Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user under the following conditions:\n 1-Every boot if no Disk Unlock Key was added to the TPM\n 2-If the TPM fails (hardware failure)\n 3-If the firmware has been tampered with/modified by the user\n\nThis process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to the LUKS device container.\n\nHit Enter to continue." | fold -w 70 -s) - whiptail --title 'Reencrypt LUKS encrypted container ?' --msgbox "$msg" 0 80 - echo -e "\nEnter the current LUKS Disk Recovery Key passphrase:" - read -r -s luks_current_Disk_Recovery_Key_passphrase - echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase - fi + if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then + if [ -f /tmp/secret/luks_current_Disk_Recovery_Key_passphrase ]; then + luks_current_Disk_Recovery_Key_passphrase=$(cat /tmp/secret/luks_current_Disk_Recovery_Key_passphrase) else + msg=$(echo -e "This will replace the encrypted container content and its LUKS Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user under the following conditions:\n 1-Every boot if no Disk Unlock Key was added to the TPM\n 2-If the TPM fails (hardware failure)\n 3-If the firmware has been tampered with/modified by the user\n\nThis process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to the LUKS device container.\n\nHit Enter to continue." | fold -w 70 -s) + whiptail --title 'Reencrypt LUKS encrypted container ?' --msgbox "$msg" 0 80 + echo -e "\nEnter the current LUKS Disk Recovery Key passphrase:" + read -r -s luks_current_Disk_Recovery_Key_passphrase echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase fi + else + echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase + fi + for luks_container in "${luks_containers[@]}"; do DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ @@ -449,70 +448,61 @@ luks_reencrypt() { continue fi - DEBUG "Test opening ${luks_containers[@]} successful. Now testing key slots to determine which holds master key" - for luks_container in "${luks_containers[@]}"; do - DRK_KEYSLOT=-1 - DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." - for i in $(seq 0 31); do - DEBUG "Testing key slot $i on $luks_container" - if DO_WITH_DEBUG cryptsetup open --test-passphrase $luks_container --key-slot $i --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then - DRK_KEYSLOT=$i - DEBUG "$luks_container: Found key-slot $DRK_KEYSLOT that can be unlocked with the current passphrase. breaking loop" - break - else - DEBUG "Key slot $i on $luks_container cannot be unlocked with the current passphrase" - fi - done - - if [ $DRK_KEYSLOT -eq -1 ]; then - whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ - "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 - TRACE_FUNC - detect_boot_device - mount -o remount,rw /boot - rm -f /boot/kexec_key_devices.txt - mount -o remount,ro /boot - luks_secrets_cleanup - unset LUKS - continue - fi - - # Now reencrypt the LUKS container with the same key slot - # Warn and launch actual reencryption - echo -e "\nReencrypting $luks_container LUKS encrypted drive content with current Recovery Disk Key passphrase..." - warn "DO NOT POWER DOWN MACHINE, UNPLUG AC OR REMOVE BATTERY DURING REENCRYPTION PROCESS" - - # --perf-no_read_workqueue and/or --perf-no_write_workqueue improve encryption/reencrypton performance on kernel 5.10.9+ - # bypassing dm-crypt queues. - # Ref https://github.com/cloudflare/linux/issues/1#issuecomment-729695518 - # --resilience=none disables the resilience feature of cryptsetup, which is enabled by default - # --force-offline-reencrypt forces the reencryption to be done offline (no read/write operations on the device) - # --disable-locks disables the lock feature of cryptsetup, which is enabled by default - - if ! DO_WITH_DEBUG cryptsetup reencrypt \ - --perf-no_read_workqueue --perf-no_write_workqueue \ - --resilience=none --force-offline-reencrypt --disable-locks \ - "$luks_container" --key-slot "$DRK_KEYSLOT" \ - --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then - whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ - "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 - TRACE_FUNC - - #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container. - #maybe the container was not the right one - detect_boot_device - mount -o remount,rw /boot - rm -f /boot/kexec_key_devices.txt - mount -o remount,ro /boot - luks_secrets_cleanup - unset LUKS + DEBUG "Test opening ${luks_container} successful. Now testing key slots to determine which holds master key" + DRK_KEYSLOT=-1 + DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..." + for i in $(seq 0 31); do + DEBUG "Testing key slot $i on $luks_container" + if DO_WITH_DEBUG cryptsetup open --test-passphrase $luks_container --key-slot $i --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then + DRK_KEYSLOT=$i + DEBUG "$luks_container: Found key-slot $DRK_KEYSLOT that can be unlocked with the current passphrase. breaking loop" + break else - #Reencryption was successful. Cleanup should be called only when done - #Exporting successfully used passphrase possibly reused by oem-factory-reset - export luks_current_Disk_Recovery_Key_passphrase - export LUKS + DEBUG "Key slot $i on $luks_container cannot be unlocked with the current passphrase" fi done + + if [ $DRK_KEYSLOT -eq -1 ]; then + whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + TRACE_FUNC + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + unset LUKS + continue + fi + + # --perf-no_read_workqueue and/or --perf-no_write_workqueue improve encryption/reencrypton performance on kernel 5.10.9+ + # bypassing dm-crypt queues. + # Ref https://github.com/cloudflare/linux/issues/1#issuecomment-729695518 + # --resilience=none disables the resilience feature of cryptsetup, which is enabled by default + # --force-offline-reencrypt forces the reencryption to be done offline (no read/write operations on the device) + # --disable-locks disables the lock feature of cryptsetup, which is enabled by default + + echo -e "\nReencrypting $luks_container LUKS encrypted drive content with current Recovery Disk Key passphrase..." + warn "DO NOT POWER DOWN MACHINE, UNPLUG AC OR REMOVE BATTERY DURING REENCRYPTION PROCESS" + + if ! DO_WITH_DEBUG cryptsetup reencrypt \ + --perf-no_read_workqueue --perf-no_write_workqueue \ + --resilience=none --force-offline-reencrypt --disable-locks \ + "$luks_container" --key-slot "$DRK_KEYSLOT" \ + --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then + whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \ + "If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80 + TRACE_FUNC + detect_boot_device + mount -o remount,rw /boot + rm -f /boot/kexec_key_devices.txt + mount -o remount,ro /boot + luks_secrets_cleanup + unset LUKS + else + export luks_current_Disk_Recovery_Key_passphrase + export LUKS + fi done }