blob: 3497a5bd680a8c22ca0edb9b2e2b00983bd643e3 [file] [log] [blame]
#ifndef WUFFS_DEFLATE_H
#define WUFFS_DEFLATE_H
// Code generated by wuffs-c. DO NOT EDIT.
#ifndef WUFFS_BASE_HEADER_H
#define WUFFS_BASE_HEADER_H
// Copyright 2017 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
// Wuffs assumes that:
// - converting a uint32_t to a size_t will never overflow.
// - converting a size_t to a uint64_t will never overflow.
#if (__WORDSIZE != 32) && (__WORDSIZE != 64)
#error "Wuffs requires a word size of either 32 or 64 bits"
#endif
// WUFFS_VERSION is the major.minor version number as a uint32_t. The major
// number is the high 16 bits. The minor number is the low 16 bits.
//
// The intention is to bump the version number at least on every API / ABI
// backwards incompatible change.
//
// For now, the API and ABI are simply unstable and can change at any time.
//
// TODO: don't hard code this in base-header.h.
#define WUFFS_VERSION ((uint32_t)0x00001)
// 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()".
typedef struct {
} wuffs_base__empty_struct;
// ---------------- Numeric Types
// Flicks are a unit of time. One flick (frame-tick) is 1 / 705_600_000 of a
// second. See https://github.com/OculusVR/Flicks
typedef uint64_t wuffs_base__flicks;
#define WUFFS_BASE__FLICKS_PER_SECOND ((uint64_t)705600000)
#define WUFFS_BASE__FLICKS_PER_MILLISECOND ((uint64_t)705600)
// --------
static inline uint8_t wuffs_base__u8__min(uint8_t x, uint8_t y) {
return x < y ? x : y;
}
static inline uint8_t wuffs_base__u8__max(uint8_t x, uint8_t y) {
return x > y ? x : y;
}
static inline uint16_t wuffs_base__u16__min(uint16_t x, uint16_t y) {
return x < y ? x : y;
}
static inline uint16_t wuffs_base__u16__max(uint16_t x, uint16_t y) {
return x > y ? x : y;
}
static inline uint32_t wuffs_base__u32__min(uint32_t x, uint32_t y) {
return x < y ? x : y;
}
static inline uint32_t wuffs_base__u32__max(uint32_t x, uint32_t y) {
return x > y ? x : y;
}
static inline uint64_t wuffs_base__u64__min(uint64_t x, uint64_t y) {
return x < y ? x : y;
}
static inline uint64_t wuffs_base__u64__max(uint64_t x, uint64_t y) {
return x > y ? x : y;
}
// --------
// Saturating arithmetic (sat_add, sat_sub) branchless bit-twiddling algorithms
// are per https://locklessinc.com/articles/sat_arithmetic/
//
// It is important that the underlying types are unsigned integers, as signed
// integer arithmetic overflow is undefined behavior in C.
static inline uint8_t wuffs_base__u8__sat_add(uint8_t x, uint8_t y) {
uint8_t res = x + y;
res |= -(res < x);
return res;
}
static inline uint8_t wuffs_base__u8__sat_sub(uint8_t x, uint8_t y) {
uint8_t res = x - y;
res &= -(res <= x);
return res;
}
static inline uint16_t wuffs_base__u16__sat_add(uint16_t x, uint16_t y) {
uint16_t res = x + y;
res |= -(res < x);
return res;
}
static inline uint16_t wuffs_base__u16__sat_sub(uint16_t x, uint16_t y) {
uint16_t res = x - y;
res &= -(res <= x);
return res;
}
static inline uint32_t wuffs_base__u32__sat_add(uint32_t x, uint32_t y) {
uint32_t res = x + y;
res |= -(res < x);
return res;
}
static inline uint32_t wuffs_base__u32__sat_sub(uint32_t x, uint32_t y) {
uint32_t res = x - y;
res &= -(res <= x);
return res;
}
static inline uint64_t wuffs_base__u64__sat_add(uint64_t x, uint64_t y) {
uint64_t res = x + y;
res |= -(res < x);
return res;
}
static inline uint64_t wuffs_base__u64__sat_sub(uint64_t x, uint64_t y) {
uint64_t res = x - y;
res &= -(res <= x);
return res;
}
// --------
// Clang also defines "__GNUC__".
static inline uint16_t wuffs_base__u16__byte_swapped(uint16_t x) {
#if defined(__GNUC__)
return __builtin_bswap16(x);
#else
return (x >> 8) | (x << 8);
#endif
}
static inline uint32_t wuffs_base__u32__byte_swapped(uint32_t x) {
#if defined(__GNUC__)
return __builtin_bswap32(x);
#else
static const uint32_t mask8 = 0x00FF00FF;
x = ((x >> 8) & mask8) | ((x & mask8) << 8);
return (x >> 16) | (x << 16);
#endif
}
static inline uint64_t wuffs_base__u64__byte_swapped(uint64_t x) {
#if defined(__GNUC__)
return __builtin_bswap64(x);
#else
static const uint64_t mask8 = 0x00FF00FF00FF00FF;
static const uint64_t mask16 = 0x0000FFFF0000FFFF;
x = ((x >> 8) & mask8) | ((x & mask8) << 8);
x = ((x >> 16) & mask16) | ((x & mask16) << 16);
return (x >> 32) | (x << 32);
#endif
}
// ---------------- Slices and Tables
// WUFFS_BASE__SLICE is a 1-dimensional buffer.
//
// A value with all fields NULL or zero is a valid, empty slice.
#define WUFFS_BASE__SLICE(T) \
struct { \
T* ptr; \
size_t len; \
}
// WUFFS_BASE__TABLE is a 2-dimensional buffer.
//
// A value with all fields NULL or zero is a valid, empty table.
#define WUFFS_BASE__TABLE(T) \
struct { \
T* ptr; \
size_t width; \
size_t height; \
size_t stride; \
}
typedef WUFFS_BASE__SLICE(uint8_t) wuffs_base__slice_u8;
typedef WUFFS_BASE__SLICE(uint16_t) wuffs_base__slice_u16;
typedef WUFFS_BASE__SLICE(uint32_t) wuffs_base__slice_u32;
typedef WUFFS_BASE__SLICE(uint64_t) wuffs_base__slice_u64;
typedef WUFFS_BASE__TABLE(uint8_t) wuffs_base__table_u8;
typedef WUFFS_BASE__TABLE(uint16_t) wuffs_base__table_u16;
typedef WUFFS_BASE__TABLE(uint32_t) wuffs_base__table_u32;
typedef WUFFS_BASE__TABLE(uint64_t) wuffs_base__table_u64;
// ---------------- Ranges and Rects
// Ranges are either inclusive ("range_ii") or exclusive ("range_ie") on the
// high end. Both the "ii" and "ie" flavors are useful in practice.
//
// The "ei" and "ee" flavors also exist in theory, but aren't widely used. In
// Wuffs, the low end is always inclusive.
//
// The "ii" (closed interval) flavor is useful when refining e.g. "the set of
// all uint32_t values" to a contiguous subset: "uint32_t values in the closed
// interval [M, N]", for uint32_t values M and N. An unrefined type (in other
// words, the set of all uint32_t values) is not representable in the "ie"
// flavor because if N equals ((1<<32) - 1) then (N + 1) will overflow.
//
// On the other hand, the "ie" (half-open interval) flavor is recommended by
// Dijkstra's "Why numbering should start at zero" at
// http://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF and a further
// discussion of motivating rationale is at
// https://www.quora.com/Why-are-Python-ranges-half-open-exclusive-instead-of-closed-inclusive
//
// For example, with "ie", the number of elements in "uint32_t values in the
// half-open interval [M, N)" is equal to max(0, N-M). Furthermore, that number
// of elements (in one dimension, a length, in two dimensions, a width or
// height) is itself representable as a uint32_t without overflow, again for
// uint32_t values M and N. In the contrasting "ii" flavor, the length of the
// closed interval [0, (1<<32) - 1] is 1<<32, which cannot be represented as a
// uint32_t. In Wuffs, because of this potential overflow, the "ie" flavor has
// length / width / height methods, but the "ii" flavor does not.
//
// It is valid for min > max (for range_ii) or for min >= max (for range_ie),
// in which case the range is empty. There are multiple representations of an
// empty range.
typedef struct {
uint32_t min_inclusive;
uint32_t max_inclusive;
} wuffs_base__range_ii_u32;
static inline bool wuffs_base__range_ii_u32__is_empty(
wuffs_base__range_ii_u32 r) {
return r.min_inclusive > r.max_inclusive;
}
static inline bool wuffs_base__range_ii_u32__equals(
wuffs_base__range_ii_u32 r,
wuffs_base__range_ii_u32 s) {
return (r.min_inclusive == s.min_inclusive &&
r.max_inclusive == s.max_inclusive) ||
(wuffs_base__range_ii_u32__is_empty(r) &&
wuffs_base__range_ii_u32__is_empty(s));
}
static inline bool wuffs_base__range_ii_u32__contains(
wuffs_base__range_ii_u32 r,
uint32_t x) {
return (r.min_inclusive <= x) && (x <= r.max_inclusive);
}
static inline wuffs_base__range_ii_u32 wuffs_base__range_ii_u32__intersection(
wuffs_base__range_ii_u32 r,
wuffs_base__range_ii_u32 s) {
r.min_inclusive = wuffs_base__u32__max(r.min_inclusive, s.min_inclusive);
r.max_inclusive = wuffs_base__u32__min(r.max_inclusive, s.max_inclusive);
return r;
}
static inline wuffs_base__range_ii_u32 wuffs_base__range_ii_u32__union(
wuffs_base__range_ii_u32 r,
wuffs_base__range_ii_u32 s) {
if (wuffs_base__range_ii_u32__is_empty(r)) {
return s;
}
if (wuffs_base__range_ii_u32__is_empty(s)) {
return r;
}
r.min_inclusive = wuffs_base__u32__min(r.min_inclusive, s.min_inclusive);
r.max_inclusive = wuffs_base__u32__max(r.max_inclusive, s.max_inclusive);
return r;
}
// --------
typedef struct {
uint32_t min_inclusive;
uint32_t max_exclusive;
} wuffs_base__range_ie_u32;
static inline bool wuffs_base__range_ie_u32__is_empty(
wuffs_base__range_ie_u32 r) {
return r.min_inclusive >= r.max_exclusive;
}
static inline bool wuffs_base__range_ie_u32__equals(
wuffs_base__range_ie_u32 r,
wuffs_base__range_ie_u32 s) {
return (r.min_inclusive == s.min_inclusive &&
r.max_exclusive == s.max_exclusive) ||
(wuffs_base__range_ie_u32__is_empty(r) &&
wuffs_base__range_ie_u32__is_empty(s));
}
static inline bool wuffs_base__range_ie_u32__contains(
wuffs_base__range_ie_u32 r,
uint32_t x) {
return (r.min_inclusive <= x) && (x < r.max_exclusive);
}
static inline wuffs_base__range_ie_u32 wuffs_base__range_ie_u32__intersection(
wuffs_base__range_ie_u32 r,
wuffs_base__range_ie_u32 s) {
r.min_inclusive = wuffs_base__u32__max(r.min_inclusive, s.min_inclusive);
r.max_exclusive = wuffs_base__u32__min(r.max_exclusive, s.max_exclusive);
return r;
}
static inline wuffs_base__range_ie_u32 wuffs_base__range_ie_u32__union(
wuffs_base__range_ie_u32 r,
wuffs_base__range_ie_u32 s) {
if (wuffs_base__range_ie_u32__is_empty(r)) {
return s;
}
if (wuffs_base__range_ie_u32__is_empty(s)) {
return r;
}
r.min_inclusive = wuffs_base__u32__min(r.min_inclusive, s.min_inclusive);
r.max_exclusive = wuffs_base__u32__max(r.max_exclusive, s.max_exclusive);
return r;
}
static inline uint32_t wuffs_base__range_ie_u32__length(
wuffs_base__range_ie_u32 r) {
return wuffs_base__u32__sat_sub(r.max_exclusive, r.min_inclusive);
}
// --------
typedef struct {
uint64_t min_inclusive;
uint64_t max_inclusive;
} wuffs_base__range_ii_u64;
static inline bool wuffs_base__range_ii_u64__is_empty(
wuffs_base__range_ii_u64 r) {
return r.min_inclusive > r.max_inclusive;
}
static inline bool wuffs_base__range_ii_u64__equals(
wuffs_base__range_ii_u64 r,
wuffs_base__range_ii_u64 s) {
return (r.min_inclusive == s.min_inclusive &&
r.max_inclusive == s.max_inclusive) ||
(wuffs_base__range_ii_u64__is_empty(r) &&
wuffs_base__range_ii_u64__is_empty(s));
}
static inline bool wuffs_base__range_ii_u64__contains(
wuffs_base__range_ii_u64 r,
uint64_t x) {
return (r.min_inclusive <= x) && (x <= r.max_inclusive);
}
static inline wuffs_base__range_ii_u64 wuffs_base__range_ii_u64__intersection(
wuffs_base__range_ii_u64 r,
wuffs_base__range_ii_u64 s) {
r.min_inclusive = wuffs_base__u64__max(r.min_inclusive, s.min_inclusive);
r.max_inclusive = wuffs_base__u64__min(r.max_inclusive, s.max_inclusive);
return r;
}
static inline wuffs_base__range_ii_u64 wuffs_base__range_ii_u64__union(
wuffs_base__range_ii_u64 r,
wuffs_base__range_ii_u64 s) {
if (wuffs_base__range_ii_u64__is_empty(r)) {
return s;
}
if (wuffs_base__range_ii_u64__is_empty(s)) {
return r;
}
r.min_inclusive = wuffs_base__u64__min(r.min_inclusive, s.min_inclusive);
r.max_inclusive = wuffs_base__u64__max(r.max_inclusive, s.max_inclusive);
return r;
}
// --------
typedef struct {
uint64_t min_inclusive;
uint64_t max_exclusive;
} wuffs_base__range_ie_u64;
static inline bool wuffs_base__range_ie_u64__is_empty(
wuffs_base__range_ie_u64 r) {
return r.min_inclusive >= r.max_exclusive;
}
static inline bool wuffs_base__range_ie_u64__equals(
wuffs_base__range_ie_u64 r,
wuffs_base__range_ie_u64 s) {
return (r.min_inclusive == s.min_inclusive &&
r.max_exclusive == s.max_exclusive) ||
(wuffs_base__range_ie_u64__is_empty(r) &&
wuffs_base__range_ie_u64__is_empty(s));
}
static inline bool wuffs_base__range_ie_u64__contains(
wuffs_base__range_ie_u64 r,
uint64_t x) {
return (r.min_inclusive <= x) && (x < r.max_exclusive);
}
static inline wuffs_base__range_ie_u64 wuffs_base__range_ie_u64__intersection(
wuffs_base__range_ie_u64 r,
wuffs_base__range_ie_u64 s) {
r.min_inclusive = wuffs_base__u64__max(r.min_inclusive, s.min_inclusive);
r.max_exclusive = wuffs_base__u64__min(r.max_exclusive, s.max_exclusive);
return r;
}
static inline wuffs_base__range_ie_u64 wuffs_base__range_ie_u64__union(
wuffs_base__range_ie_u64 r,
wuffs_base__range_ie_u64 s) {
if (wuffs_base__range_ie_u64__is_empty(r)) {
return s;
}
if (wuffs_base__range_ie_u64__is_empty(s)) {
return r;
}
r.min_inclusive = wuffs_base__u64__min(r.min_inclusive, s.min_inclusive);
r.max_exclusive = wuffs_base__u64__max(r.max_exclusive, s.max_exclusive);
return r;
}
static inline uint64_t wuffs_base__range_ie_u64__length(
wuffs_base__range_ie_u64 r) {
return wuffs_base__u64__sat_sub(r.max_exclusive, r.min_inclusive);
}
// --------
// wuffs_base__rect_ii_u32 is a rectangle (a 2-dimensional range) on the
// integer grid. The "ii" means that the bounds are inclusive on the low end
// and inclusive on the high end. It contains all points (x, y) such that
// ((min_inclusive_x <= x) && (x <= max_inclusive_x)) and likewise for y.
//
// It is valid for min > max, in which case the rectangle is empty. There are
// multiple representations of an empty rectangle.
//
// The X and Y axes increase right and down.
typedef struct {
uint32_t min_inclusive_x;
uint32_t min_inclusive_y;
uint32_t max_inclusive_x;
uint32_t max_inclusive_y;
} wuffs_base__rect_ii_u32;
static inline bool wuffs_base__rect_ii_u32__is_empty(
wuffs_base__rect_ii_u32 r) {
return (r.min_inclusive_x > r.max_inclusive_x) ||
(r.min_inclusive_y > r.max_inclusive_y);
}
static inline bool wuffs_base__rect_ii_u32__equals(wuffs_base__rect_ii_u32 r,
wuffs_base__rect_ii_u32 s) {
return (r.min_inclusive_x == s.min_inclusive_x &&
r.min_inclusive_y == s.min_inclusive_y &&
r.max_inclusive_x == s.max_inclusive_x &&
r.max_inclusive_y == s.max_inclusive_y) ||
(wuffs_base__rect_ii_u32__is_empty(r) &&
wuffs_base__rect_ii_u32__is_empty(s));
}
static inline bool wuffs_base__rect_ii_u32__contains(wuffs_base__rect_ii_u32 r,
uint32_t x,
uint32_t y) {
return (r.min_inclusive_x <= x) && (x <= r.max_inclusive_x) &&
(r.min_inclusive_y <= y) && (y <= r.max_inclusive_y);
}
static inline wuffs_base__rect_ii_u32 wuffs_base__rect_ii_u32__intersection(
wuffs_base__rect_ii_u32 r,
wuffs_base__rect_ii_u32 s) {
r.min_inclusive_x =
wuffs_base__u32__max(r.min_inclusive_x, s.min_inclusive_x);
r.min_inclusive_y =
wuffs_base__u32__max(r.min_inclusive_y, s.min_inclusive_y);
r.max_inclusive_x =
wuffs_base__u32__min(r.max_inclusive_x, s.max_inclusive_x);
r.max_inclusive_y =
wuffs_base__u32__min(r.max_inclusive_y, s.max_inclusive_y);
return r;
}
static inline wuffs_base__rect_ii_u32 wuffs_base__rect_ii_u32__union(
wuffs_base__rect_ii_u32 r,
wuffs_base__rect_ii_u32 s) {
if (wuffs_base__rect_ii_u32__is_empty(r)) {
return s;
}
if (wuffs_base__rect_ii_u32__is_empty(s)) {
return r;
}
r.min_inclusive_x =
wuffs_base__u32__min(r.min_inclusive_x, s.min_inclusive_x);
r.min_inclusive_y =
wuffs_base__u32__min(r.min_inclusive_y, s.min_inclusive_y);
r.max_inclusive_x =
wuffs_base__u32__max(r.max_inclusive_x, s.max_inclusive_x);
r.max_inclusive_y =
wuffs_base__u32__max(r.max_inclusive_y, s.max_inclusive_y);
return r;
}
// --------
// wuffs_base__rect_ie_u32 is a rectangle (a 2-dimensional range) on the
// integer grid. The "ie" means that the bounds are inclusive on the low end
// and exclusive on the high end. It contains all points (x, y) such that
// ((min_inclusive_x <= x) && (x < max_exclusive_x)) and likewise for y.
//
// It is valid for min >= max, in which case the rectangle is empty. There are
// multiple representations of an empty rectangle, including a value with all
// fields zero.
//
// The X and Y axes increase right and down.
typedef struct {
uint32_t min_inclusive_x;
uint32_t min_inclusive_y;
uint32_t max_exclusive_x;
uint32_t max_exclusive_y;
} wuffs_base__rect_ie_u32;
static inline bool wuffs_base__rect_ie_u32__is_empty(
wuffs_base__rect_ie_u32 r) {
return (r.min_inclusive_x >= r.max_exclusive_x) ||
(r.min_inclusive_y >= r.max_exclusive_y);
}
static inline bool wuffs_base__rect_ie_u32__equals(wuffs_base__rect_ie_u32 r,
wuffs_base__rect_ie_u32 s) {
return (r.min_inclusive_x == s.min_inclusive_x &&
r.min_inclusive_y == s.min_inclusive_y &&
r.max_exclusive_x == s.max_exclusive_x &&
r.max_exclusive_y == s.max_exclusive_y) ||
(wuffs_base__rect_ie_u32__is_empty(r) &&
wuffs_base__rect_ie_u32__is_empty(s));
}
static inline bool wuffs_base__rect_ie_u32__contains(wuffs_base__rect_ie_u32 r,
uint32_t x,
uint32_t y) {
return (r.min_inclusive_x <= x) && (x < r.max_exclusive_x) &&
(r.min_inclusive_y <= y) && (y < r.max_exclusive_y);
}
static inline wuffs_base__rect_ie_u32 wuffs_base__rect_ie_u32__intersection(
wuffs_base__rect_ie_u32 r,
wuffs_base__rect_ie_u32 s) {
r.min_inclusive_x =
wuffs_base__u32__max(r.min_inclusive_x, s.min_inclusive_x);
r.min_inclusive_y =
wuffs_base__u32__max(r.min_inclusive_y, s.min_inclusive_y);
r.max_exclusive_x =
wuffs_base__u32__min(r.max_exclusive_x, s.max_exclusive_x);
r.max_exclusive_y =
wuffs_base__u32__min(r.max_exclusive_y, s.max_exclusive_y);
return r;
}
static inline wuffs_base__rect_ie_u32 wuffs_base__rect_ie_u32__union(
wuffs_base__rect_ie_u32 r,
wuffs_base__rect_ie_u32 s) {
if (wuffs_base__rect_ie_u32__is_empty(r)) {
return s;
}
if (wuffs_base__rect_ie_u32__is_empty(s)) {
return r;
}
r.min_inclusive_x =
wuffs_base__u32__min(r.min_inclusive_x, s.min_inclusive_x);
r.min_inclusive_y =
wuffs_base__u32__min(r.min_inclusive_y, s.min_inclusive_y);
r.max_exclusive_x =
wuffs_base__u32__max(r.max_exclusive_x, s.max_exclusive_x);
r.max_exclusive_y =
wuffs_base__u32__max(r.max_exclusive_y, s.max_exclusive_y);
return r;
}
static inline uint32_t wuffs_base__rect_ie_u32__width(
wuffs_base__rect_ie_u32 r) {
return wuffs_base__u32__sat_sub(r.max_exclusive_x, r.min_inclusive_x);
}
static inline uint32_t wuffs_base__rect_ie_u32__height(
wuffs_base__rect_ie_u32 r) {
return wuffs_base__u32__sat_sub(r.max_exclusive_y, r.min_inclusive_y);
}
// ---------------- I/O
// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length), plus
// additional indexes into that buffer, plus an opened / closed flag.
//
// A value with all fields NULL or zero is a valid, empty buffer.
typedef struct {
uint8_t* ptr; // Pointer.
size_t len; // Length.
size_t wi; // Write index. Invariant: wi <= len.
size_t ri; // Read index. Invariant: ri <= wi.
bool closed; // No further writes are expected.
} wuffs_base__io_buffer;
typedef struct {
// Do not access the private_impl's fields directly. There is no API/ABI
// compatibility or safety guarantee if you do so.
struct {
wuffs_base__io_buffer* buf;
// The bounds values are typically NULL, when created by the Wuffs public
// API. NULL means that the callee substitutes the implicit bounds derived
// from buf.
uint8_t* bounds[2];
} private_impl;
} wuffs_base__io_reader;
typedef struct {
// Do not access the private_impl's fields directly. There is no API/ABI
// compatibility or safety guarantee if you do so.
struct {
wuffs_base__io_buffer* buf;
// The bounds values are typically NULL, when created by the Wuffs public
// API. NULL means that the callee substitutes the implicit bounds derived
// from buf.
uint8_t* bounds[2];
} private_impl;
} wuffs_base__io_writer;
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
ret.private_impl.buf = buf;
return ret;
}
static inline wuffs_base__io_writer wuffs_base__io_buffer__writer(
wuffs_base__io_buffer* buf) {
wuffs_base__io_writer ret = ((wuffs_base__io_writer){});
ret.private_impl.buf = buf;
return ret;
}
// ---------------- Images
// wuffs_base__pixel_format encodes the format of the bytes that constitute an
// image frame's pixel data. Its bits:
// - bit 31 is reserved.
// - bits 30 .. 28 encodes color (and channel order, in terms of memory).
// - bits 27 .. 26 are reserved.
// - bits 25 .. 24 encodes transparency.
// - bit 23 indicates big-endian/MSB-first (as opposed to little/LSB).
// - bit 22 indicates floating point (as opposed to integer).
// - bits 21 .. 20 are the number of planes, minus 1. Zero means packed.
// - bits 19 .. 16 encodes the number of bits (depth) in an index value.
// Zero means direct, not palette-indexed.
// - bits 15 .. 12 encodes the number of bits (depth) in the 3rd channel.
// - bits 11 .. 8 encodes the number of bits (depth) in the 2nd channel.
// - bits 7 .. 4 encodes the number of bits (depth) in the 1st channel.
// - bits 3 .. 0 encodes the number of bits (depth) in the 0th channel.
//
// The bit fields of a wuffs_base__pixel_format are not independent. For
// example, the number of planes should not be greater than the number of
// channels. Similarly, bits 15..4 are unused (and should be zero) if bits
// 31..24 (color and transparency) together imply only 1 channel (gray, no
// alpha) and floating point samples should mean a bit depth of 16, 32 or 64.
//
// Formats hold between 1 and 4 channels. For example: Y (1 channel: gray), YA
// (2 channels: gray and alpha), BGR (3 channels: blue, green, red) or CMYK (4
// channels: cyan, magenta, yellow, black).
//
// For direct formats with N > 1 channels, those channels can be laid out in
// either 1 (packed) or N (planar) planes. For example, RGBA data is usually
// packed, but YUV data is usually planar, due to chroma subsampling (for
// details, see the wuffs_base__pixel_subsampling type). For indexed formats,
// the palette (always 256 × 4 bytes) holds up to 4 packed bytes of color data
// per index value, and there is only 1 plane (for the index). The distance
// between successive palette elements is always 4 bytes.
//
// The color field is encoded in 3 bits:
// - 0 means A (Alpha).
// - 1 means Y or YA (Gray, Alpha).
// - 2 means BGR, BGRX or BGRA (Blue, Green, Red, X-padding or Alpha).
// - 3 means RGB, RGBX or RGBA (Red, Green, Blue, X-padding or Alpha).
// - 4 means YUV or YUVA (Luma, Chroma-blue, Chroma-red, Alpha).
// - 5 means CMY or CMYK (Cyan, Magenta, Yellow, Black).
// - all other values are reserved.
//
// In Wuffs, channels are given in memory order, regardless of endianness,
// since the C type for the pixel data is an array of bytes, not an array of
// uint32_t. For example, packed BGRA with 8 bits per channel means that the
// bytes in memory are always Blue, Green, Red then Alpha. On big-endian
// systems, that is the uint32_t 0xBBGGRRAA. On little-endian, 0xAARRGGBB.
//
// When the color field (3 bits) encodes multiple options, the transparency
// field (2 bits) distinguishes them:
// - 0 means fully opaque, no extra channels
// - 1 means fully opaque, one extra channel (X or K, padding or black).
// - 2 means one extra alpha channel, other channels are non-premultiplied.
// - 3 means one extra alpha channel, other channels are premultiplied.
//
// The zero wuffs_base__pixel_format value is an invalid pixel format, as it is
// invalid to combine the zero color (alpha only) with the zero transparency.
//
// Bit depth is encoded in 4 bits:
// - 0 means the channel or index is unused.
// - x means a bit depth of x, for x in the range 1..8.
// - 9 means a bit depth of 10.
// - 10 means a bit depth of 12.
// - 11 means a bit depth of 16.
// - 12 means a bit depth of 24.
// - 13 means a bit depth of 32.
// - 14 means a bit depth of 48.
// - 15 means a bit depth of 64.
//
// For example, wuffs_base__pixel_format 0x3280BBBB is a natural format for
// decoding a PNG image - network byte order (also known as big-endian),
// packed, non-premultiplied alpha - that happens to be 16-bit-depth truecolor
// with alpha (RGBA). In memory order:
//
// ptr+0 ptr+1 ptr+2 ptr+3 ptr+4 ptr+5 ptr+6 ptr+7
// Rhi Rlo Ghi Glo Bhi Blo Ahi Alo
//
// For example, the value wuffs_base__pixel_format 0x20000565 means BGR with no
// alpha or padding, 5/6/5 bits for blue/green/red, packed 2 bytes per pixel,
// laid out LSB-first in memory order:
//
// ptr+0........... ptr+1...........
// MSB LSB MSB LSB
// G₂G₁G₀B₄B₃B₂B₁B₀ R₄R₃R₂R₁R₀G₅G₄G₃
//
// On little-endian systems (but not big-endian), this Wuffs pixel format value
// (0x20000565) corresponds to the Cairo library's CAIRO_FORMAT_RGB16_565, the
// SDL2 (Simple DirectMedia Layer 2) library's SDL_PIXELFORMAT_RGB565 and the
// Skia library's kRGB_565_SkColorType. Note BGR in Wuffs versus RGB in the
// other libraries.
//
// Regardless of endianness, this Wuffs pixel format value (0x20000565)
// corresponds to the V4L2 (Video For Linux 2) library's V4L2_PIX_FMT_RGB565
// and the Wayland-DRM library's WL_DRM_FORMAT_RGB565.
//
// Different software libraries name their pixel formats (and especially their
// channel order) either according to memory layout or as bits of a native
// integer type like uint32_t. The two conventions differ because of a system's
// endianness. As mentioned earlier, Wuffs pixel formats are always in memory
// order. More detail of other software libraries' naming conventions is in the
// Pixel Format Guide at https://afrantzis.github.io/pixel-format-guide/
//
// Do not manipulate these bits directly; they are private implementation
// details. Use methods such as wuffs_base__pixel_format__num_planes instead.
typedef uint32_t wuffs_base__pixel_format;
// 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 ((wuffs_base__pixel_format)0x00000000)
#define WUFFS_BASE__PIXEL_FORMAT__A ((wuffs_base__pixel_format)0x02000008)
#define WUFFS_BASE__PIXEL_FORMAT__Y ((wuffs_base__pixel_format)0x10000008)
#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL \
((wuffs_base__pixel_format)0x12000008)
#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL \
((wuffs_base__pixel_format)0x13000008)
#define WUFFS_BASE__PIXEL_FORMAT__BGR ((wuffs_base__pixel_format)0x20000888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRX ((wuffs_base__pixel_format)0x21008888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRX_INDEXED \
((wuffs_base__pixel_format)0x21088888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL \
((wuffs_base__pixel_format)0x22008888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_INDEXED \
((wuffs_base__pixel_format)0x22088888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL \
((wuffs_base__pixel_format)0x23008888)
#define WUFFS_BASE__PIXEL_FORMAT__RGB ((wuffs_base__pixel_format)0x30000888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBX ((wuffs_base__pixel_format)0x31008888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBX_INDEXED \
((wuffs_base__pixel_format)0x31088888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL \
((wuffs_base__pixel_format)0x32008888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_INDEXED \
((wuffs_base__pixel_format)0x32088888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL \
((wuffs_base__pixel_format)0x33008888)
#define WUFFS_BASE__PIXEL_FORMAT__YUV ((wuffs_base__pixel_format)0x40200888)
#define WUFFS_BASE__PIXEL_FORMAT__YUVK ((wuffs_base__pixel_format)0x41308888)
#define WUFFS_BASE__PIXEL_FORMAT__YUVA_NONPREMUL \
((wuffs_base__pixel_format)0x42308888)
#define WUFFS_BASE__PIXEL_FORMAT__CMY ((wuffs_base__pixel_format)0x50200888)
#define WUFFS_BASE__PIXEL_FORMAT__CMYK ((wuffs_base__pixel_format)0x51308888)
static inline bool wuffs_base__pixel_format__is_valid(
wuffs_base__pixel_format f) {
return f != 0;
}
static inline bool wuffs_base__pixel_format__is_indexed(
wuffs_base__pixel_format f) {
return ((f >> 16) & 0x0F) != 0;
}
#define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4
static inline uint32_t wuffs_base__pixel_format__num_planes(
wuffs_base__pixel_format f) {
return f ? (((f >> 20) & 0x03) + 1) : 0;
}
typedef struct {
wuffs_base__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];
} wuffs_base__pixel_buffer;
// --------
// wuffs_base__pixel_subsampling encodes the mapping of pixel space coordinates
// (x, y) to pixel buffer indices (i, j). That mapping can differ for each
// plane p. For a depth of 8 bits (1 byte), the p'th plane's sample starts at
// (planes[p].ptr + (j * planes[p].stride) + i).
//
// For packed pixel formats, the mapping is trivial: i = x and j = y. For
// planar pixel formats, the mapping can differ due to chroma subsampling. For
// example, consider a three plane YUV pixel format with 4:2:2 subsampling. For
// the luma (Y) channel, there is one sample for every pixel, but for the
// chroma (U, V) channels, there is one sample for every two pixels: pairs of
// horizontally adjacent pixels form one macropixel, i = x / 2 and j == y. In
// general, for a given p:
// - i = (x + bias_x) >> shift_x.
// - j = (y + bias_y) >> shift_y.
// where biases and shifts are in the range 0..3 and 0..2 respectively.
//
// In general, the biases will be zero after decoding an image. However, making
// a sub-image may change the bias, since the (x, y) coordinates are relative
// to the sub-image's top-left origin, but the backing pixel buffers were
// created relative to the original image's origin.
//
// For each plane p, each of those four numbers (biases and shifts) are encoded
// in two bits, which combine to form an 8 bit unsigned integer:
//
// e_p = (bias_x << 6) | (shift_x << 4) | (bias_y << 2) | (shift_y << 0)
//
// Those e_p values (e_0 for the first plane, e_1 for the second plane, etc)
// combine to form a wuffs_base__pixel_subsampling value:
//
// pixsub = (e_3 << 24) | (e_2 << 16) | (e_1 << 8) | (e_0 << 0)
//
// Do not manipulate these bits directly; they are private implementation
// details. Use methods such as wuffs_base__pixel_subsampling__bias_x instead.
typedef uint32_t wuffs_base__pixel_subsampling;
#define WUFFS_BASE__PIXEL_SUBSAMPLING__NONE ((wuffs_base__pixel_subsampling)0)
#define WUFFS_BASE__PIXEL_SUBSAMPLING__444 \
((wuffs_base__pixel_subsampling)0x000000)
#define WUFFS_BASE__PIXEL_SUBSAMPLING__440 \
((wuffs_base__pixel_subsampling)0x010100)
#define WUFFS_BASE__PIXEL_SUBSAMPLING__422 \
((wuffs_base__pixel_subsampling)0x101000)
#define WUFFS_BASE__PIXEL_SUBSAMPLING__420 \
((wuffs_base__pixel_subsampling)0x111100)
#define WUFFS_BASE__PIXEL_SUBSAMPLING__411 \
((wuffs_base__pixel_subsampling)0x202000)
#define WUFFS_BASE__PIXEL_SUBSAMPLING__410 \
((wuffs_base__pixel_subsampling)0x212100)
static inline uint32_t wuffs_base__pixel_subsampling__bias_x(
wuffs_base__pixel_subsampling s,
uint32_t plane) {
uint32_t shift = ((plane & 0x03) * 8) + 6;
return (s >> shift) & 0x03;
}
static inline uint32_t wuffs_base__pixel_subsampling__shift_x(
wuffs_base__pixel_subsampling s,
uint32_t plane) {
uint32_t shift = ((plane & 0x03) * 8) + 4;
return (s >> shift) & 0x03;
}
static inline uint32_t wuffs_base__pixel_subsampling__bias_y(
wuffs_base__pixel_subsampling s,
uint32_t plane) {
uint32_t shift = ((plane & 0x03) * 8) + 2;
return (s >> shift) & 0x03;
}
static inline uint32_t wuffs_base__pixel_subsampling__shift_y(
wuffs_base__pixel_subsampling s,
uint32_t plane) {
uint32_t shift = ((plane & 0x03) * 8) + 0;
return (s >> shift) & 0x03;
}
// --------
typedef struct {
// Do not access the private_impl's fields directly. There is no API/ABI
// compatibility or safety guarantee if you do so.
struct {
wuffs_base__pixel_format pixfmt;
wuffs_base__pixel_subsampling pixsub;
uint32_t width;
uint32_t height;
uint32_t num_loops;
} private_impl;
} wuffs_base__image_config;
// TODO: Should this function return bool? An error type?
static inline void wuffs_base__image_config__initialize(
wuffs_base__image_config* c,
wuffs_base__pixel_format pixfmt,
wuffs_base__pixel_subsampling pixsub,
uint32_t width,
uint32_t height,
uint32_t num_loops) {
if (!c) {
return;
}
if (pixfmt) {
uint64_t wh = ((uint64_t)width) * ((uint64_t)height);
// TODO: handle things other than 1 byte per pixel.
if (wh <= ((uint64_t)SIZE_MAX)) {
c->private_impl.pixfmt = pixfmt;
c->private_impl.pixsub = pixsub;
c->private_impl.width = width;
c->private_impl.height = height;
c->private_impl.num_loops = num_loops;
return;
}
}
*c = ((wuffs_base__image_config){});
}
static inline void wuffs_base__image_config__invalidate(
wuffs_base__image_config* c) {
if (c) {
*c = ((wuffs_base__image_config){});
}
}
static inline bool wuffs_base__image_config__is_valid(
wuffs_base__image_config* c) {
return c && c->private_impl.pixfmt;
}
static inline wuffs_base__pixel_format wuffs_base__image_config__pixel_format(
wuffs_base__image_config* c) {
return c ? c->private_impl.pixfmt : 0;
}
static inline wuffs_base__pixel_subsampling
wuffs_base__image_config__pixel_subsampling(wuffs_base__image_config* c) {
return c ? c->private_impl.pixsub : 0;
}
static inline uint32_t wuffs_base__image_config__width(
wuffs_base__image_config* c) {
return c ? c->private_impl.width : 0;
}
static inline uint32_t wuffs_base__image_config__height(
wuffs_base__image_config* c) {
return c ? c->private_impl.height : 0;
}
static inline uint32_t wuffs_base__image_config__num_loops(
wuffs_base__image_config* c) {
return c ? c->private_impl.num_loops : 0;
}
// TODO: this is the right API for planar (not packed) pixbufs? Should it allow
// decoding into a color model different from the format's intrinsic one? For
// example, decoding a JPEG image straight to RGBA instead of to YCbCr?
static inline size_t wuffs_base__image_config__pixbuf_size(
wuffs_base__image_config* c) {
if (c) {
uint64_t wh =
((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);
// TODO: handle things other than 1 byte per pixel.
return (size_t)wh;
}
return 0;
}
// --------
typedef struct {
// Do not access the private_impl's fields directly. There is no API/ABI
// compatibility or safety guarantee if you do so.
struct {
wuffs_base__image_config config;
uint32_t loop_count; // 0-based count of the current loop.
wuffs_base__pixel_buffer pixbuf;
// TODO: color spaces.
wuffs_base__rect_ie_u32 dirty_rect;
wuffs_base__flicks duration;
bool palette_changed;
uint8_t palette[1024];
} private_impl;
} wuffs_base__image_buffer;
static inline void wuffs_base__image_buffer__set_from_pixbuf(
wuffs_base__image_buffer* b,
wuffs_base__image_config config,
wuffs_base__pixel_buffer pixbuf) {
if (!b) {
return;
}
*b = ((wuffs_base__image_buffer){});
b->private_impl.config = config;
b->private_impl.pixbuf = pixbuf;
}
// TODO: Should this function return bool? An error type?
static inline void wuffs_base__image_buffer__set_from_slice(
wuffs_base__image_buffer* b,
wuffs_base__image_config config,
wuffs_base__slice_u8 pixbuf_memory) {
if (!b) {
return;
}
*b = ((wuffs_base__image_buffer){});
// TODO: don't assume 1 byte per pixel. Don't assume packed.
uint64_t wh = ((uint64_t)config.private_impl.width) *
((uint64_t)config.private_impl.height);
if (wh > pixbuf_memory.len) {
return;
}
b->private_impl.config = config;
wuffs_base__table_u8* tab = &b->private_impl.pixbuf.planes[0];
tab->ptr = pixbuf_memory.ptr;
tab->width = config.private_impl.width;
tab->height = config.private_impl.height;
tab->stride = config.private_impl.width;
}
// The palette argument is ignored unless its length is exactly 1024.
static inline void wuffs_base__image_buffer__update(
wuffs_base__image_buffer* b,
wuffs_base__rect_ie_u32 dirty_rect,
wuffs_base__flicks duration,
wuffs_base__slice_u8 palette) {
if (!b) {
return;
}
// Clip the dirty_rect to the image bounds.
dirty_rect.max_exclusive_x = wuffs_base__u32__min(
dirty_rect.max_exclusive_x, b->private_impl.config.private_impl.width);
dirty_rect.max_exclusive_y = wuffs_base__u32__min(
dirty_rect.max_exclusive_y, b->private_impl.config.private_impl.height);
b->private_impl.dirty_rect = dirty_rect;
b->private_impl.duration = duration;
b->private_impl.palette_changed = palette.ptr && (palette.len == 1024);
if (b->private_impl.palette_changed) {
memmove(b->private_impl.palette, palette.ptr, 1024);
}
}
// wuffs_base__image_buffer__loop returns whether the image decoder should loop
// back to the beginning of the animation, assuming that we've reached the end
// of the encoded stream. If so, it increments b's count of the animation loops
// played so far.
static inline bool wuffs_base__image_buffer__loop(wuffs_base__image_buffer* b) {
if (!b) {
return false;
}
uint32_t n = b->private_impl.config.private_impl.num_loops;
if (n == 0) {
return true;
}
if (b->private_impl.loop_count < n - 1) {
b->private_impl.loop_count++;
return true;
}
return false;
}
static inline wuffs_base__image_config* wuffs_base__image_buffer__image_config(
wuffs_base__image_buffer* b) {
return b ? &b->private_impl.config : NULL;
}
// wuffs_base__image_buffer__palette_changed returns whether this frame's
// palette differs from the previous frame. It is conservative and may return
// false positives (but never false negatives).
static inline bool wuffs_base__image_buffer__palette_changed(
wuffs_base__image_buffer* b) {
return b && b->private_impl.palette_changed;
}
// wuffs_base__image_buffer__dirty_rect returns an upper bound for what part of
// this frame's pixels differs from the previous frame.
static inline wuffs_base__rect_ie_u32 wuffs_base__image_buffer__dirty_rect(
wuffs_base__image_buffer* b) {
return b ? b->private_impl.dirty_rect : ((wuffs_base__rect_ie_u32){0});
}
// wuffs_base__image_buffer__duration returns the amount of time to display
// this frame. Zero means to display forever - a still (non-animated) image.
static inline wuffs_base__flicks wuffs_base__image_buffer__duration(
wuffs_base__image_buffer* b) {
return b ? b->private_impl.duration : 0;
}
// wuffs_base__image_buffer__palette returns the palette that the pixel data
// can index. The backing array is inside b and has length 1024.
static inline wuffs_base__slice_u8 wuffs_base__image_buffer__palette(
wuffs_base__image_buffer* b) {
return b ? ((wuffs_base__slice_u8){.ptr = b->private_impl.palette,
.len = 1024})
: ((wuffs_base__slice_u8){});
}
static inline wuffs_base__table_u8 wuffs_base__image_buffer__plane(
wuffs_base__image_buffer* b,
uint32_t p) {
return (b && (p < WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX))
? b->private_impl.pixbuf.planes[p]
: ((wuffs_base__table_u8){});
}
#endif // WUFFS_BASE_HEADER_H
// ---------------- Use Declarations
#ifdef __cplusplus
extern "C" {
#endif
// ---------------- Status Codes
// Status codes are int32_t values. Its bits:
// - bit 31 (the sign bit) indicates unrecoverable-ness: an error.
// - bits 30 .. 10 are the packageid: a namespace.
// - bits 9 .. 8 are reserved.
// - bits 7 .. 0 are a package-namespaced numeric code.
//
// Do not manipulate these bits directly; they are private implementation
// details. Use methods such as wuffs_deflate__status__is_error instead.
typedef int32_t wuffs_deflate__status;
#define wuffs_deflate__packageid 848533 // 0x000CF295
#define WUFFS_DEFLATE__STATUS_OK 0 // 0x00000000
#define WUFFS_DEFLATE__ERROR_BAD_WUFFS_VERSION -2147483647 // 0x80000001
#define WUFFS_DEFLATE__ERROR_BAD_SIZEOF_RECEIVER -2147483646 // 0x80000002
#define WUFFS_DEFLATE__ERROR_BAD_RECEIVER -2147483645 // 0x80000003
#define WUFFS_DEFLATE__ERROR_BAD_ARGUMENT -2147483644 // 0x80000004
#define WUFFS_DEFLATE__ERROR_CHECK_WUFFS_VERSION_NOT_CALLED \
-2147483643 // 0x80000005
#define WUFFS_DEFLATE__ERROR_CHECK_WUFFS_VERSION_CALLED_TWICE \
-2147483642 // 0x80000006
#define WUFFS_DEFLATE__ERROR_INVALID_I_O_OPERATION -2147483641 // 0x80000007
#define WUFFS_DEFLATE__ERROR_CLOSED_FOR_WRITES -2147483640 // 0x80000008
#define WUFFS_DEFLATE__ERROR_UNEXPECTED_EOF -2147483639 // 0x80000009
#define WUFFS_DEFLATE__SUSPENSION_SHORT_READ 10 // 0x0000000A
#define WUFFS_DEFLATE__SUSPENSION_SHORT_WRITE 11 // 0x0000000B
#define WUFFS_DEFLATE__ERROR_CANNOT_RETURN_A_SUSPENSION \
-2147483636 // 0x8000000C
#define WUFFS_DEFLATE__ERROR_INVALID_CALL_SEQUENCE -2147483635 // 0x8000000D
#define WUFFS_DEFLATE__SUSPENSION_END_OF_DATA 14 // 0x0000000E
#define WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_OVER_SUBSCRIBED \
-1278585856 // 0xB3CA5400
#define WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_UNDER_SUBSCRIBED \
-1278585855 // 0xB3CA5401
#define WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_COUNT \
-1278585854 // 0xB3CA5402
#define WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_REPETITION \
-1278585853 // 0xB3CA5403
#define WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE -1278585852 // 0xB3CA5404
#define WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_MINIMUM_CODE_LENGTH \
-1278585851 // 0xB3CA5405
#define WUFFS_DEFLATE__ERROR_BAD_BLOCK -1278585850 // 0xB3CA5406
#define WUFFS_DEFLATE__ERROR_BAD_DISTANCE -1278585849 // 0xB3CA5407
#define WUFFS_DEFLATE__ERROR_BAD_DISTANCE_CODE_COUNT -1278585848 // 0xB3CA5408
#define WUFFS_DEFLATE__ERROR_BAD_LITERAL_LENGTH_CODE_COUNT \
-1278585847 // 0xB3CA5409
#define WUFFS_DEFLATE__ERROR_INCONSISTENT_STORED_BLOCK_LENGTH \
-1278585846 // 0xB3CA540A
#define WUFFS_DEFLATE__ERROR_MISSING_END_OF_BLOCK_CODE \
-1278585845 // 0xB3CA540B
#define WUFFS_DEFLATE__ERROR_NO_HUFFMAN_CODES -1278585844 // 0xB3CA540C
#define WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE \
-1278585843 // 0xB3CA540D
#define WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_END_OF_BLOCK \
-1278585842 // 0xB3CA540E
#define WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_DISTANCE \
-1278585841 // 0xB3CA540F
#define WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_N_BITS \
-1278585840 // 0xB3CA5410
bool wuffs_deflate__status__is_error(wuffs_deflate__status s);
const char* wuffs_deflate__status__string(wuffs_deflate__status s);
// ---------------- Public Consts
// ---------------- Structs
typedef struct {
// Do not access the private_impl's fields directly. There is no API/ABI
// compatibility or safety guarantee if you do so. Instead, use the
// wuffs_deflate__decoder__etc functions.
//
// In C++, these fields would be "private", but C does not support that.
//
// It is a struct, not a struct*, so that it can be stack allocated.
struct {
wuffs_deflate__status status;
uint32_t magic;
uint32_t f_bits;
uint32_t f_n_bits;
uint32_t f_huffs[2][1234];
uint32_t f_n_huffs_bits[2];
uint8_t f_history[32768];
uint32_t f_history_index;
uint8_t f_code_lengths[320];
bool f_end_of_block;
struct {
uint32_t coro_susp_point;
wuffs_deflate__status v_z;
uint64_t v_n_copied;
uint32_t v_already_full;
} c_decode[1];
struct {
uint32_t coro_susp_point;
uint32_t v_final;
uint32_t v_type;
} c_decode_blocks[1];
struct {
uint32_t coro_susp_point;
uint32_t v_length;
uint32_t v_n_copied;
uint64_t scratch;
} c_decode_uncompressed[1];
struct {
uint32_t coro_susp_point;
uint32_t v_i;
} c_init_fixed_huffman[1];
struct {
uint32_t coro_susp_point;
uint32_t v_bits;
uint32_t v_n_bits;
uint32_t v_n_lit;
uint32_t v_n_dist;
uint32_t v_n_clen;
uint32_t v_i;
uint32_t v_mask;
uint32_t v_table_entry;
uint32_t v_table_entry_n_bits;
uint32_t v_n_extra_bits;
uint8_t v_rep_symbol;
uint32_t v_rep_count;
} c_init_dynamic_huffman[1];
struct {
uint32_t coro_susp_point;
uint32_t v_bits;
uint32_t v_n_bits;
uint32_t v_table_entry;
uint32_t v_table_entry_n_bits;
uint32_t v_lmask;
uint32_t v_dmask;
uint32_t v_redir_top;
uint32_t v_redir_mask;
uint32_t v_length;
uint32_t v_dist_minus_1;
uint32_t v_n_copied;
uint32_t v_hlen;
uint32_t v_hdist;
} c_decode_huffman_slow[1];
} private_impl;
} wuffs_deflate__decoder;
// ---------------- Public Initializer Prototypes
// wuffs_deflate__decoder__check_wuffs_version is an initializer function.
//
// It should be called before any other wuffs_deflate__decoder__* function.
//
// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
void wuffs_deflate__decoder__check_wuffs_version(wuffs_deflate__decoder* self,
size_t sizeof_star_self,
uint32_t wuffs_version);
// ---------------- Public Function Prototypes
wuffs_deflate__status wuffs_deflate__decoder__decode(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WUFFS_DEFLATE_H
// C HEADER ENDS HERE.
#ifndef WUFFS_BASE_IMPL_H
#define WUFFS_BASE_IMPL_H
// Copyright 2017 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
static inline wuffs_base__empty_struct wuffs_base__return_empty_struct() {
return ((wuffs_base__empty_struct){});
}
#define WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(x) (void)(x)
// 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)
// Denote intentional fallthroughs for -Wimplicit-fallthrough.
//
// The order matters here. Clang also defines "__GNUC__".
#if defined(__clang__) && __cplusplus >= 201103L
#define WUFFS_BASE__FALLTHROUGH [[clang::fallthrough]]
#elif !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 7)
#define WUFFS_BASE__FALLTHROUGH __attribute__((fallthrough))
#else
#define WUFFS_BASE__FALLTHROUGH
#endif
// Use switch cases for coroutine suspension points, similar to the technique
// in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
//
// 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; \
WUFFS_BASE__FALLTHROUGH; \
case n:;
#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \
if (status < 0) { \
goto exit; \
} else if (status == 0) { \
goto ok; \
} \
coro_susp_point = n; \
goto suspend; \
case n:;
// Clang also defines "__GNUC__".
#if defined(__GNUC__)
#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
// Uncomment this #include for printf-debugging.
// #include <stdio.h>
// The helpers below are functions, instead of macros, because their arguments
// can be an expression that we shouldn't evaluate more than once.
//
// They are in base-impl.h and hence copy/pasted into every generated C file,
// instead of being in some "base.c" file, since a design goal is that users of
// the generated C code can often just #include a single .c file, such as
// "gif.c", without having to additionally include or otherwise build and link
// a "base.c" file.
//
// They are static, so that linking multiple wuffs .o files won't complain about
// duplicate function definitions.
//
// They are explicitly marked inline, even if modern compilers don't use the
// inline attribute to guide optimizations such as inlining, to avoid the
// -Wunused-function warning, and we like to compile with -Wall -Werror.
// ---------------- Numeric Types
static inline uint16_t wuffs_base__load_u16be(uint8_t* p) {
return ((uint16_t)(p[0]) << 8) | ((uint16_t)(p[1]) << 0);
}
static inline uint16_t wuffs_base__load_u16le(uint8_t* p) {
return ((uint16_t)(p[0]) << 0) | ((uint16_t)(p[1]) << 8);
}
static inline uint32_t wuffs_base__load_u24be(uint8_t* p) {
return ((uint32_t)(p[0]) << 16) | ((uint32_t)(p[1]) << 8) |
((uint32_t)(p[2]) << 0);
}
static inline uint32_t wuffs_base__load_u24le(uint8_t* p) {
return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
((uint32_t)(p[2]) << 16);
}
static inline uint32_t wuffs_base__load_u32be(uint8_t* p) {
return ((uint32_t)(p[0]) << 24) | ((uint32_t)(p[1]) << 16) |
((uint32_t)(p[2]) << 8) | ((uint32_t)(p[3]) << 0);
}
static inline uint32_t wuffs_base__load_u32le(uint8_t* p) {
return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24);
}
static inline uint64_t wuffs_base__load_u40be(uint8_t* p) {
return ((uint64_t)(p[0]) << 32) | ((uint64_t)(p[1]) << 24) |
((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 8) |
((uint64_t)(p[4]) << 0);
}
static inline uint64_t wuffs_base__load_u40le(uint8_t* p) {
return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
((uint64_t)(p[4]) << 32);
}
static inline uint64_t wuffs_base__load_u48be(uint8_t* p) {
return ((uint64_t)(p[0]) << 40) | ((uint64_t)(p[1]) << 32) |
((uint64_t)(p[2]) << 24) | ((uint64_t)(p[3]) << 16) |
((uint64_t)(p[4]) << 8) | ((uint64_t)(p[5]) << 0);
}
static inline uint64_t wuffs_base__load_u48le(uint8_t* p) {
return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40);
}
static inline uint64_t wuffs_base__load_u56be(uint8_t* p) {
return ((uint64_t)(p[0]) << 48) | ((uint64_t)(p[1]) << 40) |
((uint64_t)(p[2]) << 32) | ((uint64_t)(p[3]) << 24) |
((uint64_t)(p[4]) << 16) | ((uint64_t)(p[5]) << 8) |
((uint64_t)(p[6]) << 0);
}
static inline uint64_t wuffs_base__load_u56le(uint8_t* p) {
return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
((uint64_t)(p[6]) << 48);
}
static inline uint64_t wuffs_base__load_u64be(uint8_t* p) {
return ((uint64_t)(p[0]) << 56) | ((uint64_t)(p[1]) << 48) |
((uint64_t)(p[2]) << 40) | ((uint64_t)(p[3]) << 32) |
((uint64_t)(p[4]) << 24) | ((uint64_t)(p[5]) << 16) |
((uint64_t)(p[6]) << 8) | ((uint64_t)(p[7]) << 0);
}
static inline uint64_t wuffs_base__load_u64le(uint8_t* p) {
return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56);
}
// --------
static inline void wuffs_base__u8__sat_add_indirect(uint8_t* x, uint8_t y) {
*x = wuffs_base__u8__sat_add(*x, y);
}
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 void wuffs_base__u16__sat_add_indirect(uint16_t* x, uint16_t y) {
*x = wuffs_base__u16__sat_add(*x, y);
}
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 void wuffs_base__u32__sat_add_indirect(uint32_t* x, uint32_t y) {
*x = wuffs_base__u32__sat_add(*x, y);
}
static inline void wuffs_base__u32__sat_sub_indirect(uint32_t* x, uint32_t y) {
*x = wuffs_base__u32__sat_sub(*x, y);
}
static inline void wuffs_base__u64__sat_add_indirect(uint64_t* x, uint64_t y) {
*x = wuffs_base__u64__sat_add(*x, y);
}
static inline void wuffs_base__u64__sat_sub_indirect(uint64_t* x, uint64_t y) {
*x = wuffs_base__u64__sat_sub(*x, y);
}
// ---------------- Slices and Tables
static inline wuffs_base__slice_u8 wuffs_base__slice_u8__subslice_i(
wuffs_base__slice_u8 s,
uint64_t i) {
if ((i <= SIZE_MAX) && (i <= s.len)) {
return ((wuffs_base__slice_u8){
.ptr = s.ptr + i,
.len = s.len - i,
});
}
return ((wuffs_base__slice_u8){});
}
static inline wuffs_base__slice_u8 wuffs_base__slice_u8__subslice_j(
wuffs_base__slice_u8 s,
uint64_t j) {
if ((j <= SIZE_MAX) && (j <= s.len)) {
return ((wuffs_base__slice_u8){.ptr = s.ptr, .len = j});
}
return ((wuffs_base__slice_u8){});
}
static inline wuffs_base__slice_u8 wuffs_base__slice_u8__subslice_ij(
wuffs_base__slice_u8 s,
uint64_t i,
uint64_t j) {
if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) {
return ((wuffs_base__slice_u8){
.ptr = s.ptr + i,
.len = j - i,
});
}
return ((wuffs_base__slice_u8){});
}
// 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 = up_to;
}
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 = up_to;
}
return s;
}
// wuffs_base__slice_u8__copy_from_slice calls memmove(dst.ptr, src.ptr,
// length) where length 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 length = dst.len < src.len ? dst.len : src.len;
if (length > 0) {
memmove(dst.ptr, src.ptr, length);
}
return length;
}
// --------
static inline wuffs_base__slice_u8 wuffs_base__table_u8__row(
wuffs_base__table_u8 t,
uint32_t y) {
if (y < t.height) {
return ((wuffs_base__slice_u8){
.ptr = t.ptr + (t.stride * y),
.len = t.width,
});
}
return ((wuffs_base__slice_u8){});
}
// ---------------- Ranges and Rects
static inline wuffs_base__empty_struct
wuffs_base__rect_ii_u32__set_min_inclusive_x(wuffs_base__rect_ii_u32* r,
uint32_t x) {
r->min_inclusive_x = x;
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct
wuffs_base__rect_ii_u32__set_min_inclusive_y(wuffs_base__rect_ii_u32* r,
uint32_t y) {
r->min_inclusive_y = y;
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct
wuffs_base__rect_ii_u32__set_max_inclusive_x(wuffs_base__rect_ii_u32* r,
uint32_t x) {
r->max_inclusive_x = x;
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct
wuffs_base__rect_ii_u32__set_max_inclusive_y(wuffs_base__rect_ii_u32* r,
uint32_t y) {
r->max_inclusive_y = y;
return ((wuffs_base__empty_struct){});
}
// --------
static inline wuffs_base__empty_struct
wuffs_base__rect_ie_u32__set_min_inclusive_x(wuffs_base__rect_ie_u32* r,
uint32_t x) {
r->min_inclusive_x = x;
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct
wuffs_base__rect_ie_u32__set_min_inclusive_y(wuffs_base__rect_ie_u32* r,
uint32_t y) {
r->min_inclusive_y = y;
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct
wuffs_base__rect_ie_u32__set_max_exclusive_x(wuffs_base__rect_ie_u32* r,
uint32_t x) {
r->max_exclusive_x = x;
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct
wuffs_base__rect_ie_u32__set_max_exclusive_y(wuffs_base__rect_ie_u32* r,
uint32_t y) {
r->max_exclusive_y = y;
return ((wuffs_base__empty_struct){});
}
// ---------------- I/O
static inline bool wuffs_base__io_buffer__is_valid(wuffs_base__io_buffer buf) {
return (buf.ptr || (buf.len == 0)) && (buf.len >= buf.wi) &&
(buf.wi >= buf.ri);
}
static inline bool wuffs_base__io_reader__is_eof(wuffs_base__io_reader o) {
wuffs_base__io_buffer* buf = o.private_impl.buf;
return buf && buf->closed && (buf->ptr + buf->wi == o.private_impl.bounds[1]);
}
static inline bool wuffs_base__io_reader__is_valid(wuffs_base__io_reader o) {
wuffs_base__io_buffer* buf = o.private_impl.buf;
// Note: if making this function public (i.e. moving it to base-header.h), it
// also needs to allow NULL (i.e. implicit, callee-calculated) bounds.
return buf ? ((buf->ptr <= o.private_impl.bounds[0]) &&
(o.private_impl.bounds[0] <= o.private_impl.bounds[1]) &&
(o.private_impl.bounds[1] <= buf->ptr + buf->len))
: ((o.private_impl.bounds[0] == NULL) &&
(o.private_impl.bounds[1] == NULL));
}
static inline bool wuffs_base__io_writer__is_valid(wuffs_base__io_writer o) {
wuffs_base__io_buffer* buf = o.private_impl.buf;
// Note: if making this function public (i.e. moving it to base-header.h), it
// also needs to allow NULL (i.e. implicit, callee-calculated) bounds.
return buf ? ((buf->ptr <= o.private_impl.bounds[0]) &&
(o.private_impl.bounds[0] <= o.private_impl.bounds[1]) &&
(o.private_impl.bounds[1] <= buf->ptr + buf->len))
: ((o.private_impl.bounds[0] == NULL) &&
(o.private_impl.bounds[1] == NULL));
}
static inline uint32_t wuffs_base__io_writer__copy_from_history32(
uint8_t** ptr_ptr,
uint8_t* start,
uint8_t* end,
uint32_t distance,
uint32_t length) {
if (!distance) {
return 0;
}
uint8_t* ptr = *ptr_ptr;
if ((size_t)(ptr - start) < (size_t)(distance)) {
return 0;
}
start = ptr - distance;
size_t n = end - ptr;
if ((size_t)(length) > n) {
length = n;
} else {
n = 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
// copy_from_history32 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__copy_from_history32__bco below.
//
// Alternatively, or additionally, have a sloppy_copy_from_history32 method
// that copies 8 bytes at a time, possibly writing more than length bytes?
for (; n >= 3; n -= 3) {
*ptr++ = *start++;
*ptr++ = *start++;
*ptr++ = *start++;
}
for (; n; n--) {
*ptr++ = *start++;
}
*ptr_ptr = ptr;
return length;
}
// wuffs_base__io_writer__copy_from_history32__bco is a Bounds Check Optimized
// version of the wuffs_base__io_writer__copy_from_history32 function above.
// The caller needs to prove that:
// - distance > 0
// - distance <= (*ptr_ptr - start)
// - length <= (end - *ptr_ptr)
static inline uint32_t wuffs_base__io_writer__copy_from_history32__bco(
uint8_t** ptr_ptr,
uint8_t* start,
uint8_t* end,
uint32_t distance,
uint32_t length) {
uint8_t* ptr = *ptr_ptr;
start = ptr - distance;
uint32_t n = length;
for (; n >= 3; n -= 3) {
*ptr++ = *start++;
*ptr++ = *start++;
*ptr++ = *start++;
}
for (; n; n--) {
*ptr++ = *start++;
}
*ptr_ptr = ptr;
return length;
}
static inline uint32_t wuffs_base__io_writer__copy_from_reader32(
uint8_t** ptr_ioptr_w,
uint8_t* iobounds1_w,
uint8_t** ptr_ioptr_r,
uint8_t* iobounds1_r,
uint32_t length) {
uint8_t* ioptr_w = *ptr_ioptr_w;
size_t n = length;
if (n > iobounds1_w - ioptr_w) {
n = iobounds1_w - ioptr_w;
}
uint8_t* ioptr_r = *ptr_ioptr_r;
if (n > iobounds1_r - ioptr_r) {
n = iobounds1_r - ioptr_r;
}
if (n > 0) {
memmove(ioptr_w, ioptr_r, n);
*ptr_ioptr_w += n;
*ptr_ioptr_r += n;
}
return n;
}
static inline uint64_t wuffs_base__io_writer__copy_from_slice(
uint8_t** ptr_ioptr_w,
uint8_t* iobounds1_w,
wuffs_base__slice_u8 src) {
uint8_t* ioptr_w = *ptr_ioptr_w;
size_t n = src.len;
if (n > iobounds1_w - ioptr_w) {
n = iobounds1_w - ioptr_w;
}
if (n > 0) {
memmove(ioptr_w, src.ptr, n);
*ptr_ioptr_w += n;
}
return n;
}
static inline uint32_t wuffs_base__io_writer__copy_from_slice32(
uint8_t** ptr_ioptr_w,
uint8_t* iobounds1_w,
wuffs_base__slice_u8 src,
uint32_t length) {
uint8_t* ioptr_w = *ptr_ioptr_w;
size_t n = src.len;
if (n > length) {
n = length;
}
if (n > iobounds1_w - ioptr_w) {
n = iobounds1_w - ioptr_w;
}
if (n > 0) {
memmove(ioptr_w, src.ptr, n);
*ptr_ioptr_w += n;
}
return n;
}
static inline wuffs_base__empty_struct wuffs_base__io_reader__set_limit(
wuffs_base__io_reader* o,
uint8_t* ioptr_r,
uint64_t limit) {
if (o && ((o->private_impl.bounds[1] - ioptr_r) > limit)) {
o->private_impl.bounds[1] = ioptr_r + limit;
}
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct wuffs_base__io_reader__set_mark(
wuffs_base__io_reader* o,
uint8_t* mark) {
o->private_impl.bounds[0] = mark;
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct wuffs_base__io_writer__set(
wuffs_base__io_writer* o,
wuffs_base__io_buffer* b,
uint8_t** ioptr1_ptr,
uint8_t** ioptr2_ptr,
wuffs_base__slice_u8 s) {
b->ptr = s.ptr;
b->len = s.len;
b->wi = 0;
b->ri = 0;
b->closed = false;
o->private_impl.buf = b;
o->private_impl.bounds[0] = s.ptr;
o->private_impl.bounds[1] = s.ptr + s.len;
*ioptr1_ptr = s.ptr;
*ioptr2_ptr = s.ptr + s.len;
return ((wuffs_base__empty_struct){});
}
static inline wuffs_base__empty_struct wuffs_base__io_writer__set_mark(
wuffs_base__io_writer* o,
uint8_t* mark) {
o->private_impl.bounds[0] = mark;
return ((wuffs_base__empty_struct){});
}
static const char* wuffs_base__status__strings[15] = {
"ok",
"bad wuffs version",
"bad sizeof receiver",
"bad receiver",
"bad argument",
"check_wuffs_version not called",
"check_wuffs_version called twice",
"invalid I/O operation",
"closed for writes",
"unexpected EOF",
"short read",
"short write",
"cannot return a suspension",
"invalid call sequence",
"end of data",
};
#endif // WUFFS_BASE_IMPL_H
// ---------------- Status Codes Implementations
bool wuffs_deflate__status__is_error(wuffs_deflate__status s) {
return s < 0;
}
const char* wuffs_deflate__status__strings[17] = {
"deflate: bad Huffman code (over-subscribed)",
"deflate: bad Huffman code (under-subscribed)",
"deflate: bad Huffman code length count",
"deflate: bad Huffman code length repetition",
"deflate: bad Huffman code",
"deflate: bad Huffman minimum code length",
"deflate: bad block",
"deflate: bad distance",
"deflate: bad distance code count",
"deflate: bad literal/length code count",
"deflate: inconsistent stored block length",
"deflate: missing end-of-block code",
"deflate: no Huffman codes",
"deflate: internal error: inconsistent Huffman decoder state",
"deflate: internal error: inconsistent Huffman end_of_block",
"deflate: internal error: inconsistent distance",
"deflate: internal error: inconsistent n_bits",
};
const char* wuffs_deflate__status__string(wuffs_deflate__status s) {
const char** a = NULL;
uint32_t n = 0;
switch ((s >> 10) & 0x1FFFFF) {
case 0:
a = wuffs_base__status__strings;
n = 15;
break;
case wuffs_deflate__packageid:
a = wuffs_deflate__status__strings;
n = 17;
break;
}
uint32_t i = s & 0xFF;
return i < n ? a[i] : "unknown status";
}
// ---------------- Private Consts
static const uint8_t wuffs_deflate__code_order[19] = {
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] = {
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] = {
1073742592, 1073742848, 1073743104, 1073743360, 1073743616, 1073743872,
1073744128, 1073744384, 1073744656, 1073745168, 1073745680, 1073746192,
1073746720, 1073747744, 1073748768, 1073749792, 1073750832, 1073752880,
1073754928, 1073756976, 1073759040, 1073763136, 1073767232, 1073771328,
1073775440, 1073783632, 1073791824, 1073800016, 1073807872, 134217728,
134217728, 134217728,
};
static const uint32_t wuffs_deflate__dcode_magic_numbers[32] = {
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,
};
// ---------------- Private Initializer Prototypes
// ---------------- Private Function Prototypes
static wuffs_deflate__status wuffs_deflate__decoder__decode_blocks(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src);
static wuffs_deflate__status wuffs_deflate__decoder__decode_uncompressed(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src);
static wuffs_deflate__status wuffs_deflate__decoder__init_fixed_huffman(
wuffs_deflate__decoder* self);
static wuffs_deflate__status wuffs_deflate__decoder__init_dynamic_huffman(
wuffs_deflate__decoder* self,
wuffs_base__io_reader a_src);
static wuffs_deflate__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_deflate__status wuffs_deflate__decoder__decode_huffman_fast(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src);
static wuffs_deflate__status wuffs_deflate__decoder__decode_huffman_slow(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src);
// ---------------- Initializer Implementations
void wuffs_deflate__decoder__check_wuffs_version(wuffs_deflate__decoder* self,
size_t sizeof_star_self,
uint32_t wuffs_version) {
if (!self) {
return;
}
if (sizeof(*self) != sizeof_star_self) {
self->private_impl.status = WUFFS_DEFLATE__ERROR_BAD_SIZEOF_RECEIVER;
return;
}
if (wuffs_version != WUFFS_VERSION) {
self->private_impl.status = WUFFS_DEFLATE__ERROR_BAD_WUFFS_VERSION;
return;
}
if (self->private_impl.magic != 0) {
self->private_impl.status =
WUFFS_DEFLATE__ERROR_CHECK_WUFFS_VERSION_CALLED_TWICE;
return;
}
self->private_impl.magic = WUFFS_BASE__MAGIC;
}
// ---------------- Function Implementations
// -------- func decoder.decode
wuffs_deflate__status wuffs_deflate__decoder__decode(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src) {
if (!self) {
return WUFFS_DEFLATE__ERROR_BAD_RECEIVER;
}
if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
self->private_impl.status =
WUFFS_DEFLATE__ERROR_CHECK_WUFFS_VERSION_NOT_CALLED;
}
if (self->private_impl.status < 0) {
return self->private_impl.status;
}
wuffs_deflate__status status = WUFFS_DEFLATE__STATUS_OK;
wuffs_deflate__status v_z;
wuffs_base__slice_u8 v_written;
uint64_t v_n_copied;
uint32_t v_already_full;
uint8_t* ioptr_dst = NULL;
uint8_t* iobounds0orig_dst = NULL;
uint8_t* iobounds1_dst = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_dst);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_dst);
if (a_dst.private_impl.buf) {
ioptr_dst = a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->wi;
if (!a_dst.private_impl.bounds[0]) {
a_dst.private_impl.bounds[0] = ioptr_dst;
a_dst.private_impl.bounds[1] =
a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->len;
}
if (a_dst.private_impl.buf->closed) {
a_dst.private_impl.bounds[1] = ioptr_dst;
}
iobounds0orig_dst = a_dst.private_impl.bounds[0];
iobounds1_dst = a_dst.private_impl.bounds[1];
}
uint32_t coro_susp_point = self->private_impl.c_decode[0].coro_susp_point;
if (coro_susp_point) {
v_z = self->private_impl.c_decode[0].v_z;
v_written = ((wuffs_base__slice_u8){});
v_n_copied = self->private_impl.c_decode[0].v_n_copied;
v_already_full = self->private_impl.c_decode[0].v_already_full;
} else {
v_written = ((wuffs_base__slice_u8){});
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
while (true) {
wuffs_base__io_writer__set_mark(&a_dst, ioptr_dst);
{
if (a_dst.private_impl.buf) {
a_dst.private_impl.buf->wi = ioptr_dst - a_dst.private_impl.buf->ptr;
}
wuffs_deflate__status t_0 =
wuffs_deflate__decoder__decode_blocks(self, a_dst, a_src);
if (a_dst.private_impl.buf) {
ioptr_dst = a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->wi;
}
v_z = t_0;
}
if (!(v_z > 0)) {
status = v_z;
if (status == 0) {
goto ok;
} else if (status > 0) {
status = WUFFS_DEFLATE__ERROR_CANNOT_RETURN_A_SUSPENSION;
}
goto exit;
}
v_written = ((wuffs_base__slice_u8){
.ptr = a_dst.private_impl.bounds[0],
.len = (size_t)(ioptr_dst - a_dst.private_impl.bounds[0]),
});
if (((uint64_t)(v_written.len)) >= 32768) {
v_written = wuffs_base__slice_u8__suffix(v_written, 32768);
wuffs_base__slice_u8__copy_from_slice(
((wuffs_base__slice_u8){.ptr = self->private_impl.f_history,
.len = 32768}),
v_written);
self->private_impl.f_history_index = 32768;
} else {
v_n_copied = wuffs_base__slice_u8__copy_from_slice(
wuffs_base__slice_u8__subslice_i(
((wuffs_base__slice_u8){.ptr = self->private_impl.f_history,
.len = 32768}),
(self->private_impl.f_history_index & 32767)),
v_written);
if (v_n_copied < ((uint64_t)(v_written.len))) {
v_written = wuffs_base__slice_u8__subslice_i(v_written, v_n_copied);
v_n_copied = wuffs_base__slice_u8__copy_from_slice(
((wuffs_base__slice_u8){.ptr = self->private_impl.f_history,
.len = 32768}),
v_written);
self->private_impl.f_history_index =
(((uint32_t)((v_n_copied & 32767))) + 32768);
} else {
v_already_full = 0;
if (self->private_impl.f_history_index >= 32768) {
v_already_full = 32768;
}
self->private_impl.f_history_index =
((self->private_impl.f_history_index & 32767) +
((uint32_t)((v_n_copied & 32767))) + v_already_full);
}
}
status = v_z;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
}
goto ok;
ok:
self->private_impl.c_decode[0].coro_susp_point = 0;
goto exit;
}
goto suspend;
suspend:
self->private_impl.c_decode[0].coro_susp_point = coro_susp_point;
self->private_impl.c_decode[0].v_z = v_z;
self->private_impl.c_decode[0].v_n_copied = v_n_copied;
self->private_impl.c_decode[0].v_already_full = v_already_full;
goto exit;
exit:
if (a_dst.private_impl.buf) {
a_dst.private_impl.buf->wi = ioptr_dst - a_dst.private_impl.buf->ptr;
}
self->private_impl.status = status;
return status;
}
// -------- func decoder.decode_blocks
static wuffs_deflate__status wuffs_deflate__decoder__decode_blocks(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src) {
wuffs_deflate__status status = WUFFS_DEFLATE__STATUS_OK;
uint32_t v_final;
uint32_t v_type;
uint8_t* ioptr_src = NULL;
uint8_t* iobounds0orig_src = NULL;
uint8_t* iobounds1_src = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_src);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
if (!a_src.private_impl.bounds[0]) {
a_src.private_impl.bounds[0] = ioptr_src;
a_src.private_impl.bounds[1] =
a_src.private_impl.buf->ptr + a_src.private_impl.buf->wi;
}
iobounds0orig_src = a_src.private_impl.bounds[0];
iobounds1_src = a_src.private_impl.bounds[1];
}
uint32_t coro_susp_point =
self->private_impl.c_decode_blocks[0].coro_susp_point;
if (coro_susp_point) {
v_final = self->private_impl.c_decode_blocks[0].v_final;
v_type = self->private_impl.c_decode_blocks[0].v_type;
} else {
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
v_final = 0;
label_0_continue:;
while (v_final == 0) {
while (self->private_impl.f_n_bits < 3) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_0 = *ioptr_src++;
self->private_impl.f_bits |=
(((uint32_t)(t_0)) << self->private_impl.f_n_bits);
}
self->private_impl.f_n_bits += 8;
}
v_final = (self->private_impl.f_bits & 1);
v_type = ((self->private_impl.f_bits >> 1) & 3);
self->private_impl.f_bits >>= 3;
self->private_impl.f_n_bits -= 3;
if (v_type == 0) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
status =
wuffs_deflate__decoder__decode_uncompressed(self, a_dst, a_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
}
if (status) {
goto suspend;
}
goto label_0_continue;
} else if (v_type == 1) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
status = wuffs_deflate__decoder__init_fixed_huffman(self);
if (status) {
goto suspend;
}
} else if (v_type == 2) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
status = wuffs_deflate__decoder__init_dynamic_huffman(self, a_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
}
if (status) {
goto suspend;
}
} else {
status = WUFFS_DEFLATE__ERROR_BAD_BLOCK;
goto exit;
}
self->private_impl.f_end_of_block = false;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
status = wuffs_deflate__decoder__decode_huffman_fast(self, a_dst, a_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
}
if (status) {
goto suspend;
}
if (self->private_impl.f_end_of_block) {
goto label_0_continue;
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
status = wuffs_deflate__decoder__decode_huffman_slow(self, a_dst, a_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
}
if (status) {
goto suspend;
}
if (self->private_impl.f_end_of_block) {
goto label_0_continue;
}
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_END_OF_BLOCK;
goto exit;
}
goto ok;
ok:
self->private_impl.c_decode_blocks[0].coro_susp_point = 0;
goto exit;
}
goto suspend;
suspend:
self->private_impl.c_decode_blocks[0].coro_susp_point = coro_susp_point;
self->private_impl.c_decode_blocks[0].v_final = v_final;
self->private_impl.c_decode_blocks[0].v_type = v_type;
goto exit;
exit:
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
return status;
short_read_src:
if (wuffs_base__io_reader__is_eof(a_src)) {
status = WUFFS_DEFLATE__ERROR_UNEXPECTED_EOF;
goto exit;
}
status = WUFFS_DEFLATE__SUSPENSION_SHORT_READ;
goto suspend;
}
// -------- func decoder.decode_uncompressed
static wuffs_deflate__status wuffs_deflate__decoder__decode_uncompressed(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src) {
wuffs_deflate__status status = WUFFS_DEFLATE__STATUS_OK;
uint32_t v_length;
uint32_t v_n_copied;
uint8_t* ioptr_dst = NULL;
uint8_t* iobounds0orig_dst = NULL;
uint8_t* iobounds1_dst = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_dst);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_dst);
if (a_dst.private_impl.buf) {
ioptr_dst = a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->wi;
if (!a_dst.private_impl.bounds[0]) {
a_dst.private_impl.bounds[0] = ioptr_dst;
a_dst.private_impl.bounds[1] =
a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->len;
}
if (a_dst.private_impl.buf->closed) {
a_dst.private_impl.bounds[1] = ioptr_dst;
}
iobounds0orig_dst = a_dst.private_impl.bounds[0];
iobounds1_dst = a_dst.private_impl.bounds[1];
}
uint8_t* ioptr_src = NULL;
uint8_t* iobounds0orig_src = NULL;
uint8_t* iobounds1_src = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_src);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
if (!a_src.private_impl.bounds[0]) {
a_src.private_impl.bounds[0] = ioptr_src;
a_src.private_impl.bounds[1] =
a_src.private_impl.buf->ptr + a_src.private_impl.buf->wi;
}
iobounds0orig_src = a_src.private_impl.bounds[0];
iobounds1_src = a_src.private_impl.bounds[1];
}
uint32_t coro_susp_point =
self->private_impl.c_decode_uncompressed[0].coro_susp_point;
if (coro_susp_point) {
v_length = self->private_impl.c_decode_uncompressed[0].v_length;
v_n_copied = self->private_impl.c_decode_uncompressed[0].v_n_copied;
} else {
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
if ((self->private_impl.f_n_bits >= 8) ||
((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
status = WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_N_BITS;
goto exit;
}
self->private_impl.f_n_bits = 0;
self->private_impl.f_bits = 0;
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
uint32_t t_1;
if (WUFFS_BASE__LIKELY(iobounds1_src - ioptr_src >= 4)) {
t_1 = wuffs_base__load_u32le(ioptr_src);
ioptr_src += 4;
} else {
self->private_impl.c_decode_uncompressed[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
while (true) {
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint64_t* scratch =
&self->private_impl.c_decode_uncompressed[0].scratch;
uint32_t t_0 = *scratch >> 56;
*scratch <<= 8;
*scratch >>= 8;
*scratch |= ((uint64_t)(*ioptr_src++)) << t_0;
if (t_0 == 24) {
t_1 = *scratch;
break;
}
t_0 += 8;
*scratch |= ((uint64_t)(t_0)) << 56;
}
}
v_length = t_1;
}
if ((((v_length) & ((1 << (16)) - 1)) + ((v_length) >> (32 - (16)))) !=
65535) {
status = WUFFS_DEFLATE__ERROR_INCONSISTENT_STORED_BLOCK_LENGTH;
goto exit;
}
v_length = ((v_length) & ((1 << (16)) - 1));
while (true) {
v_n_copied = wuffs_base__io_writer__copy_from_reader32(
&ioptr_dst, iobounds1_dst, &ioptr_src, iobounds1_src, v_length);
if (v_length <= v_n_copied) {
status = WUFFS_DEFLATE__STATUS_OK;
goto ok;
}
v_length -= v_n_copied;
if (((uint64_t)(iobounds1_dst - ioptr_dst)) == 0) {
status = WUFFS_DEFLATE__SUSPENSION_SHORT_WRITE;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
} else {
status = WUFFS_DEFLATE__SUSPENSION_SHORT_READ;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
}
}
goto ok;
ok:
self->private_impl.c_decode_uncompressed[0].coro_susp_point = 0;
goto exit;
}
goto suspend;
suspend:
self->private_impl.c_decode_uncompressed[0].coro_susp_point = coro_susp_point;
self->private_impl.c_decode_uncompressed[0].v_length = v_length;
self->private_impl.c_decode_uncompressed[0].v_n_copied = v_n_copied;
goto exit;
exit:
if (a_dst.private_impl.buf) {
a_dst.private_impl.buf->wi = ioptr_dst - a_dst.private_impl.buf->ptr;
}
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
return status;
short_read_src:
if (wuffs_base__io_reader__is_eof(a_src)) {
status = WUFFS_DEFLATE__ERROR_UNEXPECTED_EOF;
goto exit;
}
status = WUFFS_DEFLATE__SUSPENSION_SHORT_READ;
goto suspend;
}
// -------- func decoder.init_fixed_huffman
static wuffs_deflate__status wuffs_deflate__decoder__init_fixed_huffman(
wuffs_deflate__decoder* self) {
wuffs_deflate__status status = WUFFS_DEFLATE__STATUS_OK;
uint32_t v_i;
uint32_t coro_susp_point =
self->private_impl.c_init_fixed_huffman[0].coro_susp_point;
if (coro_susp_point) {
v_i = self->private_impl.c_init_fixed_huffman[0].v_i;
} else {
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
v_i = 0;
while (v_i < 144) {
self->private_impl.f_code_lengths[v_i] = 8;
v_i += 1;
}
while (v_i < 256) {
self->private_impl.f_code_lengths[v_i] = 9;
v_i += 1;
}
while (v_i < 280) {
self->private_impl.f_code_lengths[v_i] = 7;
v_i += 1;
}
while (v_i < 288) {
self->private_impl.f_code_lengths[v_i] = 8;
v_i += 1;
}
while (v_i < 320) {
self->private_impl.f_code_lengths[v_i] = 5;
v_i += 1;
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
status = wuffs_deflate__decoder__init_huff(self, 0, 0, 288, 257);
if (status) {
goto suspend;
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
status = wuffs_deflate__decoder__init_huff(self, 1, 288, 320, 0);
if (status) {
goto suspend;
}
goto ok;
ok:
self->private_impl.c_init_fixed_huffman[0].coro_susp_point = 0;
goto exit;
}
goto suspend;
suspend:
self->private_impl.c_init_fixed_huffman[0].coro_susp_point = coro_susp_point;
self->private_impl.c_init_fixed_huffman[0].v_i = v_i;
goto exit;
exit:
return status;
}
// -------- func decoder.init_dynamic_huffman
static wuffs_deflate__status wuffs_deflate__decoder__init_dynamic_huffman(
wuffs_deflate__decoder* self,
wuffs_base__io_reader a_src) {
wuffs_deflate__status status = WUFFS_DEFLATE__STATUS_OK;
uint32_t v_bits;
uint32_t v_n_bits;
uint32_t v_n_lit;
uint32_t v_n_dist;
uint32_t v_n_clen;
uint32_t v_i;
uint32_t v_mask;
uint32_t v_table_entry;
uint32_t v_table_entry_n_bits;
uint32_t v_n_extra_bits;
uint8_t v_rep_symbol;
uint32_t v_rep_count;
uint8_t* ioptr_src = NULL;
uint8_t* iobounds0orig_src = NULL;
uint8_t* iobounds1_src = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_src);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
if (!a_src.private_impl.bounds[0]) {
a_src.private_impl.bounds[0] = ioptr_src;
a_src.private_impl.bounds[1] =
a_src.private_impl.buf->ptr + a_src.private_impl.buf->wi;
}
iobounds0orig_src = a_src.private_impl.bounds[0];
iobounds1_src = a_src.private_impl.bounds[1];
}
uint32_t coro_susp_point =
self->private_impl.c_init_dynamic_huffman[0].coro_susp_point;
if (coro_susp_point) {
v_bits = self->private_impl.c_init_dynamic_huffman[0].v_bits;
v_n_bits = self->private_impl.c_init_dynamic_huffman[0].v_n_bits;
v_n_lit = self->private_impl.c_init_dynamic_huffman[0].v_n_lit;
v_n_dist = self->private_impl.c_init_dynamic_huffman[0].v_n_dist;
v_n_clen = self->private_impl.c_init_dynamic_huffman[0].v_n_clen;
v_i = self->private_impl.c_init_dynamic_huffman[0].v_i;
v_mask = self->private_impl.c_init_dynamic_huffman[0].v_mask;
v_table_entry = self->private_impl.c_init_dynamic_huffman[0].v_table_entry;
v_table_entry_n_bits =
self->private_impl.c_init_dynamic_huffman[0].v_table_entry_n_bits;
v_n_extra_bits =
self->private_impl.c_init_dynamic_huffman[0].v_n_extra_bits;
v_rep_symbol = self->private_impl.c_init_dynamic_huffman[0].v_rep_symbol;
v_rep_count = self->private_impl.c_init_dynamic_huffman[0].v_rep_count;
} else {
}
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 < 14) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_0 = *ioptr_src++;
v_bits |= (((uint32_t)(t_0)) << v_n_bits);
}
v_n_bits += 8;
}
v_n_lit = (((v_bits) & ((1 << (5)) - 1)) + 257);
if (v_n_lit > 286) {
status = WUFFS_DEFLATE__ERROR_BAD_LITERAL_LENGTH_CODE_COUNT;
goto exit;
}
v_bits >>= 5;
v_n_dist = (((v_bits) & ((1 << (5)) - 1)) + 1);
if (v_n_dist > 30) {
status = WUFFS_DEFLATE__ERROR_BAD_DISTANCE_CODE_COUNT;
goto exit;
}
v_bits >>= 5;
v_n_clen = (((v_bits) & ((1 << (4)) - 1)) + 4);
v_bits >>= 4;
v_n_bits -= 14;
v_i = 0;
while (v_i < v_n_clen) {
while (v_n_bits < 3) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_1 = *ioptr_src++;
v_bits |= (((uint32_t)(t_1)) << v_n_bits);
}
v_n_bits += 8;
}
self->private_impl.f_code_lengths[wuffs_deflate__code_order[v_i]] =
((uint8_t)((v_bits & 7)));
v_bits >>= 3;
v_n_bits -= 3;
v_i += 1;
}
while (v_i < 19) {
self->private_impl.f_code_lengths[wuffs_deflate__code_order[v_i]] = 0;
v_i += 1;
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
status = wuffs_deflate__decoder__init_huff(self, 0, 0, 19, 4095);
if (status) {
goto suspend;
}
v_mask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
v_i = 0;
label_0_continue:;
while (v_i < (v_n_lit + v_n_dist)) {
v_table_entry = 0;
while (true) {
v_table_entry = self->private_impl.f_huffs[0][(v_bits & v_mask)];
v_table_entry_n_bits = (v_table_entry & 15);
if (v_n_bits >= v_table_entry_n_bits) {
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
goto label_1_break;
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_2 = *ioptr_src++;
v_bits |= (((uint32_t)(t_2)) << v_n_bits);
}
v_n_bits += 8;
}
label_1_break:;
if ((v_table_entry >> 24) != 128) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_table_entry = ((v_table_entry >> 8) & 255);
if (v_table_entry < 16) {
self->private_impl.f_code_lengths[v_i] = ((uint8_t)(v_table_entry));
v_i += 1;
goto label_0_continue;
}
v_n_extra_bits = 0;
v_rep_symbol = 0;
v_rep_count = 0;
if (v_table_entry == 16) {
v_n_extra_bits = 2;
if (v_i <= 0) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_REPETITION;
goto exit;
}
v_rep_symbol = self->private_impl.f_code_lengths[(v_i - 1)];
v_rep_count = 3;
} else if (v_table_entry == 17) {
v_n_extra_bits = 3;
v_rep_symbol = 0;
v_rep_count = 3;
} else if (v_table_entry == 18) {
v_n_extra_bits = 7;
v_rep_symbol = 0;
v_rep_count = 11;
} else {
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(5);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_3 = *ioptr_src++;
v_bits |= (((uint32_t)(t_3)) << v_n_bits);
}
v_n_bits += 8;
}
v_rep_count += ((v_bits) & ((1 << (v_n_extra_bits)) - 1));
v_bits >>= v_n_extra_bits;
v_n_bits -= v_n_extra_bits;
while (v_rep_count > 0) {
if (v_i >= (v_n_lit + v_n_dist)) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_COUNT;
goto exit;
}
self->private_impl.f_code_lengths[v_i] = v_rep_symbol;
v_i += 1;
v_rep_count -= 1;
}
}
if (v_i != (v_n_lit + v_n_dist)) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_COUNT;
goto exit;
}
if (self->private_impl.f_code_lengths[256] == 0) {
status = WUFFS_DEFLATE__ERROR_MISSING_END_OF_BLOCK_CODE;
goto exit;
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
status = wuffs_deflate__decoder__init_huff(self, 0, 0, v_n_lit, 257);
if (status) {
goto suspend;
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
status = wuffs_deflate__decoder__init_huff(self, 1, v_n_lit,
(v_n_lit + v_n_dist), 0);
if (status) {
goto suspend;
}
self->private_impl.f_bits = v_bits;
self->private_impl.f_n_bits = v_n_bits;
goto ok;
ok:
self->private_impl.c_init_dynamic_huffman[0].coro_susp_point = 0;
goto exit;
}
goto suspend;
suspend:
self->private_impl.c_init_dynamic_huffman[0].coro_susp_point =
coro_susp_point;
self->private_impl.c_init_dynamic_huffman[0].v_bits = v_bits;
self->private_impl.c_init_dynamic_huffman[0].v_n_bits = v_n_bits;
self->private_impl.c_init_dynamic_huffman[0].v_n_lit = v_n_lit;
self->private_impl.c_init_dynamic_huffman[0].v_n_dist = v_n_dist;
self->private_impl.c_init_dynamic_huffman[0].v_n_clen = v_n_clen;
self->private_impl.c_init_dynamic_huffman[0].v_i = v_i;
self->private_impl.c_init_dynamic_huffman[0].v_mask = v_mask;
self->private_impl.c_init_dynamic_huffman[0].v_table_entry = v_table_entry;
self->private_impl.c_init_dynamic_huffman[0].v_table_entry_n_bits =
v_table_entry_n_bits;
self->private_impl.c_init_dynamic_huffman[0].v_n_extra_bits = v_n_extra_bits;
self->private_impl.c_init_dynamic_huffman[0].v_rep_symbol = v_rep_symbol;
self->private_impl.c_init_dynamic_huffman[0].v_rep_count = v_rep_count;
goto exit;
exit:
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
return status;
short_read_src:
if (wuffs_base__io_reader__is_eof(a_src)) {
status = WUFFS_DEFLATE__ERROR_UNEXPECTED_EOF;
goto exit;
}
status = WUFFS_DEFLATE__SUSPENSION_SHORT_READ;
goto suspend;
}
// -------- func decoder.init_huff
static wuffs_deflate__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) {
wuffs_deflate__status status = WUFFS_DEFLATE__STATUS_OK;
uint16_t v_counts[16];
uint32_t v_i;
uint32_t v_remaining;
uint16_t v_offsets[16];
uint32_t v_n_symbols;
uint32_t v_count;
uint16_t v_symbols[320];
uint32_t v_min_cl;
uint32_t v_max_cl;
uint32_t v_initial_high_bits;
uint32_t v_prev_cl;
uint32_t v_prev_redirect_key;
uint32_t v_top;
uint32_t v_next_top;
uint32_t v_code;
uint32_t v_key;
uint32_t v_value;
uint32_t v_cl;
uint32_t v_tmp;
uint32_t v_redirect_key;
uint32_t v_j;
uint32_t v_reversed_key;
uint32_t v_symbol;
uint32_t v_high_bits;
uint32_t v_delta;
memset(v_counts, 0, sizeof(v_counts));
v_i = a_n_codes0;
while (v_i < a_n_codes1) {
if (v_counts[self->private_impl.f_code_lengths[v_i]] >= 320) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_counts[self->private_impl.f_code_lengths[v_i]] += 1;
v_i += 1;
}
if ((((uint32_t)(v_counts[0])) + a_n_codes0) == a_n_codes1) {
status = WUFFS_DEFLATE__ERROR_NO_HUFFMAN_CODES;
goto exit;
}
v_remaining = 1;
v_i = 1;
while (v_i <= 15) {
if (v_remaining > 1073741824) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_remaining <<= 1;
if (v_remaining < ((uint32_t)(v_counts[v_i]))) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_OVER_SUBSCRIBED;
goto exit;
}
v_remaining -= ((uint32_t)(v_counts[v_i]));
v_i += 1;
}
if (v_remaining != 0) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE_UNDER_SUBSCRIBED;
goto exit;
}
memset(v_offsets, 0, sizeof(v_offsets));
v_n_symbols = 0;
v_i = 1;
while (v_i <= 15) {
v_offsets[v_i] = ((uint16_t)(v_n_symbols));
v_count = ((uint32_t)(v_counts[v_i]));
if (v_n_symbols > (320 - v_count)) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_n_symbols = (v_n_symbols + v_count);
v_i += 1;
}
if (v_n_symbols > 288) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
memset(v_symbols, 0, sizeof(v_symbols));
v_i = a_n_codes0;
while (v_i < a_n_codes1) {
if (v_i < a_n_codes0) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
if (self->private_impl.f_code_lengths[v_i] != 0) {
if (v_offsets[self->private_impl.f_code_lengths[v_i]] >= 320) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_symbols[v_offsets[self->private_impl.f_code_lengths[v_i]]] =
((uint16_t)((v_i - a_n_codes0)));
v_offsets[self->private_impl.f_code_lengths[v_i]] += 1;
}
v_i += 1;
}
v_min_cl = 1;
while (true) {
if (v_counts[v_min_cl] != 0) {
goto label_0_break;
}
if (v_min_cl >= 9) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_MINIMUM_CODE_LENGTH;
goto exit;
}
v_min_cl += 1;
}
label_0_break:;
v_max_cl = 15;
while (true) {
if (v_counts[v_max_cl] != 0) {
goto label_1_break;
}
if (v_max_cl <= 1) {
status = WUFFS_DEFLATE__ERROR_NO_HUFFMAN_CODES;
goto exit;
}
v_max_cl -= 1;
}
label_1_break:;
if (v_max_cl <= 9) {
self->private_impl.f_n_huffs_bits[a_which] = v_max_cl;
} else {
self->private_impl.f_n_huffs_bits[a_which] = 9;
}
v_i = 0;
if ((v_n_symbols != ((uint32_t)(v_offsets[v_max_cl]))) ||
(v_n_symbols != ((uint32_t)(v_offsets[15])))) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
if ((a_n_codes0 + ((uint32_t)(v_symbols[0]))) >= 320) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_initial_high_bits = 512;
if (v_max_cl < 9) {
v_initial_high_bits = (((uint32_t)(1)) << v_max_cl);
}
v_prev_cl = ((uint32_t)(self->private_impl.f_code_lengths[(
a_n_codes0 + ((uint32_t)(v_symbols[0])))]));
v_prev_redirect_key = 4294967295;
v_top = 0;
v_next_top = 512;
v_code = 0;
v_key = 0;
v_value = 0;
while (true) {
if ((a_n_codes0 + ((uint32_t)(v_symbols[v_i]))) >= 320) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_cl = ((uint32_t)(self->private_impl.f_code_lengths[(
a_n_codes0 + ((uint32_t)(v_symbols[v_i])))]));
if (v_cl > v_prev_cl) {
v_code <<= (v_cl - v_prev_cl);
if (v_code >= 32768) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
}
v_prev_cl = v_cl;
v_key = v_code;
if (v_cl > 9) {
v_tmp = (v_cl - 9);
v_cl = v_tmp;
v_redirect_key = ((v_key >> v_tmp) & 511);
v_key = ((v_key) & ((1 << (v_tmp)) - 1));
if (v_prev_redirect_key != v_redirect_key) {
v_prev_redirect_key = v_redirect_key;
v_remaining = (((uint32_t)(1)) << v_cl);
v_j = v_prev_cl;
while (v_j <= 15) {
if (v_remaining <= ((uint32_t)(v_counts[v_j]))) {
goto label_2_break;
}
v_remaining -= ((uint32_t)(v_counts[v_j]));
if (v_remaining > 1073741824) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_remaining <<= 1;
v_j += 1;
}
label_2_break:;
if ((v_j <= 9) || (15 < v_j)) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_tmp = (v_j - 9);
v_initial_high_bits = (((uint32_t)(1)) << v_tmp);
v_top = v_next_top;
if ((v_top + (((uint32_t)(1)) << v_tmp)) > 1234) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_next_top = (v_top + (((uint32_t)(1)) << v_tmp));
v_redirect_key =
(((uint32_t)(wuffs_deflate__reverse8[(v_redirect_key >> 1)])) |
((v_redirect_key & 1) << 8));
self->private_impl.f_huffs[a_which][v_redirect_key] =
(268435465 | (v_top << 8) | (v_tmp << 4));
}
}
if ((v_key >= 512) || (v_counts[v_prev_cl] <= 0)) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_counts[v_prev_cl] -= 1;
v_reversed_key = (((uint32_t)(wuffs_deflate__reverse8[(v_key >> 1)])) |
((v_key & 1) << 8));
v_reversed_key >>= (9 - v_cl);
v_symbol = ((uint32_t)(v_symbols[v_i]));
if (v_symbol == 256) {
v_value = (536870912 | v_cl);
} else if ((v_symbol < 256) && (a_which == 0)) {
v_value = (2147483648 | (v_symbol << 8) | v_cl);
} else if (v_symbol >= a_base_symbol) {
v_symbol -= a_base_symbol;
if (a_which == 0) {
v_value = (wuffs_deflate__lcode_magic_numbers[(v_symbol & 31)] | v_cl);
} else {
v_value = (wuffs_deflate__dcode_magic_numbers[(v_symbol & 31)] | v_cl);
}
} else {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_high_bits = v_initial_high_bits;
v_delta = (((uint32_t)(1)) << v_cl);
while (v_high_bits >= v_delta) {
v_high_bits -= v_delta;
if ((v_top + ((v_high_bits | v_reversed_key) & 511)) >= 1234) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
self->private_impl
.f_huffs[a_which][(v_top + ((v_high_bits | v_reversed_key) & 511))] =
v_value;
}
v_i += 1;
if (v_i >= v_n_symbols) {
goto label_3_break;
}
v_code += 1;
if (v_code >= 32768) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
}
label_3_break:;
goto exit;
exit:
return status;
}
// -------- func decoder.decode_huffman_fast
static wuffs_deflate__status wuffs_deflate__decoder__decode_huffman_fast(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src) {
wuffs_deflate__status status = WUFFS_DEFLATE__STATUS_OK;
uint32_t v_bits;
uint32_t v_n_bits;
uint32_t v_table_entry;
uint32_t v_table_entry_n_bits;
uint32_t v_lmask;
uint32_t v_dmask;
uint32_t v_redir_top;
uint32_t v_redir_mask;
uint32_t v_length;
uint32_t v_dist_minus_1;
uint32_t v_n_copied;
uint32_t v_hlen;
uint32_t v_hdist;
uint8_t* ioptr_dst = NULL;
uint8_t* iobounds0orig_dst = NULL;
uint8_t* iobounds1_dst = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_dst);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_dst);
if (a_dst.private_impl.buf) {
ioptr_dst = a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->wi;
if (!a_dst.private_impl.bounds[0]) {
a_dst.private_impl.bounds[0] = ioptr_dst;
a_dst.private_impl.bounds[1] =
a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->len;
}
if (a_dst.private_impl.buf->closed) {
a_dst.private_impl.bounds[1] = ioptr_dst;
}
iobounds0orig_dst = a_dst.private_impl.bounds[0];
iobounds1_dst = a_dst.private_impl.bounds[1];
}
uint8_t* ioptr_src = NULL;
uint8_t* iobounds0orig_src = NULL;
uint8_t* iobounds1_src = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_src);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
if (!a_src.private_impl.bounds[0]) {
a_src.private_impl.bounds[0] = ioptr_src;
a_src.private_impl.bounds[1] =
a_src.private_impl.buf->ptr + a_src.private_impl.buf->wi;
}
iobounds0orig_src = a_src.private_impl.bounds[0];
iobounds1_src = a_src.private_impl.bounds[1];
}
if ((self->private_impl.f_n_bits >= 8) ||
((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
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_table_entry = 0;
v_table_entry_n_bits = 0;
v_lmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
v_dmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
label_0_continue:;
while ((((uint64_t)(iobounds1_dst - ioptr_dst)) >= 258) &&
(((uint64_t)(iobounds1_src - ioptr_src)) >= 12)) {
if (v_n_bits < 15) {
{
uint8_t t_0 = *ioptr_src++;
v_bits |= (((uint32_t)(t_0)) << v_n_bits);
}
v_n_bits += 8;
{
uint8_t t_1 = *ioptr_src++;
v_bits |= (((uint32_t)(t_1)) << v_n_bits);
}
v_n_bits += 8;
} else {
}
v_table_entry = self->private_impl.f_huffs[0][(v_bits & v_lmask)];
v_table_entry_n_bits = (v_table_entry & 15);
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
if ((v_table_entry >> 31) != 0) {
*ioptr_dst++ = ((uint8_t)(((v_table_entry >> 8) & 255)));
goto label_0_continue;
} else if ((v_table_entry >> 30) != 0) {
} else if ((v_table_entry >> 29) != 0) {
self->private_impl.f_end_of_block = true;
goto label_0_break;
} else if ((v_table_entry >> 28) != 0) {
if (v_n_bits < 15) {
{
uint8_t t_2 = *ioptr_src++;
v_bits |= (((uint32_t)(t_2)) << v_n_bits);
}
v_n_bits += 8;
{
uint8_t t_3 = *ioptr_src++;
v_bits |= (((uint32_t)(t_3)) << v_n_bits);
}
v_n_bits += 8;
} else {
}
v_redir_top = ((v_table_entry >> 8) & 65535);
v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
if ((v_redir_top + (v_bits & v_redir_mask)) >= 1234) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_table_entry = self->private_impl
.f_huffs[0][(v_redir_top + (v_bits & v_redir_mask))];
v_table_entry_n_bits = (v_table_entry & 15);
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
if ((v_table_entry >> 31) != 0) {
*ioptr_dst++ = ((uint8_t)(((v_table_entry >> 8) & 255)));
goto label_0_continue;
} else if ((v_table_entry >> 30) != 0) {
} else if ((v_table_entry >> 29) != 0) {
self->private_impl.f_end_of_block = true;
goto label_0_break;
} else if ((v_table_entry >> 28) != 0) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
} else if ((v_table_entry >> 27) != 0) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE;
goto exit;
} else {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
} else if ((v_table_entry >> 27) != 0) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE;
goto exit;
} else {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_length = ((v_table_entry >> 8) & 32767);
v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
if (v_table_entry_n_bits > 0) {
if (v_n_bits < 15) {
{
uint8_t t_4 = *ioptr_src++;
v_bits |= (((uint32_t)(t_4)) << v_n_bits);
}
v_n_bits += 8;
{
uint8_t t_5 = *ioptr_src++;
v_bits |= (((uint32_t)(t_5)) << v_n_bits);
}
v_n_bits += 8;
} else {
}
v_length =
((v_length + ((v_bits) & ((1 << (v_table_entry_n_bits)) - 1))) &
32767);
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
} else {
}
if (v_length > 258) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
if (v_n_bits < 15) {
{
uint8_t t_6 = *ioptr_src++;
v_bits |= (((uint32_t)(t_6)) << v_n_bits);
}
v_n_bits += 8;
{
uint8_t t_7 = *ioptr_src++;
v_bits |= (((uint32_t)(t_7)) << v_n_bits);
}
v_n_bits += 8;
} else {
}
v_table_entry = self->private_impl.f_huffs[1][(v_bits & v_dmask)];
v_table_entry_n_bits = (v_table_entry & 15);
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
if ((v_table_entry >> 28) == 1) {
if (v_n_bits < 15) {
{
uint8_t t_8 = *ioptr_src++;
v_bits |= (((uint32_t)(t_8)) << v_n_bits);
}
v_n_bits += 8;
{
uint8_t t_9 = *ioptr_src++;
v_bits |= (((uint32_t)(t_9)) << v_n_bits);
}
v_n_bits += 8;
} else {
}
v_redir_top = ((v_table_entry >> 8) & 65535);
v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
if ((v_redir_top + (v_bits & v_redir_mask)) >= 1234) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_table_entry = self->private_impl
.f_huffs[1][(v_redir_top + (v_bits & v_redir_mask))];
v_table_entry_n_bits = (v_table_entry & 15);
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
} else {
}
if ((v_table_entry >> 24) != 64) {
if ((v_table_entry >> 24) == 8) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE;
goto exit;
}
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
if (v_table_entry_n_bits > 0) {
if (v_n_bits < 15) {
{
uint8_t t_10 = *ioptr_src++;
v_bits |= (((uint32_t)(t_10)) << v_n_bits);
}
v_n_bits += 8;
{
uint8_t t_11 = *ioptr_src++;
v_bits |= (((uint32_t)(t_11)) << v_n_bits);
}
v_n_bits += 8;
}
v_dist_minus_1 =
((v_dist_minus_1 + ((v_bits) & ((1 << (v_table_entry_n_bits)) - 1))) &
32767);
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
}
v_n_copied = 0;
while (true) {
if (((uint64_t)((v_dist_minus_1 + 1))) >
((uint64_t)(
((wuffs_base__slice_u8){
.ptr = a_dst.private_impl.bounds[0],
.len = (size_t)(ioptr_dst - a_dst.private_impl.bounds[0]),
})
.len))) {
v_hlen = 0;
v_hdist = ((uint32_t)(
(((uint64_t)((v_dist_minus_1 + 1))) -
((uint64_t)(
((wuffs_base__slice_u8){
.ptr = a_dst.private_impl.bounds[0],
.len = (size_t)(ioptr_dst - a_dst.private_impl.bounds[0]),
})
.len)))));
if (v_length > v_hdist) {
v_length -= v_hdist;
v_hlen = v_hdist;
if (v_length > 258) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
} else {
v_hlen = v_length;
v_length = 0;
}
if (self->private_impl.f_history_index < v_hdist) {
status = WUFFS_DEFLATE__ERROR_BAD_DISTANCE;
goto exit;
}
v_hdist = (self->private_impl.f_history_index - v_hdist);
while (true) {
v_n_copied = wuffs_base__io_writer__copy_from_slice32(
&ioptr_dst, iobounds1_dst,
wuffs_base__slice_u8__subslice_i(
((wuffs_base__slice_u8){.ptr = self->private_impl.f_history,
.len = 32768}),
(v_hdist & 32767)),
v_hlen);
if (v_hlen <= v_n_copied) {
goto label_1_break;
}
v_hlen -= v_n_copied;
wuffs_base__io_writer__copy_from_slice32(
&ioptr_dst, iobounds1_dst,
((wuffs_base__slice_u8){.ptr = self->private_impl.f_history,
.len = 32768}),
v_hlen);
goto label_1_break;
}
label_1_break:;
if (v_length == 0) {
goto label_0_continue;
}
if (((uint64_t)((v_dist_minus_1 + 1))) >
((uint64_t)(
((wuffs_base__slice_u8){
.ptr = a_dst.private_impl.bounds[0],
.len = (size_t)(ioptr_dst - a_dst.private_impl.bounds[0]),
})
.len))) {
status = WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_DISTANCE;
goto exit;
}
}
wuffs_base__io_writer__copy_from_history32__bco(
&ioptr_dst, a_dst.private_impl.bounds[0], iobounds1_dst,
(v_dist_minus_1 + 1), v_length);
goto label_2_break;
}
label_2_break:;
}
label_0_break:;
while (v_n_bits >= 8) {
v_n_bits -= 8;
if (ioptr_src == iobounds0orig_src) {
status = WUFFS_DEFLATE__ERROR_INVALID_I_O_OPERATION;
goto exit;
}
ioptr_src--;
}
self->private_impl.f_bits = (v_bits & ((((uint32_t)(1)) << v_n_bits) - 1));
self->private_impl.f_n_bits = v_n_bits;
if ((self->private_impl.f_n_bits >= 8) ||
((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
status = WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_N_BITS;
goto exit;
}
goto exit;
exit:
if (a_dst.private_impl.buf) {
a_dst.private_impl.buf->wi = ioptr_dst - a_dst.private_impl.buf->ptr;
}
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
return status;
}
// -------- func decoder.decode_huffman_slow
static wuffs_deflate__status wuffs_deflate__decoder__decode_huffman_slow(
wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src) {
wuffs_deflate__status status = WUFFS_DEFLATE__STATUS_OK;
uint32_t v_bits;
uint32_t v_n_bits;
uint32_t v_table_entry;
uint32_t v_table_entry_n_bits;
uint32_t v_lmask;
uint32_t v_dmask;
uint32_t v_redir_top;
uint32_t v_redir_mask;
uint32_t v_length;
uint32_t v_dist_minus_1;
uint32_t v_n_copied;
uint32_t v_hlen;
uint32_t v_hdist;
uint8_t* ioptr_dst = NULL;
uint8_t* iobounds0orig_dst = NULL;
uint8_t* iobounds1_dst = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_dst);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_dst);
if (a_dst.private_impl.buf) {
ioptr_dst = a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->wi;
if (!a_dst.private_impl.bounds[0]) {
a_dst.private_impl.bounds[0] = ioptr_dst;
a_dst.private_impl.bounds[1] =
a_dst.private_impl.buf->ptr + a_dst.private_impl.buf->len;
}
if (a_dst.private_impl.buf->closed) {
a_dst.private_impl.bounds[1] = ioptr_dst;
}
iobounds0orig_dst = a_dst.private_impl.bounds[0];
iobounds1_dst = a_dst.private_impl.bounds[1];
}
uint8_t* ioptr_src = NULL;
uint8_t* iobounds0orig_src = NULL;
uint8_t* iobounds1_src = NULL;
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds0orig_src);
WUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(iobounds1_src);
if (a_src.private_impl.buf) {
ioptr_src = a_src.private_impl.buf->ptr + a_src.private_impl.buf->ri;
if (!a_src.private_impl.bounds[0]) {
a_src.private_impl.bounds[0] = ioptr_src;
a_src.private_impl.bounds[1] =
a_src.private_impl.buf->ptr + a_src.private_impl.buf->wi;
}
iobounds0orig_src = a_src.private_impl.bounds[0];
iobounds1_src = a_src.private_impl.bounds[1];
}
uint32_t coro_susp_point =
self->private_impl.c_decode_huffman_slow[0].coro_susp_point;
if (coro_susp_point) {
v_bits = self->private_impl.c_decode_huffman_slow[0].v_bits;
v_n_bits = self->private_impl.c_decode_huffman_slow[0].v_n_bits;
v_table_entry = self->private_impl.c_decode_huffman_slow[0].v_table_entry;
v_table_entry_n_bits =
self->private_impl.c_decode_huffman_slow[0].v_table_entry_n_bits;
v_lmask = self->private_impl.c_decode_huffman_slow[0].v_lmask;
v_dmask = self->private_impl.c_decode_huffman_slow[0].v_dmask;
v_redir_top = self->private_impl.c_decode_huffman_slow[0].v_redir_top;
v_redir_mask = self->private_impl.c_decode_huffman_slow[0].v_redir_mask;
v_length = self->private_impl.c_decode_huffman_slow[0].v_length;
v_dist_minus_1 = self->private_impl.c_decode_huffman_slow[0].v_dist_minus_1;
v_n_copied = self->private_impl.c_decode_huffman_slow[0].v_n_copied;
v_hlen = self->private_impl.c_decode_huffman_slow[0].v_hlen;
v_hdist = self->private_impl.c_decode_huffman_slow[0].v_hdist;
} else {
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
if ((self->private_impl.f_n_bits >= 8) ||
((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
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_table_entry = 0;
v_table_entry_n_bits = 0;
v_lmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
v_dmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
label_0_continue:;
while (true) {
while (true) {
v_table_entry = self->private_impl.f_huffs[0][(v_bits & v_lmask)];
v_table_entry_n_bits = (v_table_entry & 15);
if (v_n_bits >= v_table_entry_n_bits) {
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
goto label_1_break;
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_0 = *ioptr_src++;
v_bits |= (((uint32_t)(t_0)) << v_n_bits);
}
v_n_bits += 8;
}
label_1_break:;
if ((v_table_entry >> 31) != 0) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
if (ioptr_dst == iobounds1_dst) {
status = WUFFS_DEFLATE__SUSPENSION_SHORT_WRITE;
goto suspend;
}
*ioptr_dst++ = ((uint8_t)(((v_table_entry >> 8) & 255)));
goto label_0_continue;
} else if ((v_table_entry >> 30) != 0) {
} else if ((v_table_entry >> 29) != 0) {
self->private_impl.f_end_of_block = true;
goto label_0_break;
} else if ((v_table_entry >> 28) != 0) {
v_redir_top = ((v_table_entry >> 8) & 65535);
v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
while (true) {
if ((v_redir_top + (v_bits & v_redir_mask)) >= 1234) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_table_entry =
self->private_impl
.f_huffs[0][(v_redir_top + (v_bits & v_redir_mask))];
v_table_entry_n_bits = (v_table_entry & 15);
if (v_n_bits >= v_table_entry_n_bits) {
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
goto label_2_break;
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_1 = *ioptr_src++;
v_bits |= (((uint32_t)(t_1)) << v_n_bits);
}
v_n_bits += 8;
}
label_2_break:;
if ((v_table_entry >> 31) != 0) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
if (ioptr_dst == iobounds1_dst) {
status = WUFFS_DEFLATE__SUSPENSION_SHORT_WRITE;
goto suspend;
}
*ioptr_dst++ = ((uint8_t)(((v_table_entry >> 8) & 255)));
goto label_0_continue;
} else if ((v_table_entry >> 30) != 0) {
} else if ((v_table_entry >> 29) != 0) {
self->private_impl.f_end_of_block = true;
goto label_0_break;
} else if ((v_table_entry >> 28) != 0) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
} else if ((v_table_entry >> 27) != 0) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE;
goto exit;
} else {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
} else if ((v_table_entry >> 27) != 0) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE;
goto exit;
} else {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_length = ((v_table_entry >> 8) & 32767);
v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
if (v_table_entry_n_bits > 0) {
while (v_n_bits < v_table_entry_n_bits) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_2 = *ioptr_src++;
v_bits |= (((uint32_t)(t_2)) << v_n_bits);
}
v_n_bits += 8;
}
v_length =
((v_length + ((v_bits) & ((1 << (v_table_entry_n_bits)) - 1))) &
32767);
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
}
while (true) {
v_table_entry = self->private_impl.f_huffs[1][(v_bits & v_dmask)];
v_table_entry_n_bits = (v_table_entry & 15);
if (v_n_bits >= v_table_entry_n_bits) {
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
goto label_3_break;
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_3 = *ioptr_src++;
v_bits |= (((uint32_t)(t_3)) << v_n_bits);
}
v_n_bits += 8;
}
label_3_break:;
if ((v_table_entry >> 28) == 1) {
v_redir_top = ((v_table_entry >> 8) & 65535);
v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
while (true) {
if ((v_redir_top + (v_bits & v_redir_mask)) >= 1234) {
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_table_entry =
self->private_impl
.f_huffs[1][(v_redir_top + (v_bits & v_redir_mask))];
v_table_entry_n_bits = (v_table_entry & 15);
if (v_n_bits >= v_table_entry_n_bits) {
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
goto label_4_break;
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_4 = *ioptr_src++;
v_bits |= (((uint32_t)(t_4)) << v_n_bits);
}
v_n_bits += 8;
}
label_4_break:;
}
if ((v_table_entry >> 24) != 64) {
if ((v_table_entry >> 24) == 8) {
status = WUFFS_DEFLATE__ERROR_BAD_HUFFMAN_CODE;
goto exit;
}
status =
WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE;
goto exit;
}
v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
if (v_table_entry_n_bits > 0) {
while (v_n_bits < v_table_entry_n_bits) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
if (WUFFS_BASE__UNLIKELY(ioptr_src == iobounds1_src)) {
goto short_read_src;
}
uint8_t t_5 = *ioptr_src++;
v_bits |= (((uint32_t)(t_5)) << v_n_bits);
}
v_n_bits += 8;
}
v_dist_minus_1 = ((v_dist_minus_1 +
((v_bits) & ((1 << (v_table_entry_n_bits)) - 1))) &
32767);
v_bits >>= v_table_entry_n_bits;
v_n_bits -= v_table_entry_n_bits;
}
v_n_copied = 0;
while (true) {
if (((uint64_t)((v_dist_minus_1 + 1))) >
((uint64_t)(
((wuffs_base__slice_u8){
.ptr = a_dst.private_impl.bounds[0],
.len = (size_t)(ioptr_dst - a_dst.private_impl.bounds[0]),
})
.len))) {
v_hlen = 0;
v_hdist = ((uint32_t)(
(((uint64_t)((v_dist_minus_1 + 1))) -
((uint64_t)(((wuffs_base__slice_u8){
.ptr = a_dst.private_impl.bounds[0],
.len = (size_t)(ioptr_dst -
a_dst.private_impl.bounds[0]),
})
.len)))));
if (v_length > v_hdist) {
v_length -= v_hdist;
v_hlen = v_hdist;
} else {
v_hlen = v_length;
v_length = 0;
}
if (self->private_impl.f_history_index < v_hdist) {
status = WUFFS_DEFLATE__ERROR_BAD_DISTANCE;
goto exit;
}
v_hdist = (self->private_impl.f_history_index - v_hdist);
while (true) {
v_n_copied = wuffs_base__io_writer__copy_from_slice32(
&ioptr_dst, iobounds1_dst,
wuffs_base__slice_u8__subslice_i(
((wuffs_base__slice_u8){.ptr = self->private_impl.f_history,
.len = 32768}),
(v_hdist & 32767)),
v_hlen);
if (v_hlen <= v_n_copied) {
v_hlen = 0;
goto label_5_break;
}
if (v_n_copied > 0) {
v_hlen -= v_n_copied;
v_hdist = ((v_hdist + v_n_copied) & 32767);
if (v_hdist == 0) {
goto label_5_break;
}
}
status = WUFFS_DEFLATE__SUSPENSION_SHORT_WRITE;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
}
label_5_break:;
if (v_hlen > 0) {
while (true) {
v_n_copied = wuffs_base__io_writer__copy_from_slice32(
&ioptr_dst, iobounds1_dst,
wuffs_base__slice_u8__subslice_i(
((wuffs_base__slice_u8){
.ptr = self->private_impl.f_history, .len = 32768}),
(v_hdist & 32767)),
v_hlen);
if (v_hlen <= v_n_copied) {
v_hlen = 0;
goto label_6_break;
}
v_hlen -= v_n_copied;
v_hdist += v_n_copied;
status = WUFFS_DEFLATE__SUSPENSION_SHORT_WRITE;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
}
label_6_break:;
}
if (v_length == 0) {
goto label_0_continue;
}
}
v_n_copied = wuffs_base__io_writer__copy_from_history32(
&ioptr_dst, a_dst.private_impl.bounds[0], iobounds1_dst,
(v_dist_minus_1 + 1), v_length);
if (v_length <= v_n_copied) {
v_length = 0;
goto label_7_break;
}
v_length -= v_n_copied;
status = WUFFS_DEFLATE__SUSPENSION_SHORT_WRITE;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
}
label_7_break:;
}
label_0_break:;
self->private_impl.f_bits = v_bits;
self->private_impl.f_n_bits = v_n_bits;
if ((self->private_impl.f_n_bits >= 8) ||
((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
status = WUFFS_DEFLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_N_BITS;
goto exit;
}
goto ok;
ok:
self->private_impl.c_decode_huffman_slow[0].coro_susp_point = 0;
goto exit;
}
goto suspend;
suspend:
self->private_impl.c_decode_huffman_slow[0].coro_susp_point = coro_susp_point;
self->private_impl.c_decode_huffman_slow[0].v_bits = v_bits;
self->private_impl.c_decode_huffman_slow[0].v_n_bits = v_n_bits;
self->private_impl.c_decode_huffman_slow[0].v_table_entry = v_table_entry;
self->private_impl.c_decode_huffman_slow[0].v_table_entry_n_bits =
v_table_entry_n_bits;
self->private_impl.c_decode_huffman_slow[0].v_lmask = v_lmask;
self->private_impl.c_decode_huffman_slow[0].v_dmask = v_dmask;
self->private_impl.c_decode_huffman_slow[0].v_redir_top = v_redir_top;
self->private_impl.c_decode_huffman_slow[0].v_redir_mask = v_redir_mask;
self->private_impl.c_decode_huffman_slow[0].v_length = v_length;
self->private_impl.c_decode_huffman_slow[0].v_dist_minus_1 = v_dist_minus_1;
self->private_impl.c_decode_huffman_slow[0].v_n_copied = v_n_copied;
self->private_impl.c_decode_huffman_slow[0].v_hlen = v_hlen;
self->private_impl.c_decode_huffman_slow[0].v_hdist = v_hdist;
goto exit;
exit:
if (a_dst.private_impl.buf) {
a_dst.private_impl.buf->wi = ioptr_dst - a_dst.private_impl.buf->ptr;
}
if (a_src.private_impl.buf) {
a_src.private_impl.buf->ri = ioptr_src - a_src.private_impl.buf->ptr;
}
return status;
short_read_src:
if (wuffs_base__io_reader__is_eof(a_src)) {
status = WUFFS_DEFLATE__ERROR_UNEXPECTED_EOF;
goto exit;
}
status = WUFFS_DEFLATE__SUSPENSION_SHORT_READ;
goto suspend;
}