blob: 1cb3e28c3dfddbf5ff455af04baffb71cb37c75a [file] [log] [blame]
#ifndef WUFFS_INCLUDE_GUARD
#define WUFFS_INCLUDE_GUARD
// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
//
// To use that single file as a "foo.c"-like implementation, instead of a
// "foo.h"-like header, #define WUFFS_IMPLEMENTATION before #include'ing or
// compiling it.
// 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>
// GCC does not warn for unused *static inline* functions, but clang does.
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// 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.
#ifdef __WORDSIZE
#if (__WORDSIZE != 32) && (__WORDSIZE != 64)
#error "Wuffs requires a word size of either 32 or 64 bits"
#endif
#endif
// WUFFS_VERSION is the major.minor.patch version, as per https://semver.org/,
// as a uint64_t. The major number is the high 32 bits. The minor number is the
// middle 16 bits. The patch number is the low 16 bits. The pre-release label
// and build metadata are part of the string representation (such as
// "1.2.3-beta+456.20181231") but not the uint64_t representation.
//
// WUFFS_VERSION_PRE_RELEASE_LABEL (such as "", "beta" or "rc.1") being
// non-empty denotes a developer preview, not a release version, and has no
// backwards or forwards compatibility guarantees.
//
// WUFFS_VERSION_BUILD_METADATA_XXX, if non-zero, are the number of commits and
// the last commit date in the repository used to build this library. Within
// each major.minor branch, the commit count should increase monotonically.
//
// !! Some code generation programs can override WUFFS_VERSION.
#define WUFFS_VERSION ((uint64_t)0)
#define WUFFS_VERSION_MAJOR ((uint64_t)0)
#define WUFFS_VERSION_MINOR ((uint64_t)0)
#define WUFFS_VERSION_PATCH ((uint64_t)0)
#define WUFFS_VERSION_PRE_RELEASE_LABEL "work.in.progress"
#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 0
#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 0
#define WUFFS_VERSION_STRING "0.0.0+0.00000000"
// Define WUFFS_CONFIG__STATIC_FUNCTIONS to make all of Wuffs' functions have
// static storage. The motivation is discussed in the "ALLOW STATIC
// IMPLEMENTATION" section of
// https://raw.githubusercontent.com/nothings/stb/master/docs/stb_howto.txt
#ifdef WUFFS_CONFIG__STATIC_FUNCTIONS
#define WUFFS_BASE__MAYBE_STATIC static
#else
#define WUFFS_BASE__MAYBE_STATIC
#endif
#if defined(__clang__)
#define WUFFS_BASE__POTENTIALLY_UNUSED_FIELD __attribute__((unused))
#else
#define WUFFS_BASE__POTENTIALLY_UNUSED_FIELD
#endif
// Clang also defines "__GNUC__".
#if defined(__GNUC__)
#define WUFFS_BASE__POTENTIALLY_UNUSED __attribute__((unused))
#define WUFFS_BASE__WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define WUFFS_BASE__POTENTIALLY_UNUSED
#define WUFFS_BASE__WARN_UNUSED_RESULT
#endif
// Flags for wuffs_foo__bar__initialize functions.
#define WUFFS_INITIALIZE__DEFAULT_OPTIONS ((uint32_t)0x00000000)
// WUFFS_INITIALIZE__ALREADY_ZEROED means that the "self" receiver struct value
// has already been set to all zeroes.
#define WUFFS_INITIALIZE__ALREADY_ZEROED ((uint32_t)0x00000001)
// WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED means that, absent
// WUFFS_INITIALIZE__ALREADY_ZEROED, only some of the "self" receiver struct
// value will be set to all zeroes. Internal buffers, which tend to be a large
// proportion of the struct's size, will be left uninitialized. Internal means
// that the buffer is contained by the receiver struct, as opposed to being
// passed as a separately allocated "work buffer".
//
// With or without this bit set, the Wuffs compiler still enforces that no
// reads or writes will overflow internal buffers' bounds. Even with this bit
// set, the Wuffs standard library also considers reading from an uninitialized
// buffer to be a bug, and strives to never do so, but unlike buffer overflows,
// it is not a bug class that the Wuffs compiler eliminates.
//
// For those paranoid about security, leave this bit unset, so that
// wuffs_foo__bar__initialize will initialize the entire struct value to zeroes
// (unless WUFFS_INITIALIZE__ALREADY_ZEROED is set).
//
// Setting this bit gives a small absolute improvement on micro-benchmarks, but
// this can be a large relative effect, up to 2x faster, when the actual work
// to be done is also small, such as decompressing small input. See git commit
// 438fc105 "Move some struct fields to private_data" for some numbers and a
// discussion, noting that its commit message was written before this
// WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED option was defined.
#define WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED \
((uint32_t)0x00000002)
// --------
// 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 {
// private_impl is a placeholder field. It isn't explicitly used, except that
// without it, the sizeof a struct with no fields can differ across C/C++
// compilers, and it is undefined behavior in C99. For example, gcc says that
// the sizeof an empty struct is 0, and g++ says that it is 1. This leads to
// ABI incompatibility if a Wuffs .c file is processed by one compiler and
// its .h file with another compiler.
//
// Instead, we explicitly insert an otherwise unused field, so that the
// sizeof this struct is always 1.
uint8_t private_impl;
} wuffs_base__empty_struct;
static inline wuffs_base__empty_struct //
wuffs_base__make_empty_struct() {
wuffs_base__empty_struct ret;
ret.private_impl = 0;
return ret;
}
// wuffs_base__utility is a placeholder receiver type. It enables what Java
// calls static methods, as opposed to regular methods.
typedef struct {
// private_impl is a placeholder field. It isn't explicitly used, except that
// without it, the sizeof a struct with no fields can differ across C/C++
// compilers, and it is undefined behavior in C99. For example, gcc says that
// the sizeof an empty struct is 0, and g++ says that it is 1. This leads to
// ABI incompatibility if a Wuffs .c file is processed by one compiler and
// its .h file with another compiler.
//
// Instead, we explicitly insert an otherwise unused field, so that the
// sizeof this struct is always 1.
uint8_t private_impl;
} wuffs_base__utility;
// --------
// A status is either NULL (meaning OK) or a string message. That message is
// human-readable, for programmers, but it is not for end users. It is not
// localized, and does not contain additional contextual information such as a
// source filename.
//
// Status strings are statically allocated and should never be free'd. They can
// be compared by the == operator and not just by strcmp.
//
// Statuses come in four categories:
// - OK: the request was completed, successfully.
// - Warnings: the request was completed, unsuccessfully.
// - Suspensions: the request was not completed, but can be re-tried.
// - Errors: the request was not completed, permanently.
//
// When a function returns an incomplete status, a suspension means that that
// function should be called again within a new context, such as after flushing
// or re-filling an I/O buffer. An error means that an irrecoverable failure
// state was reached.
typedef const char* wuffs_base__status;
extern const char* wuffs_base__warning__end_of_data;
extern const char* wuffs_base__warning__metadata_reported;
extern const char* wuffs_base__suspension__short_read;
extern const char* wuffs_base__suspension__short_write;
extern const char* wuffs_base__error__bad_i_o_position;
extern const char* wuffs_base__error__bad_argument_length_too_short;
extern const char* wuffs_base__error__bad_argument;
extern const char* wuffs_base__error__bad_call_sequence;
extern const char* wuffs_base__error__bad_receiver;
extern const char* wuffs_base__error__bad_restart;
extern const char* wuffs_base__error__bad_sizeof_receiver;
extern const char* wuffs_base__error__bad_workbuf_length;
extern const char* wuffs_base__error__bad_wuffs_version;
extern const char* wuffs_base__error__cannot_return_a_suspension;
extern const char* wuffs_base__error__disabled_by_previous_error;
extern const char* wuffs_base__error__initialize_falsely_claimed_already_zeroed;
extern const char* wuffs_base__error__initialize_not_called;
extern const char* wuffs_base__error__interleaved_coroutine_calls;
extern const char* wuffs_base__error__not_enough_data;
extern const char* wuffs_base__error__too_much_data;
static inline bool //
wuffs_base__status__is_complete(wuffs_base__status z) {
return (z == NULL) || ((*z != '$') && (*z != '#'));
}
static inline bool //
wuffs_base__status__is_error(wuffs_base__status z) {
return z && (*z == '#');
}
static inline bool //
wuffs_base__status__is_ok(wuffs_base__status z) {
return z == NULL;
}
static inline bool //
wuffs_base__status__is_suspension(wuffs_base__status z) {
return z && (*z == '$');
}
static inline bool //
wuffs_base__status__is_warning(wuffs_base__status z) {
return z && (*z != '$') && (*z != '#');
}
// --------
// FourCC constants.
// International Color Consortium Profile.
#define WUFFS_BASE__FOURCC__ICCP 0x49434350
// Extensible Metadata Platform.
#define WUFFS_BASE__FOURCC__XMP 0x584D5020
// --------
// 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 int64_t wuffs_base__flicks;
#define WUFFS_BASE__FLICKS_PER_SECOND ((uint64_t)705600000)
#define WUFFS_BASE__FLICKS_PER_MILLISECOND ((uint64_t)705600)
// ---------------- Numeric Types
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 = (uint8_t)(x + y);
res |= (uint8_t)(-(res < x));
return res;
}
static inline uint8_t //
wuffs_base__u8__sat_sub(uint8_t x, uint8_t y) {
uint8_t res = (uint8_t)(x - y);
res &= (uint8_t)(-(res <= x));
return res;
}
static inline uint16_t //
wuffs_base__u16__sat_add(uint16_t x, uint16_t y) {
uint16_t res = (uint16_t)(x + y);
res |= (uint16_t)(-(res < x));
return res;
}
static inline uint16_t //
wuffs_base__u16__sat_sub(uint16_t x, uint16_t y) {
uint16_t res = (uint16_t)(x - y);
res &= (uint16_t)(-(res <= x));
return res;
}
static inline uint32_t //
wuffs_base__u32__sat_add(uint32_t x, uint32_t y) {
uint32_t res = (uint32_t)(x + y);
res |= (uint32_t)(-(res < x));
return res;
}
static inline uint32_t //
wuffs_base__u32__sat_sub(uint32_t x, uint32_t y) {
uint32_t res = (uint32_t)(x - y);
res &= (uint32_t)(-(res <= x));
return res;
}
static inline uint64_t //
wuffs_base__u64__sat_add(uint64_t x, uint64_t y) {
uint64_t res = (uint64_t)(x + y);
res |= (uint64_t)(-(res < x));
return res;
}
static inline uint64_t //
wuffs_base__u64__sat_sub(uint64_t x, uint64_t y) {
uint64_t res = (uint64_t)(x - y);
res &= (uint64_t)(-(res <= x));
return res;
}
// ---------------- Slices and Tables
// WUFFS_BASE__SLICE is a 1-dimensional buffer.
//
// len measures a number of elements, not necessarily a size in bytes.
//
// 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.
//
// width height, and stride measure a number of elements, not necessarily a
// size in bytes.
//
// 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;
static inline wuffs_base__slice_u8 //
wuffs_base__make_slice_u8(uint8_t* ptr, size_t len) {
wuffs_base__slice_u8 ret;
ret.ptr = ptr;
ret.len = len;
return ret;
}
static inline wuffs_base__slice_u16 //
wuffs_base__make_slice_u16(uint16_t* ptr, size_t len) {
wuffs_base__slice_u16 ret;
ret.ptr = ptr;
ret.len = len;
return ret;
}
static inline wuffs_base__slice_u32 //
wuffs_base__make_slice_u32(uint32_t* ptr, size_t len) {
wuffs_base__slice_u32 ret;
ret.ptr = ptr;
ret.len = len;
return ret;
}
static inline wuffs_base__slice_u64 //
wuffs_base__make_slice_u64(uint64_t* ptr, size_t len) {
wuffs_base__slice_u64 ret;
ret.ptr = ptr;
ret.len = len;
return ret;
}
static inline wuffs_base__slice_u8 //
wuffs_base__null_slice_u8() {
wuffs_base__slice_u8 ret;
ret.ptr = NULL;
ret.len = 0;
return ret;
}
static inline wuffs_base__table_u8 //
wuffs_base__null_table_u8() {
wuffs_base__table_u8 ret;
ret.ptr = NULL;
ret.width = 0;
ret.height = 0;
ret.stride = 0;
return ret;
}
// wuffs_base__slice_u8__subslice_i returns s[i:].
//
// It returns an empty slice if i is out of bounds.
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__make_slice_u8(s.ptr + i, s.len - i);
}
return wuffs_base__make_slice_u8(NULL, 0);
}
// wuffs_base__slice_u8__subslice_j returns s[:j].
//
// It returns an empty slice if j is out of bounds.
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__make_slice_u8(s.ptr, j);
}
return wuffs_base__make_slice_u8(NULL, 0);
}
// wuffs_base__slice_u8__subslice_ij returns s[i:j].
//
// It returns an empty slice if i or j is out of bounds.
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__make_slice_u8(s.ptr + i, j - i);
}
return wuffs_base__make_slice_u8(NULL, 0);
}
// ---------------- 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 wuffs_base__range_ii_u32__struct {
uint32_t min_incl;
uint32_t max_incl;
#ifdef __cplusplus
inline bool is_empty() const;
inline bool equals(wuffs_base__range_ii_u32__struct s) const;
inline wuffs_base__range_ii_u32__struct intersect(
wuffs_base__range_ii_u32__struct s) const;
inline wuffs_base__range_ii_u32__struct unite(
wuffs_base__range_ii_u32__struct s) const;
inline bool contains(uint32_t x) const;
inline bool contains_range(wuffs_base__range_ii_u32__struct s) const;
#endif // __cplusplus
} wuffs_base__range_ii_u32;
static inline wuffs_base__range_ii_u32 //
wuffs_base__make_range_ii_u32(uint32_t min_incl, uint32_t max_incl) {
wuffs_base__range_ii_u32 ret;
ret.min_incl = min_incl;
ret.max_incl = max_incl;
return ret;
}
static inline bool //
wuffs_base__range_ii_u32__is_empty(const wuffs_base__range_ii_u32* r) {
return r->min_incl > r->max_incl;
}
static inline bool //
wuffs_base__range_ii_u32__equals(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
(wuffs_base__range_ii_u32__is_empty(r) &&
wuffs_base__range_ii_u32__is_empty(&s));
}
static inline wuffs_base__range_ii_u32 //
wuffs_base__range_ii_u32__intersect(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
wuffs_base__range_ii_u32 t;
t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
t.max_incl = wuffs_base__u32__min(r->max_incl, s.max_incl);
return t;
}
static inline wuffs_base__range_ii_u32 //
wuffs_base__range_ii_u32__unite(const 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;
}
wuffs_base__range_ii_u32 t;
t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);
t.max_incl = wuffs_base__u32__max(r->max_incl, s.max_incl);
return t;
}
static inline bool //
wuffs_base__range_ii_u32__contains(const wuffs_base__range_ii_u32* r,
uint32_t x) {
return (r->min_incl <= x) && (x <= r->max_incl);
}
static inline bool //
wuffs_base__range_ii_u32__contains_range(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
return wuffs_base__range_ii_u32__equals(
&s, wuffs_base__range_ii_u32__intersect(r, s));
}
#ifdef __cplusplus
inline bool //
wuffs_base__range_ii_u32::is_empty() const {
return wuffs_base__range_ii_u32__is_empty(this);
}
inline bool //
wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__equals(this, s);
}
inline wuffs_base__range_ii_u32 //
wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__intersect(this, s);
}
inline wuffs_base__range_ii_u32 //
wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__unite(this, s);
}
inline bool //
wuffs_base__range_ii_u32::contains(uint32_t x) const {
return wuffs_base__range_ii_u32__contains(this, x);
}
inline bool //
wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__contains_range(this, s);
}
#endif // __cplusplus
// --------
typedef struct wuffs_base__range_ie_u32__struct {
uint32_t min_incl;
uint32_t max_excl;
#ifdef __cplusplus
inline bool is_empty() const;
inline bool equals(wuffs_base__range_ie_u32__struct s) const;
inline wuffs_base__range_ie_u32__struct intersect(
wuffs_base__range_ie_u32__struct s) const;
inline wuffs_base__range_ie_u32__struct unite(
wuffs_base__range_ie_u32__struct s) const;
inline bool contains(uint32_t x) const;
inline bool contains_range(wuffs_base__range_ie_u32__struct s) const;
inline uint32_t length() const;
#endif // __cplusplus
} wuffs_base__range_ie_u32;
static inline wuffs_base__range_ie_u32 //
wuffs_base__make_range_ie_u32(uint32_t min_incl, uint32_t max_excl) {
wuffs_base__range_ie_u32 ret;
ret.min_incl = min_incl;
ret.max_excl = max_excl;
return ret;
}
static inline bool //
wuffs_base__range_ie_u32__is_empty(const wuffs_base__range_ie_u32* r) {
return r->min_incl >= r->max_excl;
}
static inline bool //
wuffs_base__range_ie_u32__equals(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
(wuffs_base__range_ie_u32__is_empty(r) &&
wuffs_base__range_ie_u32__is_empty(&s));
}
static inline wuffs_base__range_ie_u32 //
wuffs_base__range_ie_u32__intersect(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
wuffs_base__range_ie_u32 t;
t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
t.max_excl = wuffs_base__u32__min(r->max_excl, s.max_excl);
return t;
}
static inline wuffs_base__range_ie_u32 //
wuffs_base__range_ie_u32__unite(const 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;
}
wuffs_base__range_ie_u32 t;
t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);
t.max_excl = wuffs_base__u32__max(r->max_excl, s.max_excl);
return t;
}
static inline bool //
wuffs_base__range_ie_u32__contains(const wuffs_base__range_ie_u32* r,
uint32_t x) {
return (r->min_incl <= x) && (x < r->max_excl);
}
static inline bool //
wuffs_base__range_ie_u32__contains_range(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
return wuffs_base__range_ie_u32__equals(
&s, wuffs_base__range_ie_u32__intersect(r, s));
}
static inline uint32_t //
wuffs_base__range_ie_u32__length(const wuffs_base__range_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl, r->min_incl);
}
#ifdef __cplusplus
inline bool //
wuffs_base__range_ie_u32::is_empty() const {
return wuffs_base__range_ie_u32__is_empty(this);
}
inline bool //
wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__equals(this, s);
}
inline wuffs_base__range_ie_u32 //
wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__intersect(this, s);
}
inline wuffs_base__range_ie_u32 //
wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__unite(this, s);
}
inline bool //
wuffs_base__range_ie_u32::contains(uint32_t x) const {
return wuffs_base__range_ie_u32__contains(this, x);
}
inline bool //
wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__contains_range(this, s);
}
inline uint32_t //
wuffs_base__range_ie_u32::length() const {
return wuffs_base__range_ie_u32__length(this);
}
#endif // __cplusplus
// --------
typedef struct wuffs_base__range_ii_u64__struct {
uint64_t min_incl;
uint64_t max_incl;
#ifdef __cplusplus
inline bool is_empty() const;
inline bool equals(wuffs_base__range_ii_u64__struct s) const;
inline wuffs_base__range_ii_u64__struct intersect(
wuffs_base__range_ii_u64__struct s) const;
inline wuffs_base__range_ii_u64__struct unite(
wuffs_base__range_ii_u64__struct s) const;
inline bool contains(uint64_t x) const;
inline bool contains_range(wuffs_base__range_ii_u64__struct s) const;
#endif // __cplusplus
} wuffs_base__range_ii_u64;
static inline wuffs_base__range_ii_u64 //
wuffs_base__make_range_ii_u64(uint64_t min_incl, uint64_t max_incl) {
wuffs_base__range_ii_u64 ret;
ret.min_incl = min_incl;
ret.max_incl = max_incl;
return ret;
}
static inline bool //
wuffs_base__range_ii_u64__is_empty(const wuffs_base__range_ii_u64* r) {
return r->min_incl > r->max_incl;
}
static inline bool //
wuffs_base__range_ii_u64__equals(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
(wuffs_base__range_ii_u64__is_empty(r) &&
wuffs_base__range_ii_u64__is_empty(&s));
}
static inline wuffs_base__range_ii_u64 //
wuffs_base__range_ii_u64__intersect(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
wuffs_base__range_ii_u64 t;
t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
t.max_incl = wuffs_base__u64__min(r->max_incl, s.max_incl);
return t;
}
static inline wuffs_base__range_ii_u64 //
wuffs_base__range_ii_u64__unite(const 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;
}
wuffs_base__range_ii_u64 t;
t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);
t.max_incl = wuffs_base__u64__max(r->max_incl, s.max_incl);
return t;
}
static inline bool //
wuffs_base__range_ii_u64__contains(const wuffs_base__range_ii_u64* r,
uint64_t x) {
return (r->min_incl <= x) && (x <= r->max_incl);
}
static inline bool //
wuffs_base__range_ii_u64__contains_range(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
return wuffs_base__range_ii_u64__equals(
&s, wuffs_base__range_ii_u64__intersect(r, s));
}
#ifdef __cplusplus
inline bool //
wuffs_base__range_ii_u64::is_empty() const {
return wuffs_base__range_ii_u64__is_empty(this);
}
inline bool //
wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__equals(this, s);
}
inline wuffs_base__range_ii_u64 //
wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__intersect(this, s);
}
inline wuffs_base__range_ii_u64 //
wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__unite(this, s);
}
inline bool //
wuffs_base__range_ii_u64::contains(uint64_t x) const {
return wuffs_base__range_ii_u64__contains(this, x);
}
inline bool //
wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__contains_range(this, s);
}
#endif // __cplusplus
// --------
typedef struct wuffs_base__range_ie_u64__struct {
uint64_t min_incl;
uint64_t max_excl;
#ifdef __cplusplus
inline bool is_empty() const;
inline bool equals(wuffs_base__range_ie_u64__struct s) const;
inline wuffs_base__range_ie_u64__struct intersect(
wuffs_base__range_ie_u64__struct s) const;
inline wuffs_base__range_ie_u64__struct unite(
wuffs_base__range_ie_u64__struct s) const;
inline bool contains(uint64_t x) const;
inline bool contains_range(wuffs_base__range_ie_u64__struct s) const;
inline uint64_t length() const;
#endif // __cplusplus
} wuffs_base__range_ie_u64;
static inline wuffs_base__range_ie_u64 //
wuffs_base__make_range_ie_u64(uint64_t min_incl, uint64_t max_excl) {
wuffs_base__range_ie_u64 ret;
ret.min_incl = min_incl;
ret.max_excl = max_excl;
return ret;
}
static inline bool //
wuffs_base__range_ie_u64__is_empty(const wuffs_base__range_ie_u64* r) {
return r->min_incl >= r->max_excl;
}
static inline bool //
wuffs_base__range_ie_u64__equals(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
(wuffs_base__range_ie_u64__is_empty(r) &&
wuffs_base__range_ie_u64__is_empty(&s));
}
static inline wuffs_base__range_ie_u64 //
wuffs_base__range_ie_u64__intersect(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
wuffs_base__range_ie_u64 t;
t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
t.max_excl = wuffs_base__u64__min(r->max_excl, s.max_excl);
return t;
}
static inline wuffs_base__range_ie_u64 //
wuffs_base__range_ie_u64__unite(const 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;
}
wuffs_base__range_ie_u64 t;
t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);
t.max_excl = wuffs_base__u64__max(r->max_excl, s.max_excl);
return t;
}
static inline bool //
wuffs_base__range_ie_u64__contains(const wuffs_base__range_ie_u64* r,
uint64_t x) {
return (r->min_incl <= x) && (x < r->max_excl);
}
static inline bool //
wuffs_base__range_ie_u64__contains_range(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
return wuffs_base__range_ie_u64__equals(
&s, wuffs_base__range_ie_u64__intersect(r, s));
}
static inline uint64_t //
wuffs_base__range_ie_u64__length(const wuffs_base__range_ie_u64* r) {
return wuffs_base__u64__sat_sub(r->max_excl, r->min_incl);
}
#ifdef __cplusplus
inline bool //
wuffs_base__range_ie_u64::is_empty() const {
return wuffs_base__range_ie_u64__is_empty(this);
}
inline bool //
wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__equals(this, s);
}
inline wuffs_base__range_ie_u64 //
wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__intersect(this, s);
}
inline wuffs_base__range_ie_u64 //
wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__unite(this, s);
}
inline bool //
wuffs_base__range_ie_u64::contains(uint64_t x) const {
return wuffs_base__range_ie_u64__contains(this, x);
}
inline bool //
wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__contains_range(this, s);
}
inline uint64_t //
wuffs_base__range_ie_u64::length() const {
return wuffs_base__range_ie_u64__length(this);
}
#endif // __cplusplus
// --------
// 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_incl_x <= x) && (x <= max_incl_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 wuffs_base__rect_ii_u32__struct {
uint32_t min_incl_x;
uint32_t min_incl_y;
uint32_t max_incl_x;
uint32_t max_incl_y;
#ifdef __cplusplus
inline bool is_empty() const;
inline bool equals(wuffs_base__rect_ii_u32__struct s) const;
inline wuffs_base__rect_ii_u32__struct intersect(
wuffs_base__rect_ii_u32__struct s) const;
inline wuffs_base__rect_ii_u32__struct unite(
wuffs_base__rect_ii_u32__struct s) const;
inline bool contains(uint32_t x, uint32_t y) const;
inline bool contains_rect(wuffs_base__rect_ii_u32__struct s) const;
#endif // __cplusplus
} wuffs_base__rect_ii_u32;
static inline wuffs_base__rect_ii_u32 //
wuffs_base__make_rect_ii_u32(uint32_t min_incl_x,
uint32_t min_incl_y,
uint32_t max_incl_x,
uint32_t max_incl_y) {
wuffs_base__rect_ii_u32 ret;
ret.min_incl_x = min_incl_x;
ret.min_incl_y = min_incl_y;
ret.max_incl_x = max_incl_x;
ret.max_incl_y = max_incl_y;
return ret;
}
static inline bool //
wuffs_base__rect_ii_u32__is_empty(const wuffs_base__rect_ii_u32* r) {
return (r->min_incl_x > r->max_incl_x) || (r->min_incl_y > r->max_incl_y);
}
static inline bool //
wuffs_base__rect_ii_u32__equals(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
r->max_incl_x == s.max_incl_x && r->max_incl_y == s.max_incl_y) ||
(wuffs_base__rect_ii_u32__is_empty(r) &&
wuffs_base__rect_ii_u32__is_empty(&s));
}
static inline wuffs_base__rect_ii_u32 //
wuffs_base__rect_ii_u32__intersect(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
wuffs_base__rect_ii_u32 t;
t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);
t.max_incl_x = wuffs_base__u32__min(r->max_incl_x, s.max_incl_x);
t.max_incl_y = wuffs_base__u32__min(r->max_incl_y, s.max_incl_y);
return t;
}
static inline wuffs_base__rect_ii_u32 //
wuffs_base__rect_ii_u32__unite(const 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;
}
wuffs_base__rect_ii_u32 t;
t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);
t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);
t.max_incl_x = wuffs_base__u32__max(r->max_incl_x, s.max_incl_x);
t.max_incl_y = wuffs_base__u32__max(r->max_incl_y, s.max_incl_y);
return t;
}
static inline bool //
wuffs_base__rect_ii_u32__contains(const wuffs_base__rect_ii_u32* r,
uint32_t x,
uint32_t y) {
return (r->min_incl_x <= x) && (x <= r->max_incl_x) && (r->min_incl_y <= y) &&
(y <= r->max_incl_y);
}
static inline bool //
wuffs_base__rect_ii_u32__contains_rect(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
return wuffs_base__rect_ii_u32__equals(
&s, wuffs_base__rect_ii_u32__intersect(r, s));
}
#ifdef __cplusplus
inline bool //
wuffs_base__rect_ii_u32::is_empty() const {
return wuffs_base__rect_ii_u32__is_empty(this);
}
inline bool //
wuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__equals(this, s);
}
inline wuffs_base__rect_ii_u32 //
wuffs_base__rect_ii_u32::intersect(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__intersect(this, s);
}
inline wuffs_base__rect_ii_u32 //
wuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__unite(this, s);
}
inline bool //
wuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) const {
return wuffs_base__rect_ii_u32__contains(this, x, y);
}
inline bool //
wuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__contains_rect(this, s);
}
#endif // __cplusplus
// --------
// 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_incl_x <= x) && (x < max_excl_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 wuffs_base__rect_ie_u32__struct {
uint32_t min_incl_x;
uint32_t min_incl_y;
uint32_t max_excl_x;
uint32_t max_excl_y;
#ifdef __cplusplus
inline bool is_empty() const;
inline bool equals(wuffs_base__rect_ie_u32__struct s) const;
inline wuffs_base__rect_ie_u32__struct intersect(
wuffs_base__rect_ie_u32__struct s) const;
inline wuffs_base__rect_ie_u32__struct unite(
wuffs_base__rect_ie_u32__struct s) const;
inline bool contains(uint32_t x, uint32_t y) const;
inline bool contains_rect(wuffs_base__rect_ie_u32__struct s) const;
inline uint32_t width() const;
inline uint32_t height() const;
#endif // __cplusplus
} wuffs_base__rect_ie_u32;
static inline wuffs_base__rect_ie_u32 //
wuffs_base__make_rect_ie_u32(uint32_t min_incl_x,
uint32_t min_incl_y,
uint32_t max_excl_x,
uint32_t max_excl_y) {
wuffs_base__rect_ie_u32 ret;
ret.min_incl_x = min_incl_x;
ret.min_incl_y = min_incl_y;
ret.max_excl_x = max_excl_x;
ret.max_excl_y = max_excl_y;
return ret;
}
static inline bool //
wuffs_base__rect_ie_u32__is_empty(const wuffs_base__rect_ie_u32* r) {
return (r->min_incl_x >= r->max_excl_x) || (r->min_incl_y >= r->max_excl_y);
}
static inline bool //
wuffs_base__rect_ie_u32__equals(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
r->max_excl_x == s.max_excl_x && r->max_excl_y == s.max_excl_y) ||
(wuffs_base__rect_ie_u32__is_empty(r) &&
wuffs_base__rect_ie_u32__is_empty(&s));
}
static inline wuffs_base__rect_ie_u32 //
wuffs_base__rect_ie_u32__intersect(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
wuffs_base__rect_ie_u32 t;
t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);
t.max_excl_x = wuffs_base__u32__min(r->max_excl_x, s.max_excl_x);
t.max_excl_y = wuffs_base__u32__min(r->max_excl_y, s.max_excl_y);
return t;
}
static inline wuffs_base__rect_ie_u32 //
wuffs_base__rect_ie_u32__unite(const 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;
}
wuffs_base__rect_ie_u32 t;
t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);
t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);
t.max_excl_x = wuffs_base__u32__max(r->max_excl_x, s.max_excl_x);
t.max_excl_y = wuffs_base__u32__max(r->max_excl_y, s.max_excl_y);
return t;
}
static inline bool //
wuffs_base__rect_ie_u32__contains(const wuffs_base__rect_ie_u32* r,
uint32_t x,
uint32_t y) {
return (r->min_incl_x <= x) && (x < r->max_excl_x) && (r->min_incl_y <= y) &&
(y < r->max_excl_y);
}
static inline bool //
wuffs_base__rect_ie_u32__contains_rect(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
return wuffs_base__rect_ie_u32__equals(
&s, wuffs_base__rect_ie_u32__intersect(r, s));
}
static inline uint32_t //
wuffs_base__rect_ie_u32__width(const wuffs_base__rect_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl_x, r->min_incl_x);
}
static inline uint32_t //
wuffs_base__rect_ie_u32__height(const wuffs_base__rect_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl_y, r->min_incl_y);
}
#ifdef __cplusplus
inline bool //
wuffs_base__rect_ie_u32::is_empty() const {
return wuffs_base__rect_ie_u32__is_empty(this);
}
inline bool //
wuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__equals(this, s);
}
inline wuffs_base__rect_ie_u32 //
wuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__intersect(this, s);
}
inline wuffs_base__rect_ie_u32 //
wuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__unite(this, s);
}
inline bool //
wuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) const {
return wuffs_base__rect_ie_u32__contains(this, x, y);
}
inline bool //
wuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__contains_rect(this, s);
}
inline uint32_t //
wuffs_base__rect_ie_u32::width() const {
return wuffs_base__rect_ie_u32__width(this);
}
inline uint32_t //
wuffs_base__rect_ie_u32::height() const {
return wuffs_base__rect_ie_u32__height(this);
}
#endif // __cplusplus
// ---------------- I/O
struct wuffs_base__io_buffer__struct;
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 {
struct wuffs_base__io_buffer__struct* 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* mark;
uint8_t* limit;
} 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 {
struct wuffs_base__io_buffer__struct* 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* mark;
uint8_t* limit;
} private_impl;
} wuffs_base__io_writer;
// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's
// data.
typedef struct {
size_t wi; // Write index. Invariant: wi <= len.
size_t ri; // Read index. Invariant: ri <= wi.
uint64_t pos; // Position of the buffer start relative to the stream start.
bool closed; // No further writes are expected.
} wuffs_base__io_buffer_meta;
// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length) plus
// additional metadata.
//
// A value with all fields zero is a valid, empty buffer.
typedef struct wuffs_base__io_buffer__struct {
wuffs_base__slice_u8 data;
wuffs_base__io_buffer_meta meta;
#ifdef __cplusplus
inline void compact();
inline wuffs_base__io_reader reader();
inline wuffs_base__io_writer writer();
inline uint64_t reader_available() const;
inline uint64_t reader_io_position() const;
inline uint64_t writer_available() const;
inline uint64_t writer_io_position() const;
#endif // __cplusplus
} wuffs_base__io_buffer;
static inline wuffs_base__io_buffer //
wuffs_base__make_io_buffer(wuffs_base__slice_u8 data,
wuffs_base__io_buffer_meta meta) {
wuffs_base__io_buffer ret;
ret.data = data;
ret.meta = meta;
return ret;
}
static inline wuffs_base__io_buffer_meta //
wuffs_base__make_io_buffer_meta(size_t wi,
size_t ri,
uint64_t pos,
bool closed) {
wuffs_base__io_buffer_meta ret;
ret.wi = wi;
ret.ri = ri;
ret.pos = pos;
ret.closed = closed;
return ret;
}
static inline wuffs_base__io_buffer //
wuffs_base__null_io_buffer() {
wuffs_base__io_buffer ret;
ret.data.ptr = NULL;
ret.data.len = 0;
ret.meta.wi = 0;
ret.meta.ri = 0;
ret.meta.pos = 0;
ret.meta.closed = false;
return ret;
}
static inline wuffs_base__io_buffer_meta //
wuffs_base__null_io_buffer_meta() {
wuffs_base__io_buffer_meta ret;
ret.wi = 0;
ret.ri = 0;
ret.pos = 0;
ret.closed = false;
return ret;
}
static inline wuffs_base__io_reader //
wuffs_base__null_io_reader() {
wuffs_base__io_reader ret;
ret.private_impl.buf = NULL;
ret.private_impl.mark = NULL;
ret.private_impl.limit = NULL;
return ret;
}
static inline wuffs_base__io_writer //
wuffs_base__null_io_writer() {
wuffs_base__io_writer ret;
ret.private_impl.buf = NULL;
ret.private_impl.mark = NULL;
ret.private_impl.limit = NULL;
return ret;
}
// wuffs_base__io_buffer__compact moves any written but unread bytes to the
// start of the buffer.
static inline void //
wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
if (!buf || (buf->meta.ri == 0)) {
return;
}
buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
size_t n = buf->meta.wi - buf->meta.ri;
if (n != 0) {
memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);
}
buf->meta.wi = n;
buf->meta.ri = 0;
}
static inline wuffs_base__io_reader //
wuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret;
ret.private_impl.buf = buf;
ret.private_impl.mark = NULL;
ret.private_impl.limit = NULL;
return ret;
}
static inline wuffs_base__io_writer //
wuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {
wuffs_base__io_writer ret;
ret.private_impl.buf = buf;
ret.private_impl.mark = NULL;
ret.private_impl.limit = NULL;
return ret;
}
static inline uint64_t //
wuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {
return buf ? buf->meta.wi - buf->meta.ri : 0;
}
static inline uint64_t //
wuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {
return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
}
static inline uint64_t //
wuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {
return buf ? buf->data.len - buf->meta.wi : 0;
}
static inline uint64_t //
wuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {
return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
}
#ifdef __cplusplus
inline void //
wuffs_base__io_buffer__struct::compact() {
wuffs_base__io_buffer__compact(this);
}
inline wuffs_base__io_reader //
wuffs_base__io_buffer__struct::reader() {
return wuffs_base__io_buffer__reader(this);
}
inline wuffs_base__io_writer //
wuffs_base__io_buffer__struct::writer() {
return wuffs_base__io_buffer__writer(this);
}
inline uint64_t //
wuffs_base__io_buffer__struct::reader_available() const {
return wuffs_base__io_buffer__reader_available(this);
}
inline uint64_t //
wuffs_base__io_buffer__struct::reader_io_position() const {
return wuffs_base__io_buffer__reader_io_position(this);
}
inline uint64_t //
wuffs_base__io_buffer__struct::writer_available() const {
return wuffs_base__io_buffer__writer_available(this);
}
inline uint64_t //
wuffs_base__io_buffer__struct::writer_io_position() const {
return wuffs_base__io_buffer__writer_io_position(this);
}
#endif // __cplusplus
// ---------------- Memory Allocation
// The memory allocation related functions in this section aren't used by Wuffs
// per se, but they may be helpful to the code that uses Wuffs.
// wuffs_base__malloc_slice_uxx wraps calling a malloc-like function, except
// that it takes a uint64_t number of elements instead of a size_t size in
// bytes, and it returns a slice (a pointer and a length) instead of just a
// pointer.
//
// You can pass the C stdlib's malloc as the malloc_func.
//
// It returns an empty slice (containing a NULL ptr field) if (num_uxx *
// sizeof(uintxx_t)) would overflow SIZE_MAX.
static inline wuffs_base__slice_u8 //
wuffs_base__malloc_slice_u8(void* (*malloc_func)(size_t), uint64_t num_u8) {
if (malloc_func && (num_u8 <= (SIZE_MAX / sizeof(uint8_t)))) {
void* p = (*malloc_func)(num_u8 * sizeof(uint8_t));
if (p) {
return wuffs_base__make_slice_u8((uint8_t*)(p), num_u8);
}
}
return wuffs_base__make_slice_u8(NULL, 0);
}
static inline wuffs_base__slice_u16 //
wuffs_base__malloc_slice_u16(void* (*malloc_func)(size_t), uint64_t num_u16) {
if (malloc_func && (num_u16 <= (SIZE_MAX / sizeof(uint16_t)))) {
void* p = (*malloc_func)(num_u16 * sizeof(uint16_t));
if (p) {
return wuffs_base__make_slice_u16((uint16_t*)(p), num_u16);
}
}
return wuffs_base__make_slice_u16(NULL, 0);
}
static inline wuffs_base__slice_u32 //
wuffs_base__malloc_slice_u32(void* (*malloc_func)(size_t), uint64_t num_u32) {
if (malloc_func && (num_u32 <= (SIZE_MAX / sizeof(uint32_t)))) {
void* p = (*malloc_func)(num_u32 * sizeof(uint32_t));
if (p) {
return wuffs_base__make_slice_u32((uint32_t*)(p), num_u32);
}
}
return wuffs_base__make_slice_u32(NULL, 0);
}
static inline wuffs_base__slice_u64 //
wuffs_base__malloc_slice_u64(void* (*malloc_func)(size_t), uint64_t num_u64) {
if (malloc_func && (num_u64 <= (SIZE_MAX / sizeof(uint64_t)))) {
void* p = (*malloc_func)(num_u64 * sizeof(uint64_t));
if (p) {
return wuffs_base__make_slice_u64((uint64_t*)(p), num_u64);
}
}
return wuffs_base__make_slice_u64(NULL, 0);
}
// ---------------- Images
// wuffs_base__color_u32_argb_premul is an 8 bit per channel premultiplied
// Alpha, Red, Green, Blue color, as a uint32_t value. It is in word order, not
// byte order: its value is always 0xAARRGGBB, regardless of endianness.
typedef uint32_t wuffs_base__color_u32_argb_premul;
// --------
// 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).
// - bit 27 is reserved.
// - bits 26 .. 24 encodes transparency.
// - bits 23 .. 21 are reserved.
// - bit 20 indicates big-endian/MSB-first (as opposed to little/LSB).
// - bit 19 indicates floating point (as opposed to integer).
// - bit 18 indicates palette-indexed. The number-of-planes (the next
// field) will be zero, as the format is considered packed,
// but the 8-bit N-BGRA color data is stored in plane 3.
// - bits 17 .. 16 are the number of planes, minus 1. Zero means packed.
// - 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 YCbCr 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 8 bits per
// channel non-alpha-premultiplied BGRA color data. There is only 1 plane (for
// the index), as the format is considered packed. Plane 0 holds the per-pixel
// indices. Plane 3 is re-purposed to hold the per-index colors.
//
// The color field is encoded in 3 bits:
// - 0 means A (Alpha).
// - 1 means Y or YA (Gray, Alpha).
// - 2 means YCbCr or YCbCrA (Luma, Chroma-blue, Chroma-red, Alpha).
// - 3 means YCoCg or YCoCgA (Luma, Chroma-orange, Chroma-green, Alpha).
// - 4 means BGR, BGRX or BGRA (Blue, Green, Red, X-padding or Alpha).
// - 5 means RGB, RGBX or RGBA (Red, Green, Blue, X-padding or Alpha).
// - 6 means CMY or CMYK (Cyan, Magenta, Yellow, Black).
// - all other values are reserved.
//
// In Wuffs, channels are given in memory order (also known as byte 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 (3 bits) distinguishes them:
// - 0 means fully opaque, no extra channels
// - 1 means fully opaque, one extra channel (X or K, padding or black).
// - 5 means one extra alpha channel, other channels are non-premultiplied.
// - 6 means one extra alpha channel, other channels are premultiplied.
// - 7 means one extra alpha channel, binary alpha.
// - all other values are reserved.
//
// Binary alpha means that if a color is not completely opaque, it is
// completely transparent black. As a source pixel format, it can therefore be
// treated as either non-premultiplied or 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 0x5510BBBB 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 0x40000565 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
// (0x40000565) 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 (0x40000565)
// 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)0x15000008)
#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL \
((wuffs_base__pixel_format)0x16000008)
#define WUFFS_BASE__PIXEL_FORMAT__YCBCR ((wuffs_base__pixel_format)0x20020888)
#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK ((wuffs_base__pixel_format)0x21038888)
#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL \
((wuffs_base__pixel_format)0x25038888)
#define WUFFS_BASE__PIXEL_FORMAT__YCOCG ((wuffs_base__pixel_format)0x30020888)
#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK ((wuffs_base__pixel_format)0x31038888)
#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL \
((wuffs_base__pixel_format)0x35038888)
#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL \
((wuffs_base__pixel_format)0x45040008)
#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL \
((wuffs_base__pixel_format)0x46040008)
#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY \
((wuffs_base__pixel_format)0x47040008)
#define WUFFS_BASE__PIXEL_FORMAT__BGR ((wuffs_base__pixel_format)0x40000888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRX ((wuffs_base__pixel_format)0x41008888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL \
((wuffs_base__pixel_format)0x45008888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL \
((wuffs_base__pixel_format)0x46008888)
#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY \
((wuffs_base__pixel_format)0x47008888)
#define WUFFS_BASE__PIXEL_FORMAT__RGB ((wuffs_base__pixel_format)0x50000888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBX ((wuffs_base__pixel_format)0x51008888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL \
((wuffs_base__pixel_format)0x55008888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL \
((wuffs_base__pixel_format)0x56008888)
#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY \
((wuffs_base__pixel_format)0x57008888)
#define WUFFS_BASE__PIXEL_FORMAT__CMY ((wuffs_base__pixel_format)0x60020888)
#define WUFFS_BASE__PIXEL_FORMAT__CMYK ((wuffs_base__pixel_format)0x61038888)
extern const uint32_t wuffs_base__pixel_format__bits_per_channel[16];
static inline bool //
wuffs_base__pixel_format__is_valid(wuffs_base__pixel_format f) {
return f != 0;
}
// wuffs_base__pixel_format__bits_per_pixel returns, for packed pixel formats,
// the number of bits per pixel. It returns 0 for planar pixel formats.
static inline uint32_t //
wuffs_base__pixel_format__bits_per_pixel(wuffs_base__pixel_format f) {
if (((f >> 16) & 0x03) != 0) {
return 0;
}
return wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 0)] +
wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 4)] +
wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 8)] +
wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 12)];
}
static inline bool //
wuffs_base__pixel_format__is_indexed(wuffs_base__pixel_format f) {
return (f >> 18) & 0x01;
}
static inline bool //
wuffs_base__pixel_format__is_packed(wuffs_base__pixel_format f) {
return ((f >> 16) & 0x03) == 0;
}
static inline bool //
wuffs_base__pixel_format__is_planar(wuffs_base__pixel_format f) {
return ((f >> 16) & 0x03) != 0;
}
static inline uint32_t //
wuffs_base__pixel_format__num_planes(wuffs_base__pixel_format f) {
return ((f >> 16) & 0x03) + 1;
}
#define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4
#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0
#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3
// --------
// 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 YCbCr pixel format with 4:2:2 subsampling.
// For the luma (Y) channel, there is one sample for every pixel, but for the
// chroma (Cb, Cr) 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;
} private_impl;
#ifdef __cplusplus
inline void set(wuffs_base__pixel_format pixfmt,
wuffs_base__pixel_subsampling pixsub,
uint32_t width,
uint32_t height);
inline void invalidate();
inline bool is_valid() const;
inline wuffs_base__pixel_format pixel_format() const;
inline wuffs_base__pixel_subsampling pixel_subsampling() const;
inline wuffs_base__rect_ie_u32 bounds() const;
inline uint32_t width() const;
inline uint32_t height() const;
inline uint64_t pixbuf_len() const;
#endif // __cplusplus
} wuffs_base__pixel_config;
static inline wuffs_base__pixel_config //
wuffs_base__null_pixel_config() {
wuffs_base__pixel_config ret;
ret.private_impl.pixfmt = 0;
ret.private_impl.pixsub = 0;
ret.private_impl.width = 0;
ret.private_impl.height = 0;
return ret;
}
// TODO: Should this function return bool? An error type?
static inline void //
wuffs_base__pixel_config__set(wuffs_base__pixel_config* c,
wuffs_base__pixel_format pixfmt,
wuffs_base__pixel_subsampling pixsub,
uint32_t width,
uint32_t height) {
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;
return;
}
}
c->private_impl.pixfmt = 0;
c->private_impl.pixsub = 0;
c->private_impl.width = 0;
c->private_impl.height = 0;
}
static inline void //
wuffs_base__pixel_config__invalidate(wuffs_base__pixel_config* c) {
if (c) {
c->private_impl.pixfmt = 0;
c->private_impl.pixsub = 0;
c->private_impl.width = 0;
c->private_impl.height = 0;
}
}
static inline bool //
wuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) {
return c && c->private_impl.pixfmt;
}
static inline wuffs_base__pixel_format //
wuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.pixfmt : 0;
}
static inline wuffs_base__pixel_subsampling //
wuffs_base__pixel_config__pixel_subsampling(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.pixsub : 0;
}
static inline wuffs_base__rect_ie_u32 //
wuffs_base__pixel_config__bounds(const wuffs_base__pixel_config* c) {
if (c) {
wuffs_base__rect_ie_u32 ret;
ret.min_incl_x = 0;
ret.min_incl_y = 0;
ret.max_excl_x = c->private_impl.width;
ret.max_excl_y = c->private_impl.height;
return ret;
}
wuffs_base__rect_ie_u32 ret;
ret.min_incl_x = 0;
ret.min_incl_y = 0;
ret.max_excl_x = 0;
ret.max_excl_y = 0;
return ret;
}
static inline uint32_t //
wuffs_base__pixel_config__width(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.width : 0;
}
static inline uint32_t //
wuffs_base__pixel_config__height(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.height : 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 uint64_t //
wuffs_base__pixel_config__pixbuf_len(const wuffs_base__pixel_config* c) {
if (!c) {
return 0;
}
if (wuffs_base__pixel_format__is_planar(c->private_impl.pixfmt)) {
// TODO: support planar pixel formats, concious of pixel subsampling.
return 0;
}
uint32_t bits_per_pixel =
wuffs_base__pixel_format__bits_per_pixel(c->private_impl.pixfmt);
if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
// TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
return 0;
}
uint64_t bytes_per_pixel = bits_per_pixel / 8;
uint64_t n =
((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);
if (n > (UINT64_MAX / bytes_per_pixel)) {
return 0;
}
n *= bytes_per_pixel;
if (wuffs_base__pixel_format__is_indexed(c->private_impl.pixfmt)) {
if (n > (UINT64_MAX - 1024)) {
return 0;
}
n += 1024;
}
return n;
}
#ifdef __cplusplus
inline void //
wuffs_base__pixel_config::set(wuffs_base__pixel_format pixfmt,
wuffs_base__pixel_subsampling pixsub,
uint32_t width,
uint32_t height) {
wuffs_base__pixel_config__set(this, pixfmt, pixsub, width, height);
}
inline void //
wuffs_base__pixel_config::invalidate() {
wuffs_base__pixel_config__invalidate(this);
}
inline bool //
wuffs_base__pixel_config::is_valid() const {
return wuffs_base__pixel_config__is_valid(this);
}
inline wuffs_base__pixel_format //
wuffs_base__pixel_config::pixel_format() const {
return wuffs_base__pixel_config__pixel_format(this);
}
inline wuffs_base__pixel_subsampling //
wuffs_base__pixel_config::pixel_subsampling() const {
return wuffs_base__pixel_config__pixel_subsampling(this);
}
inline wuffs_base__rect_ie_u32 //
wuffs_base__pixel_config::bounds() const {
return wuffs_base__pixel_config__bounds(this);
}
inline uint32_t //
wuffs_base__pixel_config::width() const {
return wuffs_base__pixel_config__width(this);
}
inline uint32_t //
wuffs_base__pixel_config::height() const {
return wuffs_base__pixel_config__height(this);
}
inline uint64_t //
wuffs_base__pixel_config::pixbuf_len() const {
return wuffs_base__pixel_config__pixbuf_len(this);
}
#endif // __cplusplus
// --------
typedef struct {
wuffs_base__pixel_config pixcfg;
// Do not access the private_impl's fields directly. There is no API/ABI
// compatibility or safety guarantee if you do so.
struct {
uint64_t first_frame_io_position;
bool first_frame_is_opaque;
wuffs_base__color_u32_argb_premul background_color;
} private_impl;
#ifdef __cplusplus
inline void set(wuffs_base__pixel_format pixfmt,
wuffs_base__pixel_subsampling pixsub,
uint32_t width,
uint32_t height,
uint64_t first_frame_io_position,
bool first_frame_is_opaque,
wuffs_base__color_u32_argb_premul background_color);
inline void invalidate();
inline bool is_valid() const;
inline uint64_t first_frame_io_position() const;
inline bool first_frame_is_opaque() const;
inline wuffs_base__color_u32_argb_premul background_color() const;
#endif // __cplusplus
} wuffs_base__image_config;
static inline wuffs_base__image_config //
wuffs_base__null_image_config() {
wuffs_base__image_config ret;
ret.pixcfg = wuffs_base__null_pixel_config();
ret.private_impl.first_frame_io_position = 0;
ret.private_impl.first_frame_is_opaque = false;
return ret;
}
// TODO: Should this function return bool? An error type?
static inline void //
wuffs_base__image_config__set(
wuffs_base__image_config* c,
wuffs_base__pixel_format pixfmt,
wuffs_base__pixel_subsampling pixsub,
uint32_t width,
uint32_t height,
uint64_t first_frame_io_position,
bool first_frame_is_opaque,
wuffs_base__color_u32_argb_premul background_color) {
if (!c) {
return;
}
if (wuffs_base__pixel_format__is_valid(pixfmt)) {
c->pixcfg.private_impl.pixfmt = pixfmt;
c->pixcfg.private_impl.pixsub = pixsub;
c->pixcfg.private_impl.width = width;
c->pixcfg.private_impl.height = height;
c->private_impl.first_frame_io_position = first_frame_io_position;
c->private_impl.first_frame_is_opaque = first_frame_is_opaque;
c->private_impl.background_color = background_color;
return;
}
c->pixcfg.private_impl.pixfmt = 0;
c->pixcfg.private_impl.pixsub = 0;
c->pixcfg.private_impl.width = 0;
c->pixcfg.private_impl.height = 0;
c->private_impl.first_frame_io_position = 0;
c->private_impl.first_frame_is_opaque = 0;
c->private_impl.background_color = 0;
}
static inline void //
wuffs_base__image_config__invalidate(wuffs_base__image_config* c) {
if (c) {
c->pixcfg.private_impl.pixfmt = 0;
c->pixcfg.private_impl.pixsub = 0;
c->pixcfg.private_impl.width = 0;
c->pixcfg.private_impl.height = 0;
c->private_impl.first_frame_io_position = 0;
c->private_impl.first_frame_is_opaque = 0;
c->private_impl.background_color = 0;
}
}
static inline bool //
wuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {
return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));
}
static inline uint64_t //
wuffs_base__image_config__first_frame_io_position(
const wuffs_base__image_config* c) {
return c ? c->private_impl.first_frame_io_position : 0;
}
static inline bool //
wuffs_base__image_config__first_frame_is_opaque(
const wuffs_base__image_config* c) {
return c ? c->private_impl.first_frame_is_opaque : false;
}
static inline wuffs_base__color_u32_argb_premul //
wuffs_base__image_config__background_color(const wuffs_base__image_config* c) {
return c ? c->private_impl.background_color : 0;
}
#ifdef __cplusplus
inline void //
wuffs_base__image_config::set(
wuffs_base__pixel_format pixfmt,
wuffs_base__pixel_subsampling pixsub,
uint32_t width,
uint32_t height,
uint64_t first_frame_io_position,
bool first_frame_is_opaque,
wuffs_base__color_u32_argb_premul background_color) {
wuffs_base__image_config__set(this, pixfmt, pixsub, width, height,
first_frame_io_position, first_frame_is_opaque,
background_color);
}
inline void //
wuffs_base__image_config::invalidate() {
wuffs_base__image_config__invalidate(this);
}
inline bool //
wuffs_base__image_config::is_valid() const {
return wuffs_base__image_config__is_valid(this);
}
inline uint64_t //
wuffs_base__image_config::first_frame_io_position() const {
return wuffs_base__image_config__first_frame_io_position(this);
}
inline bool //
wuffs_base__image_config::first_frame_is_opaque() const {
return wuffs_base__image_config__first_frame_is_opaque(this);
}
inline wuffs_base__color_u32_argb_premul //
wuffs_base__image_config::background_color() const {
return wuffs_base__image_config__background_color(this);
}
#endif // __cplusplus
// --------
// wuffs_base__animation_blend encodes, for an animated image, how to blend the
// transparent pixels of this frame with the existing canvas. In Porter-Duff
// compositing operator terminology:
// - 0 means the frame may be transparent, and should be blended "src over
// dst", also known as just "over".
// - 1 means the frame may be transparent, and should be blended "src".
// - 2 means the frame is completely opaque, so that "src over dst" and "src"
// are equivalent.
//
// These semantics are conservative. It is valid for a completely opaque frame
// to have a blend value other than 2.
typedef uint8_t wuffs_base__animation_blend;
#define WUFFS_BASE__ANIMATION_BLEND__SRC_OVER_DST \
((wuffs_base__animation_blend)0)
#define WUFFS_BASE__ANIMATION_BLEND__SRC ((wuffs_base__animation_blend)1)
#define WUFFS_BASE__ANIMATION_BLEND__OPAQUE ((wuffs_base__animation_blend)2)
// --------
// wuffs_base__animation_disposal encodes, for an animated image, how to
// dispose of a frame after displaying it:
// - None means to draw the next frame on top of this one.
// - Restore Background means to clear the frame's dirty rectangle to "the
// background color" (in practice, this means transparent black) before
// drawing the next frame.
// - Restore Previous means to undo the current frame, so that the next frame
// is drawn on top of the previous one.
typedef uint8_t wuffs_base__animation_disposal;
#define WUFFS_BASE__ANIMATION_DISPOSAL__NONE ((wuffs_base__animation_disposal)0)
#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND \
((wuffs_base__animation_disposal)1)
#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS \
((wuffs_base__animation_disposal)2)
// --------
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__rect_ie_u32 bounds;
wuffs_base__flicks duration;
uint64_t index;
uint64_t io_position;
wuffs_base__animation_blend blend;
wuffs_base__animation_disposal disposal;
} private_impl;
#ifdef __cplusplus
inline void update(wuffs_base__rect_ie_u32 bounds,
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal);
inline wuffs_base__rect_ie_u32 bounds() const;
inline uint32_t width() const;
inline uint32_t height() const;
inline wuffs_base__flicks duration() const;
inline uint64_t index() const;
inline uint64_t io_position() const;
inline wuffs_base__animation_blend blend() const;
inline wuffs_base__animation_disposal disposal() const;
#endif // __cplusplus
} wuffs_base__frame_config;
static inline wuffs_base__frame_config //
wuffs_base__null_frame_config() {
wuffs_base__frame_config ret;
ret.private_impl.bounds = wuffs_base__make_rect_ie_u32(0, 0, 0, 0);
ret.private_impl.duration = 0;
ret.private_impl.index = 0;
ret.private_impl.io_position = 0;
ret.private_impl.blend = 0;
ret.private_impl.disposal = 0;
return ret;
}
static inline void //
wuffs_base__frame_config__update(wuffs_base__frame_config* c,
wuffs_base__rect_ie_u32 bounds,
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal) {
if (!c) {
return;
}
c->private_impl.bounds = bounds;
c->private_impl.duration = duration;
c->private_impl.index = index;
c->private_impl.io_position = io_position;
c->private_impl.blend = blend;
c->private_impl.disposal = disposal;
}
static inline wuffs_base__rect_ie_u32 //
wuffs_base__frame_config__bounds(const wuffs_base__frame_config* c) {
if (c) {
return c->private_impl.bounds;
}
wuffs_base__rect_ie_u32 ret;
ret.min_incl_x = 0;
ret.min_incl_y = 0;
ret.max_excl_x = 0;
ret.max_excl_y = 0;
return ret;
}
static inline uint32_t //
wuffs_base__frame_config__width(const wuffs_base__frame_config* c) {
return c ? wuffs_base__rect_ie_u32__width(&c->private_impl.bounds) : 0;
}
static inline uint32_t //
wuffs_base__frame_config__height(const wuffs_base__frame_config* c) {
return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;
}
// wuffs_base__frame_config__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__frame_config__duration(const wuffs_base__frame_config* c) {
return c ? c->private_impl.duration : 0;
}
// wuffs_base__frame_config__index returns the index of this frame. The first
// frame in an image has index 0, the second frame has index 1, and so on.
static inline uint64_t //
wuffs_base__frame_config__index(const wuffs_base__frame_config* c) {
return c ? c->private_impl.index : 0;
}
// wuffs_base__frame_config__io_position returns the I/O stream position before
// the frame config.
static inline uint64_t //
wuffs_base__frame_config__io_position(const wuffs_base__frame_config* c) {
return c ? c->private_impl.io_position : 0;
}
// wuffs_base__frame_config__blend returns, for an animated image, how to blend
// the transparent pixels of this frame with the existing canvas.
static inline wuffs_base__animation_blend //
wuffs_base__frame_config__blend(const wuffs_base__frame_config* c) {
return c ? c->private_impl.blend : 0;
}
// wuffs_base__frame_config__disposal returns, for an animated image, how to
// dispose of this frame after displaying it.
static inline wuffs_base__animation_disposal //
wuffs_base__frame_config__disposal(const wuffs_base__frame_config* c) {
return c ? c->private_impl.disposal : 0;
}
#ifdef __cplusplus
inline void //
wuffs_base__frame_config::update(wuffs_base__rect_ie_u32 bounds,
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal) {
wuffs_base__frame_config__update(this, bounds, duration, index, io_position,
blend, disposal);
}
inline wuffs_base__rect_ie_u32 //
wuffs_base__frame_config::bounds() const {
return wuffs_base__frame_config__bounds(this);
}
inline uint32_t //
wuffs_base__frame_config::width() const {
return wuffs_base__frame_config__width(this);
}
inline uint32_t //
wuffs_base__frame_config::height() const {
return wuffs_base__frame_config__height(this);
}
inline wuffs_base__flicks //
wuffs_base__frame_config::duration() const {
return wuffs_base__frame_config__duration(this);
}
inline uint64_t //
wuffs_base__frame_config::index() const {
return wuffs_base__frame_config__index(this);
}
inline uint64_t //
wuffs_base__frame_config::io_position() const {
return wuffs_base__frame_config__io_position(this);
}
inline wuffs_base__animation_blend //
wuffs_base__frame_config::blend() const {
return wuffs_base__frame_config__blend(this);
}
inline wuffs_base__animation_disposal //
wuffs_base__frame_config::disposal() const {
return wuffs_base__frame_config__disposal(this);
}
#endif // __cplusplus
// --------
typedef struct {
wuffs_base__pixel_config pixcfg;
// 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__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];
// TODO: color spaces.
} private_impl;
#ifdef __cplusplus
inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,
wuffs_base__slice_u8 pixbuf_memory);
inline wuffs_base__slice_u8 palette();
inline wuffs_base__pixel_format pixel_format() const;
inline wuffs_base__table_u8 plane(uint32_t p);
#endif // __cplusplus
} wuffs_base__pixel_buffer;
static inline wuffs_base__pixel_buffer //
wuffs_base__null_pixel_buffer() {
wuffs_base__pixel_buffer ret;
ret.pixcfg = wuffs_base__null_pixel_config();
ret.private_impl.planes[0] = wuffs_base__null_table_u8();
ret.private_impl.planes[1] = wuffs_base__null_table_u8();
ret.private_impl.planes[2] = wuffs_base__null_table_u8();
ret.private_impl.planes[3] = wuffs_base__null_table_u8();
return ret;
}
static inline wuffs_base__status //
wuffs_base__pixel_buffer__set_from_slice(wuffs_base__pixel_buffer* b,
wuffs_base__pixel_config* pixcfg,
wuffs_base__slice_u8 pixbuf_memory) {
if (!b) {
return wuffs_base__error__bad_receiver;
}
memset(b, 0, sizeof(*b));
if (!pixcfg) {
return wuffs_base__error__bad_argument;
}
if (wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {
// TODO: support planar pixel formats, concious of pixel subsampling.
return wuffs_base__error__bad_argument;
}
uint32_t bits_per_pixel =
wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);
if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
return wuffs_base__error__bad_argument;
}
uint64_t bytes_per_pixel = bits_per_pixel / 8;
uint8_t* ptr = pixbuf_memory.ptr;
uint64_t len = pixbuf_memory.len;
if (wuffs_base__pixel_format__is_indexed(pixcfg->private_impl.pixfmt)) {
// Split a 1024 byte chunk (256 palette entries × 4 bytes per entry) from
// the start of pixbuf_memory. We split from the start, not the end, so
// that the both chunks' pointers have the same alignment as the original
// pointer, up to an alignment of 1024.
if (len < 1024) {
return wuffs_base__error__bad_argument_length_too_short;
}
wuffs_base__table_u8* tab =
&b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
tab->ptr = ptr;
tab->width = 1024;
tab->height = 1;
tab->stride = 1024;
ptr += 1024;
len -= 1024;
}
uint64_t wh = ((uint64_t)pixcfg->private_impl.width) *
((uint64_t)pixcfg->private_impl.height);
size_t width = (size_t)(pixcfg->private_impl.width);
if ((wh > (UINT64_MAX / bytes_per_pixel)) ||
(width > (SIZE_MAX / bytes_per_pixel))) {
return wuffs_base__error__bad_argument;
}
wh *= bytes_per_pixel;
width *= bytes_per_pixel;
if (wh > len) {
return wuffs_base__error__bad_argument_length_too_short;
}
b->pixcfg = *pixcfg;
wuffs_base__table_u8* tab = &b->private_impl.planes[0];
tab->ptr = ptr;
tab->width = width;
tab->height = pixcfg->private_impl.height;
tab->stride = width;
return NULL;
}
// wuffs_base__pixel_buffer__palette returns the palette color data. If
// non-empty, it will have length 1024.
static inline wuffs_base__slice_u8 //
wuffs_base__pixel_buffer__palette(wuffs_base__pixel_buffer* b) {
if (b &&
wuffs_base__pixel_format__is_indexed(b->pixcfg.private_impl.pixfmt)) {
wuffs_base__table_u8* tab =
&b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
if ((tab->width == 1024) && (tab->height == 1)) {
return wuffs_base__make_slice_u8(tab->ptr, 1024);
}
}
return wuffs_base__make_slice_u8(NULL, 0);
}
static inline wuffs_base__pixel_format //
wuffs_base__pixel_buffer__pixel_format(const wuffs_base__pixel_buffer* b) {
if (b) {
return b->pixcfg.private_impl.pixfmt;
}
return WUFFS_BASE__PIXEL_FORMAT__INVALID;
}
static inline wuffs_base__table_u8 //
wuffs_base__pixel_buffer__plane(wuffs_base__pixel_buffer* b, uint32_t p) {
if (b && (p < WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX)) {
return b->private_impl.planes[p];
}
wuffs_base__table_u8 ret;
ret.ptr = NULL;
ret.width = 0;
ret.height = 0;
ret.stride = 0;
return ret;
}
#ifdef __cplusplus
inline wuffs_base__status //
wuffs_base__pixel_buffer::set_from_slice(wuffs_base__pixel_config* pixcfg,
wuffs_base__slice_u8 pixbuf_memory) {
return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);
}
inline wuffs_base__slice_u8 //
wuffs_base__pixel_buffer::palette() {
return wuffs_base__pixel_buffer__palette(this);
}
inline wuffs_base__pixel_format //
wuffs_base__pixel_buffer::pixel_format() const {
return wuffs_base__pixel_buffer__pixel_format(this);
}
inline wuffs_base__table_u8 //
wuffs_base__pixel_buffer::plane(uint32_t p) {
return wuffs_base__pixel_buffer__plane(this, p);
}
#endif // __cplusplus
// --------
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 {
uint8_t TODO;
} private_impl;
#ifdef __cplusplus
#endif // __cplusplus
} wuffs_base__decode_frame_options;
#ifdef __cplusplus
#endif // __cplusplus
// --------
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 {
// TODO: should the func type take restrict pointers?
uint64_t (*func)(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 dst_palette,
wuffs_base__slice_u8 src);
} private_impl;
#ifdef __cplusplus
inline void prepare(wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
wuffs_base__pixel_format src_format,
wuffs_base__slice_u8 src_palette);
inline uint64_t swizzle_packed(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 dst_palette,
wuffs_base__slice_u8 src) const;
#endif // __cplusplus
} wuffs_base__pixel_swizzler;
// TODO: should prepare (both the C and C++ methods) return a status?
void //
wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
wuffs_base__pixel_format src_format,
wuffs_base__slice_u8 src_palette);
uint64_t //
wuffs_base__pixel_swizzler__swizzle_packed(const wuffs_base__pixel_swizzler* p,
wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 dst_palette,
wuffs_base__slice_u8 src);
#ifdef __cplusplus
inline void //
wuffs_base__pixel_swizzler::prepare(wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
wuffs_base__pixel_format src_format,
wuffs_base__slice_u8 src_palette) {
wuffs_base__pixel_swizzler__prepare(this, dst_format, dst_palette, src_format,
src_palette);
}
uint64_t //
wuffs_base__pixel_swizzler::swizzle_packed(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 dst_palette,
wuffs_base__slice_u8 src) const {
return wuffs_base__pixel_swizzler__swizzle_packed(this, dst, dst_palette,
src);
}
#endif // __cplusplus
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef __cplusplus
extern "C" {
#endif
// ---------------- Status Codes
// ---------------- Public Consts
// ---------------- Struct Declarations
typedef struct wuffs_adler32__hasher__struct wuffs_adler32__hasher;
// ---------------- Public Initializer Prototypes
// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
//
// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for initialize_flags.
wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
wuffs_adler32__hasher__initialize(wuffs_adler32__hasher* self,
size_t sizeof_star_self,
uint64_t wuffs_version,
uint32_t initialize_flags);
size_t //
sizeof__wuffs_adler32__hasher();
// ---------------- Public Function Prototypes
WUFFS_BASE__MAYBE_STATIC uint32_t //
wuffs_adler32__hasher__update(wuffs_adler32__hasher* self,
wuffs_base__slice_u8 a_x);
// ---------------- Struct Definitions
// These structs' fields, and the sizeof them, are private implementation
// details that aren't guaranteed to be stable across Wuffs versions.
//
// See https://en.wikipedia.org/wiki/Opaque_pointer#C
#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
struct wuffs_adler32__hasher__struct {
#ifdef WUFFS_IMPLEMENTATION
// Do not access the private_impl's or private_data's fields directly. There
// is no API/ABI compatibility or safety guarantee if you do so. Instead, use
// the wuffs_foo__bar__baz functions.
//
// It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
// can be stack allocated when WUFFS_IMPLEMENTATION is defined.
struct {
uint32_t magic;
uint32_t active_coroutine;
uint32_t f_state;
bool f_started;
} private_impl;
#else // WUFFS_IMPLEMENTATION
// When WUFFS_IMPLEMENTATION is not defined, this placeholder private_impl is
// large enough to discourage trying to allocate one on the stack. The sizeof
// the real private_impl (and the sizeof the real outermost wuffs_foo__bar
// struct) is not part of the public, stable, memory-safe API. Call
// wuffs_foo__bar__baz methods (which all take a "this"-like pointer as their
// first argument) instead of fiddling with bar.private_impl.qux fields.
//
// Even when WUFFS_IMPLEMENTATION is not defined, the outermost struct still
// defines C++ convenience methods. These methods forward on "this", so that
// you can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
private:
union {
uint32_t align_as_per_magic_field;
uint8_t placeholder[1073741824]; // 1 GiB.
} private_impl WUFFS_BASE__POTENTIALLY_UNUSED_FIELD;
public:
#endif // WUFFS_IMPLEMENTATION
#ifdef __cplusplus
inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
initialize(size_t sizeof_star_self,
uint64_t wuffs_version,
uint32_t initialize_flags) {
return wuffs_adler32__hasher__initialize(this, sizeof_star_self,
wuffs_version, initialize_flags);
}
inline uint32_t //
update(wuffs_base__slice_u8 a_x) {
return wuffs_adler32__hasher__update(this, a_x);
}
#if (__cplusplus >= 201103L) && !defined(WUFFS_IMPLEMENTATION)
// Disallow copy and assign.
wuffs_adler32__hasher__struct(const wuffs_adler32__hasher__struct&) = delete;
wuffs_adler32__hasher__struct& operator=(
const wuffs_adler32__hasher__struct&) = delete;
#endif // (__cplusplus >= 201103L) && !defined(WUFFS_IMPLEMENTATION)
#endif // __cplusplus
}; // struct wuffs_adler32__hasher__struct
#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// ---------------- Status Codes
// ---------------- Public Consts
// ---------------- Struct Declarations
typedef struct wuffs_crc32__ieee_hasher__struct wuffs_crc32__ieee_hasher;
// ---------------- Public Initializer Prototypes
// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
//
// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for initialize_flags.
wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
wuffs_crc32__ieee_hasher__initialize(wuffs_crc32__ieee_hasher* self,
size_t sizeof_star_self,
uint64_t wuffs_version,
uint32_t initialize_flags);
size_t //
sizeof__wuffs_crc32__ieee_hasher();
// ---------------- Public Function Prototypes
WUFFS_BASE__MAYBE_STATIC uint32_t //
wuffs_crc32__ieee_hasher__update(wuffs_crc32__ieee_hasher* self,
wuffs_base__slice_u8 a_x);
// ---------------- Struct Definitions
// These structs' fields, and the sizeof them, are private implementation
// details that aren't guaranteed to be stable across Wuffs versions.
//
// See https://en.wikipedia.org/wiki/Opaque_pointer#C
#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
struct wuffs_crc32__ieee_hasher__struct {
#ifdef WUFFS_IMPLEMENTATION
// Do not access the private_impl's or private_data's fields directly. There
// is no API/ABI compatibility or safety guarantee if you do so. Instead, use
// the wuffs_foo__bar__baz functions.
//
// It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
// can be stack allocated when WUFFS_IMPLEMENTATION is defined.
struct {
uint32_t magic;
uint32_t active_coroutine;
uint32_t f_state;
} private_impl;
#else // WUFFS_IMPLEMENTATION
// When WUFFS_IMPLEMENTATION is not defined, this placeholder private_impl is
// large enough to discourage trying to allocate one on the stack. The sizeof
// the real private_impl (and the sizeof the real outermost wuffs_foo__bar
// struct) is not part of the public, stable, memory-safe API. Call
// wuffs_foo__bar__baz methods (which all take a "this"-like pointer as their
// first argument) instead of fiddling with bar.private_impl.qux fields.
//
// Even when WUFFS_IMPLEMENTATION is not defined, the outermost struct still
// defines C++ convenience methods. These methods forward on "this", so that
// you can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
private:
union {
uint32_t align_as_per_magic_field;
uint8_t placeholder[1073741824]; // 1 GiB.
} private_impl WUFFS_BASE__POTENTIALLY_UNUSED_FIELD;
public:
#endif // WUFFS_IMPLEMENTATION
#ifdef __cplusplus
inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
initialize(size_t sizeof_star_self,
uint64_t wuffs_version,
uint32_t initialize_flags) {
return wuffs_crc32__ieee_hasher__initialize(
this, sizeof_star_self, wuffs_version, initialize_flags);
}
inline uint32_t //
update(wuffs_base__slice_u8 a_x) {
return wuffs_crc32__ieee_hasher__update(this, a_x);
}
#if (__cplusplus >= 201103L) && !defined(WUFFS_IMPLEMENTATION)
// Disallow copy and assign.
wuffs_crc32__ieee_hasher__struct(const wuffs_crc32__ieee_hasher__struct&) =
delete;
wuffs_crc32__ieee_hasher__struct& operator=(
const wuffs_crc32__ieee_hasher__struct&) = delete;
#endif // (__cplusplus >= 201103L) && !defined(WUFFS_IMPLEMENTATION)
#endif // __cplusplus
}; // struct wuffs_crc32__ieee_hasher__struct
#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// ---------------- Status Codes
extern const char* wuffs_deflate__error__bad_huffman_code_over_subscribed;
extern const char* wuffs_deflate__error__bad_huffman_code_under_subscribed;
extern const char* wuffs_deflate__error__bad_huffman_code_length_count;
extern const char* wuffs_deflate__error__bad_huffman_code_length_repetition;
extern const char* wuffs_deflate__error__bad_huffman_code;
extern const char* wuffs_deflate__error__bad_huffman_minimum_code_length;
extern const char* wuffs_deflate__error__bad_block;
extern const char* wuffs_deflate__error__bad_distance;
extern const char* wuffs_deflate__error__bad_distance_code_count;
extern const char* wuffs_deflate__error__bad_literal_length_code_count;
extern const char* wuffs_deflate__error__inconsistent_stored_block_length;
extern const char* wuffs_deflate__error__missing_end_of_block_code;
extern const char* wuffs_deflate__error__no_huffman_codes;
// ---------------- Public Consts
#define WUFFS_DEFLATE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1
static const uint64_t //
wuffs_deflate__decoder_workbuf_len_max_incl_worst_case //
WUFFS_BASE__POTENTIALLY_UNUSED = 1;
// ---------------- Struct Declarations
typedef struct wuffs_deflate__decoder__struct wuffs_deflate__decoder;
// ---------------- Public Initializer Prototypes
// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
//
// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for initialize_flags.
wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
wuffs_deflate__decoder__initialize(wuffs_deflate__decoder* self,
size_t sizeof_star_self,
uint64_t wuffs_version,
uint32_t initialize_flags);
size_t //
sizeof__wuffs_deflate__decoder();
// ---------------- Public Function Prototypes
WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 //
wuffs_deflate__decoder__workbuf_len(const wuffs_deflate__decoder* self);
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_deflate__decoder__decode_io_writer(wuffs_deflate__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src,
wuffs_base__slice_u8 a_workbuf);
// ---------------- Struct Definitions
// These structs' fields, and the sizeof them, are private implementation
// details that aren't guaranteed to be stable across Wuffs versions.
//
// See https://en.wikipedia.org/wiki/Opaque_pointer#C
#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
struct wuffs_deflate__decoder__struct {
#ifdef WUFFS_IMPLEMENTATION
// Do not access the private_impl's or private_data's fields directly. There
// is no API/ABI compatibility or safety guarantee if you do so. Instead, use
// the wuffs_foo__bar__baz functions.
//
// It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
// can be stack allocated when WUFFS_IMPLEMENTATION is defined.
struct {
uint32_t magic;
uint32_t active_coroutine;
uint32_t f_bits;
uint32_t f_n_bits;
uint32_t f_history_index;
uint32_t f_n_huffs_bits[2];
bool f_end_of_block;
uint32_t p_decode_io_writer[1];
uint32_t p_decode_blocks[1];
uint32_t p_decode_uncompressed[1];
uint32_t p_init_dynamic_huffman[1];
uint32_t p_decode_huffman_slow[1];
} private_impl;
struct {
uint32_t f_huffs[2][1024];
uint8_t f_history[32768];
uint8_t f_code_lengths[320];
struct {
uint32_t v_final;
} s_decode_blocks[1];
struct {
uint32_t v_length;
uint64_t scratch;
} s_decode_uncompressed[1];
struct {
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_n_extra_bits;
uint8_t v_rep_symbol;
uint32_t v_rep_count;
} s_init_dynamic_huffman[1];
struct {
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_hlen;
uint32_t v_hdist;
} s_decode_huffman_slow[1];
} private_data;
#else // WUFFS_IMPLEMENTATION
// When WUFFS_IMPLEMENTATION is not defined, this placeholder private_impl is
// large enough to discourage trying to allocate one on the stack. The sizeof
// the real private_impl (and the sizeof the real outermost wuffs_foo__bar
// struct) is not part of the public, stable, memory-safe API. Call
// wuffs_foo__bar__baz methods (which all take a "this"-like pointer as their
// first argument) instead of fiddling with bar.private_impl.qux fields.
//
// Even when WUFFS_IMPLEMENTATION is not defined, the outermost struct still
// defines C++ convenience methods. These methods forward on "this", so that
// you can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
private:
union {
uint32_t align_as_per_magic_field;
uint8_t placeholder[1073741824]; // 1 GiB.
} private_impl WUFFS_BASE__POTENTIALLY_UNUSED_FIELD;
public:
#endif // WUFFS_IMPLEMENTATION
#ifdef __cplusplus
inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
initialize(size_t sizeof_star_self,
uint64_t wuffs_version,
uint32_t initialize_flags) {
return wuffs_deflate__decoder__initialize(this, sizeof_star_self,
wuffs_version, initialize_flags);
}
inline wuffs_base__range_ii_u64 //
workbuf_len() const {
return wuffs_deflate__decoder__workbuf_len(this);
}
inline wuffs_base__status //
decode_io_writer(wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src,
wuffs_base__slice_u8 a_workbuf) {
return wuffs_deflate__decoder__decode_io_writer(this, a_dst, a_src,
a_workbuf);
}
#if (__cplusplus >= 201103L) && !defined(WUFFS_IMPLEMENTATION)
// Disallow copy and assign.
wuffs_deflate__decoder__struct(const wuffs_deflate__decoder__struct&) =
delete;
wuffs_deflate__decoder__struct& operator=(
const wuffs_deflate__decoder__struct&) = delete;
#endif // (__cplusplus >= 201103L) && !defined(WUFFS_IMPLEMENTATION)
#endif // __cplusplus
}; // struct wuffs_deflate__decoder__struct
#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// ---------------- Status Codes
extern const char* wuffs_lzw__error__bad_code;
// ---------------- Public Consts
#define WUFFS_LZW__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
static const uint64_t //
wuffs_lzw__decoder_workbuf_len_max_incl_worst_case //
WUFFS_BASE__POTENTIALLY_UNUSED = 0;
// ---------------- Struct Declarations
typedef struct wuffs_lzw__decoder__struct wuffs_lzw__decoder;
// ---------------- Public Initializer Prototypes
// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
//
// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for initialize_flags.
wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
wuffs_lzw__decoder__initialize(wuffs_lzw__decoder* self,
size_t sizeof_star_self,
uint64_t wuffs_version,
uint32_t initialize_flags);
size_t //
sizeof__wuffs_lzw__decoder();
// ---------------- Public Function Prototypes
WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
wuffs_lzw__decoder__set_literal_width(wuffs_lzw__decoder* self, uint32_t a_lw);
WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 //
wuffs_lzw__decoder__workbuf_len(const wuffs_lzw__decoder* self);
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_lzw__decoder__decode_io_writer(wuffs_lzw__decoder* self,
wuffs_base__io_writer a_dst,
wuffs_base__io_reader a_src,
wuffs_base__slice_u8 a_workbuf);
WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8 //
wuffs_lzw__decoder__flush(wuffs_lzw__decoder* self);
// ---------------- Struct Definitions
// These structs' fields, and the sizeof them, are private implementation
// details that aren't guaranteed to be stable across Wuffs versions.
//
// See https://en.wikipedia.org/wiki/Opaque_pointer#C
#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
struct wuffs_lzw__decoder__struct {
#ifdef WUFFS_IMPLEMENTATION
// Do not access the private_impl's or private_data's fields directly. There
// is no API/ABI compatibility or safety guarantee if you do so. Instead, use
// the wuffs_foo__bar__baz functions.
//
// It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
// can be stack allocated when WUFFS_IMPLEMENTATION is defined.
struct {
uint32_t magic;
uint32_t active_coroutine;
uint32_t f_set_literal_width_arg;
uint32_t f_literal_width;
uint32_t f_clear_code;
uint32_t f_end_code;
uint32_t f_save_code;
uint32_t f_prev_code;
uint32_t f_width;
uint32_t f_bits;
uint32_t f_n_bits;
uint32_t f_output_ri;
uint32_t f_output_wi;
uint32_t f_read_from_return_value;
uint16_t f_prefixes[4096];
uint32_t p_decode_io_writer[1];
uint32_t p_write_to[1];
} private_impl;
struct {
uint8_t f_suffixes[4096][8];
uint16_t f_lm1s[4096];
uint8_t f_output[8199];
} private_data;
#else // WUFFS_IMPLEMENTATION
// When WUFFS_IMPLEMENTATION is not defined, this placeholder private_impl is
// large enough to discourage trying to allocate one on the stack. The sizeof
// the real private_impl (and the sizeof the real outermost wuffs_foo__bar
// struct) is not part of the public, stable, memory-safe API. Call
// wuffs_foo__bar__baz methods (which all take a "this"-like pointer as their
// first argument) instead of fiddling with bar.private_impl.qux fields.
//
// Even when WUFFS_IMPLEMENTATION is not defined, the outermost struct still
// defines C++ convenience methods. These methods forward on "this", so that
// you can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
private:
union {
uint32_t align_as_per_magic_field;
uint8_t placeholder[1073741824]; // 1 GiB.
} private_impl WUFFS_BASE__POTENTIALLY_UNUSED_FIELD;
public:
#endif // WUFFS_IMPLEMENTATION
#ifdef __cplusplus
inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
initialize(size_t sizeof_star_self,
uint64_t wuffs_version,
uint32_t initialize_flags) {
return wuffs_lzw__decoder__initialize(this, sizeof_star_self, wuffs_version,