blob: 91181f8c558b691396fee939ee7b61978ce3ee56 [file] [log] [blame]
Nigel Taoe360a532021-04-05 22:47:03 +10001#ifndef WUFFS_INCLUDE_GUARD
2#define WUFFS_INCLUDE_GUARD
3
4// Wuffs ships as a "single file C library" or "header file library" as per
5// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
6//
7// To use that single file as a "foo.c"-like implementation, instead of a
8// "foo.h"-like header, #define WUFFS_IMPLEMENTATION before #include'ing or
9// compiling it.
10
11// Wuffs' C code is generated automatically, not hand-written. These warnings'
12// costs outweigh the benefits.
Nigel Taobb778712021-06-25 15:38:45 +100013//
14// The "elif defined(__clang__)" isn't redundant. While vanilla clang defines
15// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not.
Nigel Taoe360a532021-04-05 22:47:03 +100016#if defined(__GNUC__)
17#pragma GCC diagnostic push
Nigel Tao5aae6d12021-07-05 21:53:02 +100018#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
Nigel Taoe360a532021-04-05 22:47:03 +100019#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
20#pragma GCC diagnostic ignored "-Wunreachable-code"
21#pragma GCC diagnostic ignored "-Wunused-function"
22#pragma GCC diagnostic ignored "-Wunused-parameter"
23#if defined(__cplusplus)
24#pragma GCC diagnostic ignored "-Wold-style-cast"
25#endif
Nigel Taobb778712021-06-25 15:38:45 +100026#elif defined(__clang__)
27#pragma clang diagnostic push
Nigel Tao5aae6d12021-07-05 21:53:02 +100028#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
Nigel Taobb778712021-06-25 15:38:45 +100029#pragma clang diagnostic ignored "-Wmissing-field-initializers"
30#pragma clang diagnostic ignored "-Wunreachable-code"
31#pragma clang diagnostic ignored "-Wunused-function"
32#pragma clang diagnostic ignored "-Wunused-parameter"
33#if defined(__cplusplus)
34#pragma clang diagnostic ignored "-Wold-style-cast"
35#endif
Nigel Taoe360a532021-04-05 22:47:03 +100036#endif
37
38// Copyright 2017 The Wuffs Authors.
39//
40// Licensed under the Apache License, Version 2.0 (the "License");
41// you may not use this file except in compliance with the License.
42// You may obtain a copy of the License at
43//
44// https://www.apache.org/licenses/LICENSE-2.0
45//
46// Unless required by applicable law or agreed to in writing, software
47// distributed under the License is distributed on an "AS IS" BASIS,
48// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
49// See the License for the specific language governing permissions and
50// limitations under the License.
51
52#include <stdbool.h>
53#include <stdint.h>
54#include <stdlib.h>
55#include <string.h>
56
Nigel Taoe360a532021-04-05 22:47:03 +100057#ifdef __cplusplus
58#if (__cplusplus >= 201103L) || defined(_MSC_VER)
59#include <memory>
60#define WUFFS_BASE__HAVE_EQ_DELETE
61#define WUFFS_BASE__HAVE_UNIQUE_PTR
Nigel Taobf9dab32021-11-18 19:19:55 +110062// The "defined(__clang__)" isn't redundant. While vanilla clang defines
63// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not.
64#elif defined(__GNUC__) || defined(__clang__)
Nigel Taoe360a532021-04-05 22:47:03 +100065#warning "Wuffs' C++ code expects -std=c++11 or later"
66#endif
67
68extern "C" {
69#endif
70
71// ---------------- Version
72
73// WUFFS_VERSION is the major.minor.patch version, as per https://semver.org/,
74// as a uint64_t. The major number is the high 32 bits. The minor number is the
75// middle 16 bits. The patch number is the low 16 bits. The pre-release label
76// and build metadata are part of the string representation (such as
77// "1.2.3-beta+456.20181231") but not the uint64_t representation.
78//
79// WUFFS_VERSION_PRE_RELEASE_LABEL (such as "", "beta" or "rc.1") being
80// non-empty denotes a developer preview, not a release version, and has no
81// backwards or forwards compatibility guarantees.
82//
83// WUFFS_VERSION_BUILD_METADATA_XXX, if non-zero, are the number of commits and
84// the last commit date in the repository used to build this library. Within
85// each major.minor branch, the commit count should increase monotonically.
86//
87// WUFFS_VERSION was overridden by "wuffs gen -version" based on revision
Nigel Taobf9dab32021-11-18 19:19:55 +110088// 161e4730d8b446a72d6152b8343da8543e7518bf committed on 2021-11-18.
Nigel Taoe360a532021-04-05 22:47:03 +100089#define WUFFS_VERSION 0x000030000
90#define WUFFS_VERSION_MAJOR 0
91#define WUFFS_VERSION_MINOR 3
92#define WUFFS_VERSION_PATCH 0
Nigel Taobf9dab32021-11-18 19:19:55 +110093#define WUFFS_VERSION_PRE_RELEASE_LABEL "beta.11"
94#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 3198
95#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 20211118
96#define WUFFS_VERSION_STRING "0.3.0-beta.11+3198.20211118"
Nigel Taoe360a532021-04-05 22:47:03 +100097
98// ---------------- Configuration
99
100// Define WUFFS_CONFIG__AVOID_CPU_ARCH to avoid any code tied to a specific CPU
101// architecture, such as SSE SIMD for the x86 CPU family.
102#if defined(WUFFS_CONFIG__AVOID_CPU_ARCH) // (#if-chain ref AVOID_CPU_ARCH_0)
103// No-op.
104#else // (#if-chain ref AVOID_CPU_ARCH_0)
105
106// The "defined(__clang__)" isn't redundant. While vanilla clang defines
107// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not.
108#if defined(__GNUC__) || defined(__clang__)
109#define WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET(arg) __attribute__((target(arg)))
110#else
111#define WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET(arg)
112#endif // defined(__GNUC__) || defined(__clang__)
113
114#if defined(__GNUC__) // (#if-chain ref AVOID_CPU_ARCH_1)
115
116// To simplify Wuffs code, "cpu_arch >= arm_xxx" requires xxx but also
117// unaligned little-endian load/stores.
Nigel Tao5571bfe2021-06-24 22:44:29 +1000118#if defined(__ARM_FEATURE_UNALIGNED) && !defined(__native_client__) && \
119 defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
Nigel Taoe360a532021-04-05 22:47:03 +1000120// Not all gcc versions define __ARM_ACLE, even if they support crc32
121// intrinsics. Look for __ARM_FEATURE_CRC32 instead.
122#if defined(__ARM_FEATURE_CRC32)
123#include <arm_acle.h>
124#define WUFFS_BASE__CPU_ARCH__ARM_CRC32
125#endif // defined(__ARM_FEATURE_CRC32)
126#if defined(__ARM_NEON)
127#include <arm_neon.h>
128#define WUFFS_BASE__CPU_ARCH__ARM_NEON
129#endif // defined(__ARM_NEON)
130#endif // defined(__ARM_FEATURE_UNALIGNED) etc
131
132// Similarly, "cpu_arch >= x86_sse42" requires SSE4.2 but also PCLMUL and
133// POPCNT. This is checked at runtime via cpuid, not at compile time.
Nigel Tao5571bfe2021-06-24 22:44:29 +1000134//
135// Likewise, "cpu_arch >= x86_avx2" also requires PCLMUL, POPCNT and SSE4.2.
Nigel Tao7804ffe2021-10-07 21:58:26 +1100136#if defined(__i386__) || defined(__x86_64__)
137#if !defined(__native_client__)
Nigel Taoe360a532021-04-05 22:47:03 +1000138#include <cpuid.h>
139#include <x86intrin.h>
Nigel Tao7804ffe2021-10-07 21:58:26 +1100140// X86_FAMILY means X86 (32-bit) or X86_64 (64-bit, obviously).
141#define WUFFS_BASE__CPU_ARCH__X86_FAMILY
142#endif // !defined(__native_client__)
143#endif // defined(__i386__) || defined(__x86_64__)
Nigel Taoe360a532021-04-05 22:47:03 +1000144
145#elif defined(_MSC_VER) // (#if-chain ref AVOID_CPU_ARCH_1)
146
Nigel Tao7804ffe2021-10-07 21:58:26 +1100147#if defined(_M_IX86) || defined(_M_X64)
Nigel Taoe360a532021-04-05 22:47:03 +1000148#if defined(__AVX__) || defined(__clang__)
149
150// We need <intrin.h> for the __cpuid function.
151#include <intrin.h>
152// That's not enough for X64 SIMD, with clang-cl, if we want to use
153// "__attribute__((target(arg)))" without e.g. "/arch:AVX".
154//
155// Some web pages suggest that <immintrin.h> is all you need, as it pulls in
156// the earlier SIMD families like SSE4.2, but that doesn't seem to work in
157// practice, possibly for the same reason that just <intrin.h> doesn't work.
158#include <immintrin.h> // AVX, AVX2, FMA, POPCNT
159#include <nmmintrin.h> // SSE4.2
160#include <wmmintrin.h> // AES, PCLMUL
Nigel Tao7804ffe2021-10-07 21:58:26 +1100161// X86_FAMILY means X86 (32-bit) or X86_64 (64-bit, obviously).
162#define WUFFS_BASE__CPU_ARCH__X86_FAMILY
Nigel Taoe360a532021-04-05 22:47:03 +1000163
164#else // defined(__AVX__) || defined(__clang__)
165
166// clang-cl (which defines both __clang__ and _MSC_VER) supports
167// "__attribute__((target(arg)))".
168//
169// For MSVC's cl.exe (unlike clang or gcc), SIMD capability is a compile-time
170// property of the source file (e.g. a /arch:AVX or -mavx compiler flag), not
171// of individual functions (that can be conditionally selected at runtime).
Nigel Tao7804ffe2021-10-07 21:58:26 +1100172#pragma message("Wuffs with MSVC+IX86/X64 needs /arch:AVX for best performance")
Nigel Taoe360a532021-04-05 22:47:03 +1000173
174#endif // defined(__AVX__) || defined(__clang__)
Nigel Tao7804ffe2021-10-07 21:58:26 +1100175#endif // defined(_M_IX86) || defined(_M_X64)
Nigel Taoe360a532021-04-05 22:47:03 +1000176
177#endif // (#if-chain ref AVOID_CPU_ARCH_1)
178#endif // (#if-chain ref AVOID_CPU_ARCH_0)
179
180// --------
181
Nigel Tao7804ffe2021-10-07 21:58:26 +1100182// Define WUFFS_CONFIG__STATIC_FUNCTIONS (combined with WUFFS_IMPLEMENTATION)
183// to make all of Wuffs' functions have static storage.
184//
185// This can help the compiler ignore or discard unused code, which can produce
186// faster compiles and smaller binaries. Other motivations are discussed in the
187// "ALLOW STATIC IMPLEMENTATION" section of
Nigel Taoe360a532021-04-05 22:47:03 +1000188// https://raw.githubusercontent.com/nothings/stb/master/docs/stb_howto.txt
189#if defined(WUFFS_CONFIG__STATIC_FUNCTIONS)
190#define WUFFS_BASE__MAYBE_STATIC static
191#else
192#define WUFFS_BASE__MAYBE_STATIC
193#endif // defined(WUFFS_CONFIG__STATIC_FUNCTIONS)
194
195// ---------------- CPU Architecture
196
197static inline bool //
198wuffs_base__cpu_arch__have_arm_crc32() {
199#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
200 return true;
201#else
202 return false;
203#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
204}
205
206static inline bool //
207wuffs_base__cpu_arch__have_arm_neon() {
208#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
209 return true;
210#else
211 return false;
212#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
213}
214
215static inline bool //
Nigel Tao5571bfe2021-06-24 22:44:29 +1000216wuffs_base__cpu_arch__have_x86_avx2() {
Nigel Tao7804ffe2021-10-07 21:58:26 +1100217#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +1000218 // GCC defines these macros but MSVC does not.
219 // - bit_AVX2 = (1 << 5)
220 const unsigned int avx2_ebx7 = 0x00000020;
221 // GCC defines these macros but MSVC does not.
222 // - bit_PCLMUL = (1 << 1)
223 // - bit_POPCNT = (1 << 23)
224 // - bit_SSE4_2 = (1 << 20)
225 const unsigned int avx2_ecx1 = 0x00900002;
226
227 // clang defines __GNUC__ and clang-cl defines _MSC_VER (but not __GNUC__).
228#if defined(__GNUC__)
229 unsigned int eax7 = 0;
230 unsigned int ebx7 = 0;
231 unsigned int ecx7 = 0;
232 unsigned int edx7 = 0;
233 if (__get_cpuid_count(7, 0, &eax7, &ebx7, &ecx7, &edx7) &&
234 ((ebx7 & avx2_ebx7) == avx2_ebx7)) {
235 unsigned int eax1 = 0;
236 unsigned int ebx1 = 0;
237 unsigned int ecx1 = 0;
238 unsigned int edx1 = 0;
239 if (__get_cpuid(1, &eax1, &ebx1, &ecx1, &edx1) &&
240 ((ecx1 & avx2_ecx1) == avx2_ecx1)) {
241 return true;
242 }
243 }
244#elif defined(_MSC_VER) // defined(__GNUC__)
245 int x7[4];
246 __cpuidex(x7, 7, 0);
247 if ((((unsigned int)(x7[1])) & avx2_ebx7) == avx2_ebx7) {
248 int x1[4];
249 __cpuid(x1, 1);
250 if ((((unsigned int)(x1[2])) & avx2_ecx1) == avx2_ecx1) {
251 return true;
252 }
253 }
254#else
255#error "WUFFS_BASE__CPU_ARCH__ETC combined with an unsupported compiler"
256#endif // defined(__GNUC__); defined(_MSC_VER)
Nigel Tao7804ffe2021-10-07 21:58:26 +1100257#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +1000258 return false;
259}
260
261static inline bool //
262wuffs_base__cpu_arch__have_x86_bmi2() {
Nigel Tao7804ffe2021-10-07 21:58:26 +1100263#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +1000264 // GCC defines these macros but MSVC does not.
265 // - bit_BMI2 = (1 << 8)
266 const unsigned int bmi2_ebx7 = 0x00000100;
267
268 // clang defines __GNUC__ and clang-cl defines _MSC_VER (but not __GNUC__).
269#if defined(__GNUC__)
270 unsigned int eax7 = 0;
271 unsigned int ebx7 = 0;
272 unsigned int ecx7 = 0;
273 unsigned int edx7 = 0;
274 if (__get_cpuid_count(7, 0, &eax7, &ebx7, &ecx7, &edx7) &&
275 ((ebx7 & bmi2_ebx7) == bmi2_ebx7)) {
276 return true;
277 }
278#elif defined(_MSC_VER) // defined(__GNUC__)
279 int x7[4];
280 __cpuidex(x7, 7, 0);
281 if ((((unsigned int)(x7[1])) & bmi2_ebx7) == bmi2_ebx7) {
282 return true;
283 }
284#else
285#error "WUFFS_BASE__CPU_ARCH__ETC combined with an unsupported compiler"
286#endif // defined(__GNUC__); defined(_MSC_VER)
Nigel Tao7804ffe2021-10-07 21:58:26 +1100287#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +1000288 return false;
289}
290
291static inline bool //
Nigel Taoe360a532021-04-05 22:47:03 +1000292wuffs_base__cpu_arch__have_x86_sse42() {
Nigel Tao7804ffe2021-10-07 21:58:26 +1100293#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +1000294 // GCC defines these macros but MSVC does not.
295 // - bit_PCLMUL = (1 << 1)
296 // - bit_POPCNT = (1 << 23)
297 // - bit_SSE4_2 = (1 << 20)
298 const unsigned int sse42_ecx1 = 0x00900002;
299
300 // clang defines __GNUC__ and clang-cl defines _MSC_VER (but not __GNUC__).
301#if defined(__GNUC__)
302 unsigned int eax1 = 0;
303 unsigned int ebx1 = 0;
304 unsigned int ecx1 = 0;
305 unsigned int edx1 = 0;
Nigel Tao5571bfe2021-06-24 22:44:29 +1000306 if (__get_cpuid(1, &eax1, &ebx1, &ecx1, &edx1) &&
307 ((ecx1 & sse42_ecx1) == sse42_ecx1)) {
308 return true;
Nigel Taoe360a532021-04-05 22:47:03 +1000309 }
310#elif defined(_MSC_VER) // defined(__GNUC__)
Nigel Tao5571bfe2021-06-24 22:44:29 +1000311 int x1[4];
312 __cpuid(x1, 1);
313 if ((((unsigned int)(x1[2])) & sse42_ecx1) == sse42_ecx1) {
314 return true;
315 }
Nigel Taoe360a532021-04-05 22:47:03 +1000316#else
317#error "WUFFS_BASE__CPU_ARCH__ETC combined with an unsupported compiler"
318#endif // defined(__GNUC__); defined(_MSC_VER)
Nigel Tao7804ffe2021-10-07 21:58:26 +1100319#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +1000320 return false;
321}
322
323// ---------------- Fundamentals
324
325// Wuffs assumes that:
326// - converting a uint32_t to a size_t will never overflow.
327// - converting a size_t to a uint64_t will never overflow.
328#if defined(__WORDSIZE)
329#if (__WORDSIZE != 32) && (__WORDSIZE != 64)
330#error "Wuffs requires a word size of either 32 or 64 bits"
331#endif
332#endif
333
Nigel Taobf9dab32021-11-18 19:19:55 +1100334// The "defined(__clang__)" isn't redundant. While vanilla clang defines
335// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not.
336#if defined(__GNUC__) || defined(__clang__)
Nigel Taoe360a532021-04-05 22:47:03 +1000337#define WUFFS_BASE__POTENTIALLY_UNUSED __attribute__((unused))
338#define WUFFS_BASE__WARN_UNUSED_RESULT __attribute__((warn_unused_result))
339#else
340#define WUFFS_BASE__POTENTIALLY_UNUSED
341#define WUFFS_BASE__WARN_UNUSED_RESULT
342#endif
343
344// --------
345
346// Options (bitwise or'ed together) for wuffs_foo__bar__initialize functions.
347
348#define WUFFS_INITIALIZE__DEFAULT_OPTIONS ((uint32_t)0x00000000)
349
350// WUFFS_INITIALIZE__ALREADY_ZEROED means that the "self" receiver struct value
351// has already been set to all zeroes.
352#define WUFFS_INITIALIZE__ALREADY_ZEROED ((uint32_t)0x00000001)
353
354// WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED means that, absent
355// WUFFS_INITIALIZE__ALREADY_ZEROED, only some of the "self" receiver struct
356// value will be set to all zeroes. Internal buffers, which tend to be a large
357// proportion of the struct's size, will be left uninitialized. Internal means
358// that the buffer is contained by the receiver struct, as opposed to being
359// passed as a separately allocated "work buffer".
360//
361// For more detail, see:
362// https://github.com/google/wuffs/blob/main/doc/note/initialization.md
363#define WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED \
364 ((uint32_t)0x00000002)
365
366// --------
367
368// wuffs_base__empty_struct is used when a Wuffs function returns an empty
369// struct. In C, if a function f returns void, you can't say "x = f()", but in
370// Wuffs, if a function g returns empty, you can say "y = g()".
371typedef struct wuffs_base__empty_struct__struct {
372 // private_impl is a placeholder field. It isn't explicitly used, except that
373 // without it, the sizeof a struct with no fields can differ across C/C++
374 // compilers, and it is undefined behavior in C99. For example, gcc says that
375 // the sizeof an empty struct is 0, and g++ says that it is 1. This leads to
376 // ABI incompatibility if a Wuffs .c file is processed by one compiler and
377 // its .h file with another compiler.
378 //
379 // Instead, we explicitly insert an otherwise unused field, so that the
380 // sizeof this struct is always 1.
381 uint8_t private_impl;
382} wuffs_base__empty_struct;
383
384static inline wuffs_base__empty_struct //
385wuffs_base__make_empty_struct() {
386 wuffs_base__empty_struct ret;
387 ret.private_impl = 0;
388 return ret;
389}
390
391// wuffs_base__utility is a placeholder receiver type. It enables what Java
392// calls static methods, as opposed to regular methods.
393typedef struct wuffs_base__utility__struct {
394 // private_impl is a placeholder field. It isn't explicitly used, except that
395 // without it, the sizeof a struct with no fields can differ across C/C++
396 // compilers, and it is undefined behavior in C99. For example, gcc says that
397 // the sizeof an empty struct is 0, and g++ says that it is 1. This leads to
398 // ABI incompatibility if a Wuffs .c file is processed by one compiler and
399 // its .h file with another compiler.
400 //
401 // Instead, we explicitly insert an otherwise unused field, so that the
402 // sizeof this struct is always 1.
403 uint8_t private_impl;
404} wuffs_base__utility;
405
406typedef struct wuffs_base__vtable__struct {
407 const char* vtable_name;
408 const void* function_pointers;
409} wuffs_base__vtable;
410
411// --------
412
413// See https://github.com/google/wuffs/blob/main/doc/note/statuses.md
414typedef struct wuffs_base__status__struct {
415 const char* repr;
416
417#ifdef __cplusplus
418 inline bool is_complete() const;
419 inline bool is_error() const;
420 inline bool is_note() const;
421 inline bool is_ok() const;
422 inline bool is_suspension() const;
423 inline const char* message() const;
424#endif // __cplusplus
425
426} wuffs_base__status;
427
428extern const char wuffs_base__note__i_o_redirect[];
429extern const char wuffs_base__note__end_of_data[];
430extern const char wuffs_base__note__metadata_reported[];
431extern const char wuffs_base__suspension__even_more_information[];
432extern const char wuffs_base__suspension__mispositioned_read[];
433extern const char wuffs_base__suspension__mispositioned_write[];
434extern const char wuffs_base__suspension__short_read[];
435extern const char wuffs_base__suspension__short_write[];
436extern const char wuffs_base__error__bad_i_o_position[];
437extern const char wuffs_base__error__bad_argument_length_too_short[];
438extern const char wuffs_base__error__bad_argument[];
439extern const char wuffs_base__error__bad_call_sequence[];
440extern const char wuffs_base__error__bad_data[];
441extern const char wuffs_base__error__bad_receiver[];
442extern const char wuffs_base__error__bad_restart[];
443extern const char wuffs_base__error__bad_sizeof_receiver[];
444extern const char wuffs_base__error__bad_vtable[];
445extern const char wuffs_base__error__bad_workbuf_length[];
446extern const char wuffs_base__error__bad_wuffs_version[];
447extern const char wuffs_base__error__cannot_return_a_suspension[];
448extern const char wuffs_base__error__disabled_by_previous_error[];
449extern const char wuffs_base__error__initialize_falsely_claimed_already_zeroed[];
450extern const char wuffs_base__error__initialize_not_called[];
451extern const char wuffs_base__error__interleaved_coroutine_calls[];
452extern const char wuffs_base__error__no_more_information[];
453extern const char wuffs_base__error__not_enough_data[];
454extern const char wuffs_base__error__out_of_bounds[];
455extern const char wuffs_base__error__unsupported_method[];
456extern const char wuffs_base__error__unsupported_option[];
457extern const char wuffs_base__error__unsupported_pixel_swizzler_option[];
458extern const char wuffs_base__error__too_much_data[];
459
460static inline wuffs_base__status //
461wuffs_base__make_status(const char* repr) {
462 wuffs_base__status z;
463 z.repr = repr;
464 return z;
465}
466
467static inline bool //
468wuffs_base__status__is_complete(const wuffs_base__status* z) {
469 return (z->repr == NULL) || ((*z->repr != '$') && (*z->repr != '#'));
470}
471
472static inline bool //
473wuffs_base__status__is_error(const wuffs_base__status* z) {
474 return z->repr && (*z->repr == '#');
475}
476
477static inline bool //
478wuffs_base__status__is_note(const wuffs_base__status* z) {
479 return z->repr && (*z->repr != '$') && (*z->repr != '#');
480}
481
482static inline bool //
483wuffs_base__status__is_ok(const wuffs_base__status* z) {
484 return z->repr == NULL;
485}
486
487static inline bool //
488wuffs_base__status__is_suspension(const wuffs_base__status* z) {
489 return z->repr && (*z->repr == '$');
490}
491
492// wuffs_base__status__message strips the leading '$', '#' or '@'.
493static inline const char* //
494wuffs_base__status__message(const wuffs_base__status* z) {
495 if (z->repr) {
496 if ((*z->repr == '$') || (*z->repr == '#') || (*z->repr == '@')) {
497 return z->repr + 1;
498 }
499 }
500 return z->repr;
501}
502
503#ifdef __cplusplus
504
505inline bool //
506wuffs_base__status::is_complete() const {
507 return wuffs_base__status__is_complete(this);
508}
509
510inline bool //
511wuffs_base__status::is_error() const {
512 return wuffs_base__status__is_error(this);
513}
514
515inline bool //
516wuffs_base__status::is_note() const {
517 return wuffs_base__status__is_note(this);
518}
519
520inline bool //
521wuffs_base__status::is_ok() const {
522 return wuffs_base__status__is_ok(this);
523}
524
525inline bool //
526wuffs_base__status::is_suspension() const {
527 return wuffs_base__status__is_suspension(this);
528}
529
530inline const char* //
531wuffs_base__status::message() const {
532 return wuffs_base__status__message(this);
533}
534
535#endif // __cplusplus
536
537// --------
538
539// WUFFS_BASE__RESULT is a result type: either a status (an error) or a value.
540//
541// A result with all fields NULL or zero is as valid as a zero-valued T.
542#define WUFFS_BASE__RESULT(T) \
543 struct { \
544 wuffs_base__status status; \
545 T value; \
546 }
547
548typedef WUFFS_BASE__RESULT(double) wuffs_base__result_f64;
549typedef WUFFS_BASE__RESULT(int64_t) wuffs_base__result_i64;
550typedef WUFFS_BASE__RESULT(uint64_t) wuffs_base__result_u64;
551
552// --------
553
554// wuffs_base__transform__output is the result of transforming from a src slice
555// to a dst slice.
556typedef struct wuffs_base__transform__output__struct {
557 wuffs_base__status status;
558 size_t num_dst;
559 size_t num_src;
560} wuffs_base__transform__output;
561
562// --------
563
Nigel Taobf9dab32021-11-18 19:19:55 +1100564// FourCC constants. Four Character Codes are literally four ASCII characters
565// (sometimes padded with ' ' spaces) that pack neatly into a signed or
566// unsigned 32-bit integer. ASCII letters are conventionally upper case.
567//
568// They are often used to identify video codecs (e.g. "H265") and pixel formats
569// (e.g. "YV12"). Wuffs uses them for that but also generally for naming
570// various things: compression formats (e.g. "BZ2 "), image metadata (e.g.
571// "EXIF"), file formats (e.g. "HTML"), etc.
572//
573// Wuffs' u32 values are big-endian ("JPEG" is 0x4A504547 not 0x4745504A) to
574// preserve ordering: "JPEG" < "MP3 " and 0x4A504547 < 0x4D503320.
575
576// Background Color.
577#define WUFFS_BASE__FOURCC__BGCL 0x4247434C
Nigel Taoe360a532021-04-05 22:47:03 +1000578
579// Bitmap.
580#define WUFFS_BASE__FOURCC__BMP 0x424D5020
581
582// Brotli.
583#define WUFFS_BASE__FOURCC__BRTL 0x4252544C
584
585// Bzip2.
586#define WUFFS_BASE__FOURCC__BZ2 0x425A3220
587
588// Concise Binary Object Representation.
589#define WUFFS_BASE__FOURCC__CBOR 0x43424F52
590
Nigel Taobf9dab32021-11-18 19:19:55 +1100591// Primary Chromaticities and White Point.
592#define WUFFS_BASE__FOURCC__CHRM 0x4348524D
593
Nigel Taoe360a532021-04-05 22:47:03 +1000594// Cascading Style Sheets.
595#define WUFFS_BASE__FOURCC__CSS 0x43535320
596
597// Encapsulated PostScript.
598#define WUFFS_BASE__FOURCC__EPS 0x45505320
599
Nigel Taobf9dab32021-11-18 19:19:55 +1100600// Exchangeable Image File Format.
601#define WUFFS_BASE__FOURCC__EXIF 0x45584946
602
Nigel Taoe360a532021-04-05 22:47:03 +1000603// Free Lossless Audio Codec.
604#define WUFFS_BASE__FOURCC__FLAC 0x464C4143
605
Nigel Taobf9dab32021-11-18 19:19:55 +1100606// Gamma Correction.
607#define WUFFS_BASE__FOURCC__GAMA 0x47414D41
608
Nigel Taoe360a532021-04-05 22:47:03 +1000609// Graphics Interchange Format.
610#define WUFFS_BASE__FOURCC__GIF 0x47494620
611
612// GNU Zip.
613#define WUFFS_BASE__FOURCC__GZ 0x475A2020
614
615// High Efficiency Image File.
616#define WUFFS_BASE__FOURCC__HEIF 0x48454946
617
618// Hypertext Markup Language.
619#define WUFFS_BASE__FOURCC__HTML 0x48544D4C
620
621// International Color Consortium Profile.
622#define WUFFS_BASE__FOURCC__ICCP 0x49434350
623
624// Icon.
625#define WUFFS_BASE__FOURCC__ICO 0x49434F20
626
627// Icon Vector Graphics.
628#define WUFFS_BASE__FOURCC__ICVG 0x49435647
629
630// Initialization.
631#define WUFFS_BASE__FOURCC__INI 0x494E4920
632
633// Joint Photographic Experts Group.
634#define WUFFS_BASE__FOURCC__JPEG 0x4A504547
635
636// JavaScript.
637#define WUFFS_BASE__FOURCC__JS 0x4A532020
638
639// JavaScript Object Notation.
640#define WUFFS_BASE__FOURCC__JSON 0x4A534F4E
641
642// JSON With Commas and Comments.
643#define WUFFS_BASE__FOURCC__JWCC 0x4A574343
644
Nigel Taobf9dab32021-11-18 19:19:55 +1100645// Key-Value Pair.
646#define WUFFS_BASE__FOURCC__KVP 0x4B565020
647
648// Key-Value Pair (Key).
649#define WUFFS_BASE__FOURCC__KVPK 0x4B56504B
650
651// Key-Value Pair (Value).
652#define WUFFS_BASE__FOURCC__KVPV 0x4B565056
653
Nigel Taoe360a532021-04-05 22:47:03 +1000654// Lempel–Ziv 4.
655#define WUFFS_BASE__FOURCC__LZ4 0x4C5A3420
656
657// Markdown.
658#define WUFFS_BASE__FOURCC__MD 0x4D442020
659
Nigel Taobf9dab32021-11-18 19:19:55 +1100660// Modification Time.
661#define WUFFS_BASE__FOURCC__MTIM 0x4D54494D
662
Nigel Taoe360a532021-04-05 22:47:03 +1000663// MPEG-1 Audio Layer III.
664#define WUFFS_BASE__FOURCC__MP3 0x4D503320
665
666// Naive Image.
667#define WUFFS_BASE__FOURCC__NIE 0x4E494520
668
Nigel Taobf9dab32021-11-18 19:19:55 +1100669// Offset (2-Dimensional).
670#define WUFFS_BASE__FOURCC__OFS2 0x4F465332
671
Nigel Taoe360a532021-04-05 22:47:03 +1000672// Open Type Format.
673#define WUFFS_BASE__FOURCC__OTF 0x4F544620
674
675// Portable Document Format.
676#define WUFFS_BASE__FOURCC__PDF 0x50444620
677
Nigel Taobf9dab32021-11-18 19:19:55 +1100678// Physical Dimensions.
679#define WUFFS_BASE__FOURCC__PHYD 0x50485944
680
Nigel Taoe360a532021-04-05 22:47:03 +1000681// Portable Network Graphics.
682#define WUFFS_BASE__FOURCC__PNG 0x504E4720
683
684// Portable Anymap.
685#define WUFFS_BASE__FOURCC__PNM 0x504E4D20
686
687// PostScript.
688#define WUFFS_BASE__FOURCC__PS 0x50532020
689
690// Random Access Compression.
691#define WUFFS_BASE__FOURCC__RAC 0x52414320
692
693// Raw.
694#define WUFFS_BASE__FOURCC__RAW 0x52415720
695
696// Resource Interchange File Format.
697#define WUFFS_BASE__FOURCC__RIFF 0x52494646
698
699// Riegeli Records.
700#define WUFFS_BASE__FOURCC__RIGL 0x5249474C
701
702// Snappy.
703#define WUFFS_BASE__FOURCC__SNPY 0x534E5059
704
Nigel Taobf9dab32021-11-18 19:19:55 +1100705// Standard Red Green Blue (Rendering Intent).
706#define WUFFS_BASE__FOURCC__SRGB 0x53524742
707
Nigel Taoe360a532021-04-05 22:47:03 +1000708// Scalable Vector Graphics.
709#define WUFFS_BASE__FOURCC__SVG 0x53564720
710
711// Tape Archive.
712#define WUFFS_BASE__FOURCC__TAR 0x54415220
713
Nigel Taobf9dab32021-11-18 19:19:55 +1100714// Text.
715#define WUFFS_BASE__FOURCC__TEXT 0x54455854
716
Nigel Taoe360a532021-04-05 22:47:03 +1000717// Tagged Image File Format.
718#define WUFFS_BASE__FOURCC__TIFF 0x54494646
719
720// Tom's Obvious Minimal Language.
721#define WUFFS_BASE__FOURCC__TOML 0x544F4D4C
722
723// Waveform.
724#define WUFFS_BASE__FOURCC__WAVE 0x57415645
725
726// Wireless Bitmap.
727#define WUFFS_BASE__FOURCC__WBMP 0x57424D50
728
729// Web Open Font Format.
730#define WUFFS_BASE__FOURCC__WOFF 0x574F4646
731
732// Web Picture (VP8).
733#define WUFFS_BASE__FOURCC__WP8 0x57503820
734
735// Web Picture (VP8 Lossless).
736#define WUFFS_BASE__FOURCC__WP8L 0x5750384C
737
738// Extensible Markup Language.
739#define WUFFS_BASE__FOURCC__XML 0x584D4C20
740
741// Extensible Metadata Platform.
742#define WUFFS_BASE__FOURCC__XMP 0x584D5020
743
744// Xz.
745#define WUFFS_BASE__FOURCC__XZ 0x585A2020
746
747// Zip.
748#define WUFFS_BASE__FOURCC__ZIP 0x5A495020
749
750// Zlib.
751#define WUFFS_BASE__FOURCC__ZLIB 0x5A4C4942
752
753// Zstandard.
754#define WUFFS_BASE__FOURCC__ZSTD 0x5A535444
755
756// --------
757
758// Quirks.
759
760#define WUFFS_BASE__QUIRK_IGNORE_CHECKSUM 1
761
762// --------
763
764// Flicks are a unit of time. One flick (frame-tick) is 1 / 705_600_000 of a
765// second. See https://github.com/OculusVR/Flicks
766typedef int64_t wuffs_base__flicks;
767
768#define WUFFS_BASE__FLICKS_PER_SECOND ((uint64_t)705600000)
769#define WUFFS_BASE__FLICKS_PER_MILLISECOND ((uint64_t)705600)
770
771// ---------------- Numeric Types
772
773// The helpers below are functions, instead of macros, because their arguments
774// can be an expression that we shouldn't evaluate more than once.
775//
776// They are static, so that linking multiple wuffs .o files won't complain about
777// duplicate function definitions.
778//
779// They are explicitly marked inline, even if modern compilers don't use the
780// inline attribute to guide optimizations such as inlining, to avoid the
781// -Wunused-function warning, and we like to compile with -Wall -Werror.
782
783static inline int8_t //
784wuffs_base__i8__min(int8_t x, int8_t y) {
785 return x < y ? x : y;
786}
787
788static inline int8_t //
789wuffs_base__i8__max(int8_t x, int8_t y) {
790 return x > y ? x : y;
791}
792
793static inline int16_t //
794wuffs_base__i16__min(int16_t x, int16_t y) {
795 return x < y ? x : y;
796}
797
798static inline int16_t //
799wuffs_base__i16__max(int16_t x, int16_t y) {
800 return x > y ? x : y;
801}
802
803static inline int32_t //
804wuffs_base__i32__min(int32_t x, int32_t y) {
805 return x < y ? x : y;
806}
807
808static inline int32_t //
809wuffs_base__i32__max(int32_t x, int32_t y) {
810 return x > y ? x : y;
811}
812
813static inline int64_t //
814wuffs_base__i64__min(int64_t x, int64_t y) {
815 return x < y ? x : y;
816}
817
818static inline int64_t //
819wuffs_base__i64__max(int64_t x, int64_t y) {
820 return x > y ? x : y;
821}
822
823static inline uint8_t //
824wuffs_base__u8__min(uint8_t x, uint8_t y) {
825 return x < y ? x : y;
826}
827
828static inline uint8_t //
829wuffs_base__u8__max(uint8_t x, uint8_t y) {
830 return x > y ? x : y;
831}
832
833static inline uint16_t //
834wuffs_base__u16__min(uint16_t x, uint16_t y) {
835 return x < y ? x : y;
836}
837
838static inline uint16_t //
839wuffs_base__u16__max(uint16_t x, uint16_t y) {
840 return x > y ? x : y;
841}
842
843static inline uint32_t //
844wuffs_base__u32__min(uint32_t x, uint32_t y) {
845 return x < y ? x : y;
846}
847
848static inline uint32_t //
849wuffs_base__u32__max(uint32_t x, uint32_t y) {
850 return x > y ? x : y;
851}
852
853static inline uint64_t //
854wuffs_base__u64__min(uint64_t x, uint64_t y) {
855 return x < y ? x : y;
856}
857
858static inline uint64_t //
859wuffs_base__u64__max(uint64_t x, uint64_t y) {
860 return x > y ? x : y;
861}
862
863// --------
864
Nigel Taof3caaea2021-06-28 10:12:04 +1000865static inline uint8_t //
866wuffs_base__u8__rotate_left(uint8_t x, uint32_t n) {
867 n &= 7;
868 return ((uint8_t)(x << n)) | ((uint8_t)(x >> (8 - n)));
869}
870
871static inline uint8_t //
872wuffs_base__u8__rotate_right(uint8_t x, uint32_t n) {
873 n &= 7;
874 return ((uint8_t)(x >> n)) | ((uint8_t)(x << (8 - n)));
875}
876
877static inline uint16_t //
878wuffs_base__u16__rotate_left(uint16_t x, uint32_t n) {
879 n &= 15;
880 return ((uint16_t)(x << n)) | ((uint16_t)(x >> (16 - n)));
881}
882
883static inline uint16_t //
884wuffs_base__u16__rotate_right(uint16_t x, uint32_t n) {
885 n &= 15;
886 return ((uint16_t)(x >> n)) | ((uint16_t)(x << (16 - n)));
887}
888
889static inline uint32_t //
890wuffs_base__u32__rotate_left(uint32_t x, uint32_t n) {
891 n &= 31;
892 return ((uint32_t)(x << n)) | ((uint32_t)(x >> (32 - n)));
893}
894
895static inline uint32_t //
896wuffs_base__u32__rotate_right(uint32_t x, uint32_t n) {
897 n &= 31;
898 return ((uint32_t)(x >> n)) | ((uint32_t)(x << (32 - n)));
899}
900
901static inline uint64_t //
902wuffs_base__u64__rotate_left(uint64_t x, uint32_t n) {
903 n &= 63;
904 return ((uint64_t)(x << n)) | ((uint64_t)(x >> (64 - n)));
905}
906
907static inline uint64_t //
908wuffs_base__u64__rotate_right(uint64_t x, uint32_t n) {
909 n &= 63;
910 return ((uint64_t)(x >> n)) | ((uint64_t)(x << (64 - n)));
911}
912
913// --------
914
Nigel Taoe360a532021-04-05 22:47:03 +1000915// Saturating arithmetic (sat_add, sat_sub) branchless bit-twiddling algorithms
916// are per https://locklessinc.com/articles/sat_arithmetic/
917//
918// It is important that the underlying types are unsigned integers, as signed
919// integer arithmetic overflow is undefined behavior in C.
920
921static inline uint8_t //
922wuffs_base__u8__sat_add(uint8_t x, uint8_t y) {
923 uint8_t res = (uint8_t)(x + y);
924 res |= (uint8_t)(-(res < x));
925 return res;
926}
927
928static inline uint8_t //
929wuffs_base__u8__sat_sub(uint8_t x, uint8_t y) {
930 uint8_t res = (uint8_t)(x - y);
931 res &= (uint8_t)(-(res <= x));
932 return res;
933}
934
935static inline uint16_t //
936wuffs_base__u16__sat_add(uint16_t x, uint16_t y) {
937 uint16_t res = (uint16_t)(x + y);
938 res |= (uint16_t)(-(res < x));
939 return res;
940}
941
942static inline uint16_t //
943wuffs_base__u16__sat_sub(uint16_t x, uint16_t y) {
944 uint16_t res = (uint16_t)(x - y);
945 res &= (uint16_t)(-(res <= x));
946 return res;
947}
948
949static inline uint32_t //
950wuffs_base__u32__sat_add(uint32_t x, uint32_t y) {
951 uint32_t res = (uint32_t)(x + y);
952 res |= (uint32_t)(-(res < x));
953 return res;
954}
955
956static inline uint32_t //
957wuffs_base__u32__sat_sub(uint32_t x, uint32_t y) {
958 uint32_t res = (uint32_t)(x - y);
959 res &= (uint32_t)(-(res <= x));
960 return res;
961}
962
963static inline uint64_t //
964wuffs_base__u64__sat_add(uint64_t x, uint64_t y) {
965 uint64_t res = (uint64_t)(x + y);
966 res |= (uint64_t)(-(res < x));
967 return res;
968}
969
970static inline uint64_t //
971wuffs_base__u64__sat_sub(uint64_t x, uint64_t y) {
972 uint64_t res = (uint64_t)(x - y);
973 res &= (uint64_t)(-(res <= x));
974 return res;
975}
976
977// --------
978
979typedef struct wuffs_base__multiply_u64__output__struct {
980 uint64_t lo;
981 uint64_t hi;
982} wuffs_base__multiply_u64__output;
983
984// wuffs_base__multiply_u64 returns x*y as a 128-bit value.
985//
986// The maximum inclusive output hi_lo is 0xFFFFFFFFFFFFFFFE_0000000000000001.
987static inline wuffs_base__multiply_u64__output //
988wuffs_base__multiply_u64(uint64_t x, uint64_t y) {
989#if defined(__SIZEOF_INT128__)
990 __uint128_t z = ((__uint128_t)x) * ((__uint128_t)y);
991 wuffs_base__multiply_u64__output o;
992 o.lo = ((uint64_t)(z));
993 o.hi = ((uint64_t)(z >> 64));
994 return o;
995#else
996 // TODO: consider using the _mul128 intrinsic if defined(_MSC_VER).
997 uint64_t x0 = x & 0xFFFFFFFF;
998 uint64_t x1 = x >> 32;
999 uint64_t y0 = y & 0xFFFFFFFF;
1000 uint64_t y1 = y >> 32;
1001 uint64_t w0 = x0 * y0;
1002 uint64_t t = (x1 * y0) + (w0 >> 32);
1003 uint64_t w1 = t & 0xFFFFFFFF;
1004 uint64_t w2 = t >> 32;
1005 w1 += x0 * y1;
1006 wuffs_base__multiply_u64__output o;
1007 o.lo = x * y;
1008 o.hi = (x1 * y1) + w2 + (w1 >> 32);
1009 return o;
1010#endif
1011}
1012
1013// --------
1014
Nigel Taobf9dab32021-11-18 19:19:55 +11001015// The "defined(__clang__)" isn't redundant. While vanilla clang defines
1016// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not.
1017#if (defined(__GNUC__) || defined(__clang__)) && (__SIZEOF_LONG__ == 8)
Nigel Taoe360a532021-04-05 22:47:03 +10001018
1019static inline uint32_t //
1020wuffs_base__count_leading_zeroes_u64(uint64_t u) {
1021 return u ? ((uint32_t)(__builtin_clzl(u))) : 64u;
1022}
1023
1024#else
1025// TODO: consider using the _BitScanReverse intrinsic if defined(_MSC_VER).
1026
1027static inline uint32_t //
1028wuffs_base__count_leading_zeroes_u64(uint64_t u) {
1029 if (u == 0) {
1030 return 64;
1031 }
1032
1033 uint32_t n = 0;
1034 if ((u >> 32) == 0) {
1035 n |= 32;
1036 u <<= 32;
1037 }
1038 if ((u >> 48) == 0) {
1039 n |= 16;
1040 u <<= 16;
1041 }
1042 if ((u >> 56) == 0) {
1043 n |= 8;
1044 u <<= 8;
1045 }
1046 if ((u >> 60) == 0) {
1047 n |= 4;
1048 u <<= 4;
1049 }
1050 if ((u >> 62) == 0) {
1051 n |= 2;
1052 u <<= 2;
1053 }
1054 if ((u >> 63) == 0) {
1055 n |= 1;
1056 u <<= 1;
1057 }
1058 return n;
1059}
1060
Nigel Taobf9dab32021-11-18 19:19:55 +11001061#endif // (defined(__GNUC__) || defined(__clang__)) && (__SIZEOF_LONG__ == 8)
Nigel Taoe360a532021-04-05 22:47:03 +10001062
1063// --------
1064
1065#define wuffs_base__peek_u8be__no_bounds_check \
1066 wuffs_base__peek_u8__no_bounds_check
1067#define wuffs_base__peek_u8le__no_bounds_check \
1068 wuffs_base__peek_u8__no_bounds_check
1069
1070static inline uint8_t //
1071wuffs_base__peek_u8__no_bounds_check(const uint8_t* p) {
1072 return p[0];
1073}
1074
1075static inline uint16_t //
1076wuffs_base__peek_u16be__no_bounds_check(const uint8_t* p) {
1077 return (uint16_t)(((uint16_t)(p[0]) << 8) | ((uint16_t)(p[1]) << 0));
1078}
1079
1080static inline uint16_t //
1081wuffs_base__peek_u16le__no_bounds_check(const uint8_t* p) {
1082 return (uint16_t)(((uint16_t)(p[0]) << 0) | ((uint16_t)(p[1]) << 8));
1083}
1084
1085static inline uint32_t //
1086wuffs_base__peek_u24be__no_bounds_check(const uint8_t* p) {
1087 return ((uint32_t)(p[0]) << 16) | ((uint32_t)(p[1]) << 8) |
1088 ((uint32_t)(p[2]) << 0);
1089}
1090
1091static inline uint32_t //
1092wuffs_base__peek_u24le__no_bounds_check(const uint8_t* p) {
1093 return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
1094 ((uint32_t)(p[2]) << 16);
1095}
1096
1097static inline uint32_t //
1098wuffs_base__peek_u32be__no_bounds_check(const uint8_t* p) {
1099 return ((uint32_t)(p[0]) << 24) | ((uint32_t)(p[1]) << 16) |
1100 ((uint32_t)(p[2]) << 8) | ((uint32_t)(p[3]) << 0);
1101}
1102
1103static inline uint32_t //
1104wuffs_base__peek_u32le__no_bounds_check(const uint8_t* p) {
1105 return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
1106 ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24);
1107}
1108
1109static inline uint64_t //
1110wuffs_base__peek_u40be__no_bounds_check(const uint8_t* p) {
1111 return ((uint64_t)(p[0]) << 32) | ((uint64_t)(p[1]) << 24) |
1112 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 8) |
1113 ((uint64_t)(p[4]) << 0);
1114}
1115
1116static inline uint64_t //
1117wuffs_base__peek_u40le__no_bounds_check(const uint8_t* p) {
1118 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
1119 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
1120 ((uint64_t)(p[4]) << 32);
1121}
1122
1123static inline uint64_t //
1124wuffs_base__peek_u48be__no_bounds_check(const uint8_t* p) {
1125 return ((uint64_t)(p[0]) << 40) | ((uint64_t)(p[1]) << 32) |
1126 ((uint64_t)(p[2]) << 24) | ((uint64_t)(p[3]) << 16) |
1127 ((uint64_t)(p[4]) << 8) | ((uint64_t)(p[5]) << 0);
1128}
1129
1130static inline uint64_t //
1131wuffs_base__peek_u48le__no_bounds_check(const uint8_t* p) {
1132 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
1133 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
1134 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40);
1135}
1136
1137static inline uint64_t //
1138wuffs_base__peek_u56be__no_bounds_check(const uint8_t* p) {
1139 return ((uint64_t)(p[0]) << 48) | ((uint64_t)(p[1]) << 40) |
1140 ((uint64_t)(p[2]) << 32) | ((uint64_t)(p[3]) << 24) |
1141 ((uint64_t)(p[4]) << 16) | ((uint64_t)(p[5]) << 8) |
1142 ((uint64_t)(p[6]) << 0);
1143}
1144
1145static inline uint64_t //
1146wuffs_base__peek_u56le__no_bounds_check(const uint8_t* p) {
1147 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
1148 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
1149 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
1150 ((uint64_t)(p[6]) << 48);
1151}
1152
1153static inline uint64_t //
1154wuffs_base__peek_u64be__no_bounds_check(const uint8_t* p) {
1155 return ((uint64_t)(p[0]) << 56) | ((uint64_t)(p[1]) << 48) |
1156 ((uint64_t)(p[2]) << 40) | ((uint64_t)(p[3]) << 32) |
1157 ((uint64_t)(p[4]) << 24) | ((uint64_t)(p[5]) << 16) |
1158 ((uint64_t)(p[6]) << 8) | ((uint64_t)(p[7]) << 0);
1159}
1160
1161static inline uint64_t //
1162wuffs_base__peek_u64le__no_bounds_check(const uint8_t* p) {
1163 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
1164 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
1165 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
1166 ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56);
1167}
1168
1169// --------
1170
1171#define wuffs_base__poke_u8be__no_bounds_check \
1172 wuffs_base__poke_u8__no_bounds_check
1173#define wuffs_base__poke_u8le__no_bounds_check \
1174 wuffs_base__poke_u8__no_bounds_check
1175
1176static inline void //
1177wuffs_base__poke_u8__no_bounds_check(uint8_t* p, uint8_t x) {
1178 p[0] = x;
1179}
1180
1181static inline void //
1182wuffs_base__poke_u16be__no_bounds_check(uint8_t* p, uint16_t x) {
1183 p[0] = (uint8_t)(x >> 8);
1184 p[1] = (uint8_t)(x >> 0);
1185}
1186
1187static inline void //
1188wuffs_base__poke_u16le__no_bounds_check(uint8_t* p, uint16_t x) {
1189#if defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__)
1190 // This seems to perform better on gcc 10 (but not clang 9). Clang also
1191 // defines "__GNUC__".
1192 memcpy(p, &x, 2);
1193#else
1194 p[0] = (uint8_t)(x >> 0);
1195 p[1] = (uint8_t)(x >> 8);
1196#endif
1197}
1198
1199static inline void //
1200wuffs_base__poke_u24be__no_bounds_check(uint8_t* p, uint32_t x) {
1201 p[0] = (uint8_t)(x >> 16);
1202 p[1] = (uint8_t)(x >> 8);
1203 p[2] = (uint8_t)(x >> 0);
1204}
1205
1206static inline void //
1207wuffs_base__poke_u24le__no_bounds_check(uint8_t* p, uint32_t x) {
1208 p[0] = (uint8_t)(x >> 0);
1209 p[1] = (uint8_t)(x >> 8);
1210 p[2] = (uint8_t)(x >> 16);
1211}
1212
1213static inline void //
1214wuffs_base__poke_u32be__no_bounds_check(uint8_t* p, uint32_t x) {
1215 p[0] = (uint8_t)(x >> 24);
1216 p[1] = (uint8_t)(x >> 16);
1217 p[2] = (uint8_t)(x >> 8);
1218 p[3] = (uint8_t)(x >> 0);
1219}
1220
1221static inline void //
1222wuffs_base__poke_u32le__no_bounds_check(uint8_t* p, uint32_t x) {
1223#if defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__)
1224 // This seems to perform better on gcc 10 (but not clang 9). Clang also
1225 // defines "__GNUC__".
1226 memcpy(p, &x, 4);
1227#else
1228 p[0] = (uint8_t)(x >> 0);
1229 p[1] = (uint8_t)(x >> 8);
1230 p[2] = (uint8_t)(x >> 16);
1231 p[3] = (uint8_t)(x >> 24);
1232#endif
1233}
1234
1235static inline void //
1236wuffs_base__poke_u40be__no_bounds_check(uint8_t* p, uint64_t x) {
1237 p[0] = (uint8_t)(x >> 32);
1238 p[1] = (uint8_t)(x >> 24);
1239 p[2] = (uint8_t)(x >> 16);
1240 p[3] = (uint8_t)(x >> 8);
1241 p[4] = (uint8_t)(x >> 0);
1242}
1243
1244static inline void //
1245wuffs_base__poke_u40le__no_bounds_check(uint8_t* p, uint64_t x) {
1246 p[0] = (uint8_t)(x >> 0);
1247 p[1] = (uint8_t)(x >> 8);
1248 p[2] = (uint8_t)(x >> 16);
1249 p[3] = (uint8_t)(x >> 24);
1250 p[4] = (uint8_t)(x >> 32);
1251}
1252
1253static inline void //
1254wuffs_base__poke_u48be__no_bounds_check(uint8_t* p, uint64_t x) {
1255 p[0] = (uint8_t)(x >> 40);
1256 p[1] = (uint8_t)(x >> 32);
1257 p[2] = (uint8_t)(x >> 24);
1258 p[3] = (uint8_t)(x >> 16);
1259 p[4] = (uint8_t)(x >> 8);
1260 p[5] = (uint8_t)(x >> 0);
1261}
1262
1263static inline void //
1264wuffs_base__poke_u48le__no_bounds_check(uint8_t* p, uint64_t x) {
1265 p[0] = (uint8_t)(x >> 0);
1266 p[1] = (uint8_t)(x >> 8);
1267 p[2] = (uint8_t)(x >> 16);
1268 p[3] = (uint8_t)(x >> 24);
1269 p[4] = (uint8_t)(x >> 32);
1270 p[5] = (uint8_t)(x >> 40);
1271}
1272
1273static inline void //
1274wuffs_base__poke_u56be__no_bounds_check(uint8_t* p, uint64_t x) {
1275 p[0] = (uint8_t)(x >> 48);
1276 p[1] = (uint8_t)(x >> 40);
1277 p[2] = (uint8_t)(x >> 32);
1278 p[3] = (uint8_t)(x >> 24);
1279 p[4] = (uint8_t)(x >> 16);
1280 p[5] = (uint8_t)(x >> 8);
1281 p[6] = (uint8_t)(x >> 0);
1282}
1283
1284static inline void //
1285wuffs_base__poke_u56le__no_bounds_check(uint8_t* p, uint64_t x) {
1286 p[0] = (uint8_t)(x >> 0);
1287 p[1] = (uint8_t)(x >> 8);
1288 p[2] = (uint8_t)(x >> 16);
1289 p[3] = (uint8_t)(x >> 24);
1290 p[4] = (uint8_t)(x >> 32);
1291 p[5] = (uint8_t)(x >> 40);
1292 p[6] = (uint8_t)(x >> 48);
1293}
1294
1295static inline void //
1296wuffs_base__poke_u64be__no_bounds_check(uint8_t* p, uint64_t x) {
1297 p[0] = (uint8_t)(x >> 56);
1298 p[1] = (uint8_t)(x >> 48);
1299 p[2] = (uint8_t)(x >> 40);
1300 p[3] = (uint8_t)(x >> 32);
1301 p[4] = (uint8_t)(x >> 24);
1302 p[5] = (uint8_t)(x >> 16);
1303 p[6] = (uint8_t)(x >> 8);
1304 p[7] = (uint8_t)(x >> 0);
1305}
1306
1307static inline void //
1308wuffs_base__poke_u64le__no_bounds_check(uint8_t* p, uint64_t x) {
1309#if defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__)
1310 // This seems to perform better on gcc 10 (but not clang 9). Clang also
1311 // defines "__GNUC__".
1312 memcpy(p, &x, 8);
1313#else
1314 p[0] = (uint8_t)(x >> 0);
1315 p[1] = (uint8_t)(x >> 8);
1316 p[2] = (uint8_t)(x >> 16);
1317 p[3] = (uint8_t)(x >> 24);
1318 p[4] = (uint8_t)(x >> 32);
1319 p[5] = (uint8_t)(x >> 40);
1320 p[6] = (uint8_t)(x >> 48);
1321 p[7] = (uint8_t)(x >> 56);
1322#endif
1323}
1324
1325// --------
1326
1327// Load and Store functions are deprecated. Use Peek and Poke instead.
1328
1329#define wuffs_base__load_u8__no_bounds_check \
1330 wuffs_base__peek_u8__no_bounds_check
1331#define wuffs_base__load_u16be__no_bounds_check \
1332 wuffs_base__peek_u16be__no_bounds_check
1333#define wuffs_base__load_u16le__no_bounds_check \
1334 wuffs_base__peek_u16le__no_bounds_check
1335#define wuffs_base__load_u24be__no_bounds_check \
1336 wuffs_base__peek_u24be__no_bounds_check
1337#define wuffs_base__load_u24le__no_bounds_check \
1338 wuffs_base__peek_u24le__no_bounds_check
1339#define wuffs_base__load_u32be__no_bounds_check \
1340 wuffs_base__peek_u32be__no_bounds_check
1341#define wuffs_base__load_u32le__no_bounds_check \
1342 wuffs_base__peek_u32le__no_bounds_check
1343#define wuffs_base__load_u40be__no_bounds_check \
1344 wuffs_base__peek_u40be__no_bounds_check
1345#define wuffs_base__load_u40le__no_bounds_check \
1346 wuffs_base__peek_u40le__no_bounds_check
1347#define wuffs_base__load_u48be__no_bounds_check \
1348 wuffs_base__peek_u48be__no_bounds_check
1349#define wuffs_base__load_u48le__no_bounds_check \
1350 wuffs_base__peek_u48le__no_bounds_check
1351#define wuffs_base__load_u56be__no_bounds_check \
1352 wuffs_base__peek_u56be__no_bounds_check
1353#define wuffs_base__load_u56le__no_bounds_check \
1354 wuffs_base__peek_u56le__no_bounds_check
1355#define wuffs_base__load_u64be__no_bounds_check \
1356 wuffs_base__peek_u64be__no_bounds_check
1357#define wuffs_base__load_u64le__no_bounds_check \
1358 wuffs_base__peek_u64le__no_bounds_check
1359
1360#define wuffs_base__store_u8__no_bounds_check \
1361 wuffs_base__poke_u8__no_bounds_check
1362#define wuffs_base__store_u16be__no_bounds_check \
1363 wuffs_base__poke_u16be__no_bounds_check
1364#define wuffs_base__store_u16le__no_bounds_check \
1365 wuffs_base__poke_u16le__no_bounds_check
1366#define wuffs_base__store_u24be__no_bounds_check \
1367 wuffs_base__poke_u24be__no_bounds_check
1368#define wuffs_base__store_u24le__no_bounds_check \
1369 wuffs_base__poke_u24le__no_bounds_check
1370#define wuffs_base__store_u32be__no_bounds_check \
1371 wuffs_base__poke_u32be__no_bounds_check
1372#define wuffs_base__store_u32le__no_bounds_check \
1373 wuffs_base__poke_u32le__no_bounds_check
1374#define wuffs_base__store_u40be__no_bounds_check \
1375 wuffs_base__poke_u40be__no_bounds_check
1376#define wuffs_base__store_u40le__no_bounds_check \
1377 wuffs_base__poke_u40le__no_bounds_check
1378#define wuffs_base__store_u48be__no_bounds_check \
1379 wuffs_base__poke_u48be__no_bounds_check
1380#define wuffs_base__store_u48le__no_bounds_check \
1381 wuffs_base__poke_u48le__no_bounds_check
1382#define wuffs_base__store_u56be__no_bounds_check \
1383 wuffs_base__poke_u56be__no_bounds_check
1384#define wuffs_base__store_u56le__no_bounds_check \
1385 wuffs_base__poke_u56le__no_bounds_check
1386#define wuffs_base__store_u64be__no_bounds_check \
1387 wuffs_base__poke_u64be__no_bounds_check
1388#define wuffs_base__store_u64le__no_bounds_check \
1389 wuffs_base__poke_u64le__no_bounds_check
1390
1391// ---------------- Slices and Tables
1392
1393// WUFFS_BASE__SLICE is a 1-dimensional buffer.
1394//
1395// len measures a number of elements, not necessarily a size in bytes.
1396//
1397// A value with all fields NULL or zero is a valid, empty slice.
1398#define WUFFS_BASE__SLICE(T) \
1399 struct { \
1400 T* ptr; \
1401 size_t len; \
1402 }
1403
1404// WUFFS_BASE__TABLE is a 2-dimensional buffer.
1405//
1406// width, height and stride measure a number of elements, not necessarily a
1407// size in bytes.
1408//
1409// A value with all fields NULL or zero is a valid, empty table.
1410#define WUFFS_BASE__TABLE(T) \
1411 struct { \
1412 T* ptr; \
1413 size_t width; \
1414 size_t height; \
1415 size_t stride; \
1416 }
1417
1418typedef WUFFS_BASE__SLICE(uint8_t) wuffs_base__slice_u8;
1419typedef WUFFS_BASE__SLICE(uint16_t) wuffs_base__slice_u16;
1420typedef WUFFS_BASE__SLICE(uint32_t) wuffs_base__slice_u32;
1421typedef WUFFS_BASE__SLICE(uint64_t) wuffs_base__slice_u64;
1422
1423typedef WUFFS_BASE__TABLE(uint8_t) wuffs_base__table_u8;
1424typedef WUFFS_BASE__TABLE(uint16_t) wuffs_base__table_u16;
1425typedef WUFFS_BASE__TABLE(uint32_t) wuffs_base__table_u32;
1426typedef WUFFS_BASE__TABLE(uint64_t) wuffs_base__table_u64;
1427
1428static inline wuffs_base__slice_u8 //
1429wuffs_base__make_slice_u8(uint8_t* ptr, size_t len) {
1430 wuffs_base__slice_u8 ret;
1431 ret.ptr = ptr;
1432 ret.len = len;
1433 return ret;
1434}
1435
1436static inline wuffs_base__slice_u16 //
1437wuffs_base__make_slice_u16(uint16_t* ptr, size_t len) {
1438 wuffs_base__slice_u16 ret;
1439 ret.ptr = ptr;
1440 ret.len = len;
1441 return ret;
1442}
1443
1444static inline wuffs_base__slice_u32 //
1445wuffs_base__make_slice_u32(uint32_t* ptr, size_t len) {
1446 wuffs_base__slice_u32 ret;
1447 ret.ptr = ptr;
1448 ret.len = len;
1449 return ret;
1450}
1451
1452static inline wuffs_base__slice_u64 //
1453wuffs_base__make_slice_u64(uint64_t* ptr, size_t len) {
1454 wuffs_base__slice_u64 ret;
1455 ret.ptr = ptr;
1456 ret.len = len;
1457 return ret;
1458}
1459
1460static inline wuffs_base__slice_u8 //
1461wuffs_base__empty_slice_u8() {
1462 wuffs_base__slice_u8 ret;
1463 ret.ptr = NULL;
1464 ret.len = 0;
1465 return ret;
1466}
1467
1468static inline wuffs_base__slice_u16 //
1469wuffs_base__empty_slice_u16() {
1470 wuffs_base__slice_u16 ret;
1471 ret.ptr = NULL;
1472 ret.len = 0;
1473 return ret;
1474}
1475
1476static inline wuffs_base__slice_u32 //
1477wuffs_base__empty_slice_u32() {
1478 wuffs_base__slice_u32 ret;
1479 ret.ptr = NULL;
1480 ret.len = 0;
1481 return ret;
1482}
1483
1484static inline wuffs_base__slice_u64 //
1485wuffs_base__empty_slice_u64() {
1486 wuffs_base__slice_u64 ret;
1487 ret.ptr = NULL;
1488 ret.len = 0;
1489 return ret;
1490}
1491
1492static inline wuffs_base__table_u8 //
1493wuffs_base__make_table_u8(uint8_t* ptr,
1494 size_t width,
1495 size_t height,
1496 size_t stride) {
1497 wuffs_base__table_u8 ret;
1498 ret.ptr = ptr;
1499 ret.width = width;
1500 ret.height = height;
1501 ret.stride = stride;
1502 return ret;
1503}
1504
1505static inline wuffs_base__table_u16 //
1506wuffs_base__make_table_u16(uint16_t* ptr,
1507 size_t width,
1508 size_t height,
1509 size_t stride) {
1510 wuffs_base__table_u16 ret;
1511 ret.ptr = ptr;
1512 ret.width = width;
1513 ret.height = height;
1514 ret.stride = stride;
1515 return ret;
1516}
1517
1518static inline wuffs_base__table_u32 //
1519wuffs_base__make_table_u32(uint32_t* ptr,
1520 size_t width,
1521 size_t height,
1522 size_t stride) {
1523 wuffs_base__table_u32 ret;
1524 ret.ptr = ptr;
1525 ret.width = width;
1526 ret.height = height;
1527 ret.stride = stride;
1528 return ret;
1529}
1530
1531static inline wuffs_base__table_u64 //
1532wuffs_base__make_table_u64(uint64_t* ptr,
1533 size_t width,
1534 size_t height,
1535 size_t stride) {
1536 wuffs_base__table_u64 ret;
1537 ret.ptr = ptr;
1538 ret.width = width;
1539 ret.height = height;
1540 ret.stride = stride;
1541 return ret;
1542}
1543
1544static inline wuffs_base__table_u8 //
1545wuffs_base__empty_table_u8() {
1546 wuffs_base__table_u8 ret;
1547 ret.ptr = NULL;
1548 ret.width = 0;
1549 ret.height = 0;
1550 ret.stride = 0;
1551 return ret;
1552}
1553
1554static inline wuffs_base__table_u16 //
1555wuffs_base__empty_table_u16() {
1556 wuffs_base__table_u16 ret;
1557 ret.ptr = NULL;
1558 ret.width = 0;
1559 ret.height = 0;
1560 ret.stride = 0;
1561 return ret;
1562}
1563
1564static inline wuffs_base__table_u32 //
1565wuffs_base__empty_table_u32() {
1566 wuffs_base__table_u32 ret;
1567 ret.ptr = NULL;
1568 ret.width = 0;
1569 ret.height = 0;
1570 ret.stride = 0;
1571 return ret;
1572}
1573
1574static inline wuffs_base__table_u64 //
1575wuffs_base__empty_table_u64() {
1576 wuffs_base__table_u64 ret;
1577 ret.ptr = NULL;
1578 ret.width = 0;
1579 ret.height = 0;
1580 ret.stride = 0;
1581 return ret;
1582}
1583
1584static inline bool //
1585wuffs_base__slice_u8__overlaps(wuffs_base__slice_u8 s, wuffs_base__slice_u8 t) {
1586 return ((s.ptr <= t.ptr) && (t.ptr < (s.ptr + s.len))) ||
1587 ((t.ptr <= s.ptr) && (s.ptr < (t.ptr + t.len)));
1588}
1589
1590// wuffs_base__slice_u8__subslice_i returns s[i:].
1591//
1592// It returns an empty slice if i is out of bounds.
1593static inline wuffs_base__slice_u8 //
1594wuffs_base__slice_u8__subslice_i(wuffs_base__slice_u8 s, uint64_t i) {
1595 if ((i <= SIZE_MAX) && (i <= s.len)) {
1596 return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(s.len - i)));
1597 }
1598 return wuffs_base__make_slice_u8(NULL, 0);
1599}
1600
1601// wuffs_base__slice_u8__subslice_j returns s[:j].
1602//
1603// It returns an empty slice if j is out of bounds.
1604static inline wuffs_base__slice_u8 //
1605wuffs_base__slice_u8__subslice_j(wuffs_base__slice_u8 s, uint64_t j) {
1606 if ((j <= SIZE_MAX) && (j <= s.len)) {
1607 return wuffs_base__make_slice_u8(s.ptr, ((size_t)j));
1608 }
1609 return wuffs_base__make_slice_u8(NULL, 0);
1610}
1611
1612// wuffs_base__slice_u8__subslice_ij returns s[i:j].
1613//
1614// It returns an empty slice if i or j is out of bounds.
1615static inline wuffs_base__slice_u8 //
1616wuffs_base__slice_u8__subslice_ij(wuffs_base__slice_u8 s,
1617 uint64_t i,
1618 uint64_t j) {
1619 if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) {
1620 return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(j - i)));
1621 }
1622 return wuffs_base__make_slice_u8(NULL, 0);
1623}
1624
Nigel Taobf9dab32021-11-18 19:19:55 +11001625// wuffs_base__table_u8__subtable_ij returns t[ix:jx, iy:jy].
1626//
1627// It returns an empty table if i or j is out of bounds.
1628static inline wuffs_base__table_u8 //
1629wuffs_base__table_u8__subtable_ij(wuffs_base__table_u8 t,
1630 uint64_t ix,
1631 uint64_t iy,
1632 uint64_t jx,
1633 uint64_t jy) {
1634 if ((ix <= jx) && (jx <= SIZE_MAX) && (jx <= t.width) && //
1635 (iy <= jy) && (jy <= SIZE_MAX) && (jy <= t.height)) {
1636 return wuffs_base__make_table_u8(t.ptr + ix + (iy * t.stride), //
1637 ((size_t)(jx - ix)), //
1638 ((size_t)(jy - iy)), //
1639 t.stride); //
1640 }
1641 return wuffs_base__make_table_u8(NULL, 0, 0, 0);
1642}
1643
Nigel Taoe360a532021-04-05 22:47:03 +10001644// wuffs_base__table__flattened_length returns the number of elements covered
1645// by the 1-dimensional span that backs a 2-dimensional table. This counts the
1646// elements inside the table and, when width != stride, the elements outside
1647// the table but between its rows.
1648//
1649// For example, consider a width 10, height 4, stride 10 table. Mark its first
1650// and last (inclusive) elements with 'a' and 'z'. This function returns 40.
1651//
1652// a123456789
1653// 0123456789
1654// 0123456789
1655// 012345678z
1656//
1657// Now consider the sub-table of that from (2, 1) inclusive to (8, 4) exclusive.
1658//
1659// a123456789
1660// 01iiiiiioo
1661// ooiiiiiioo
1662// ooiiiiii8z
1663//
1664// This function (called with width 6, height 3, stride 10) returns 26: 18 'i'
1665// inside elements plus 8 'o' outside elements. Note that 26 is less than a
1666// naive (height * stride = 30) computation. Indeed, advancing 29 elements from
1667// the first 'i' would venture past 'z', out of bounds of the original table.
1668//
1669// It does not check for overflow, but if the arguments come from a table that
1670// exists in memory and each element occupies a positive number of bytes then
1671// the result should be bounded by the amount of allocatable memory (which
1672// shouldn't overflow SIZE_MAX).
1673static inline size_t //
1674wuffs_base__table__flattened_length(size_t width,
1675 size_t height,
1676 size_t stride) {
1677 if (height == 0) {
1678 return 0;
1679 }
1680 return ((height - 1) * stride) + width;
1681}
1682
1683// ---------------- Magic Numbers
1684
1685// wuffs_base__magic_number_guess_fourcc guesses the file format of some data,
1686// given its opening bytes. It returns a positive FourCC value on success.
1687//
1688// It returns zero if nothing matches its hard-coded list of 'magic numbers'.
1689//
1690// It returns a negative value if a longer prefix is required for a conclusive
1691// result. For example, seeing a single 'B' byte is not enough to discriminate
1692// the BMP and BPG image file formats.
1693//
1694// It does not do a full validity check. Like any guess made from a short
1695// prefix of the data, it may return false positives. Data that starts with 99
1696// bytes of valid JPEG followed by corruption or truncation is an invalid JPEG
1697// image overall, but this function will still return WUFFS_BASE__FOURCC__JPEG.
1698//
1699// Another source of false positives is that some 'magic numbers' are valid
1700// ASCII data. A file starting with "GIF87a and GIF89a are the two versions of
1701// GIF" will match GIF's 'magic number' even if it's plain text, not an image.
1702//
1703// For modular builds that divide the base module into sub-modules, using this
1704// function requires the WUFFS_CONFIG__MODULE__BASE__MAGIC sub-module, not just
1705// WUFFS_CONFIG__MODULE__BASE__CORE.
1706WUFFS_BASE__MAYBE_STATIC int32_t //
1707wuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix);
1708
1709// ---------------- Ranges and Rects
1710
1711// See https://github.com/google/wuffs/blob/main/doc/note/ranges-and-rects.md
1712
1713typedef struct wuffs_base__range_ii_u32__struct {
1714 uint32_t min_incl;
1715 uint32_t max_incl;
1716
1717#ifdef __cplusplus
1718 inline bool is_empty() const;
1719 inline bool equals(wuffs_base__range_ii_u32__struct s) const;
1720 inline wuffs_base__range_ii_u32__struct intersect(
1721 wuffs_base__range_ii_u32__struct s) const;
1722 inline wuffs_base__range_ii_u32__struct unite(
1723 wuffs_base__range_ii_u32__struct s) const;
1724 inline bool contains(uint32_t x) const;
1725 inline bool contains_range(wuffs_base__range_ii_u32__struct s) const;
1726#endif // __cplusplus
1727
1728} wuffs_base__range_ii_u32;
1729
1730static inline wuffs_base__range_ii_u32 //
1731wuffs_base__empty_range_ii_u32() {
1732 wuffs_base__range_ii_u32 ret;
1733 ret.min_incl = 0;
1734 ret.max_incl = 0;
1735 return ret;
1736}
1737
1738static inline wuffs_base__range_ii_u32 //
1739wuffs_base__make_range_ii_u32(uint32_t min_incl, uint32_t max_incl) {
1740 wuffs_base__range_ii_u32 ret;
1741 ret.min_incl = min_incl;
1742 ret.max_incl = max_incl;
1743 return ret;
1744}
1745
1746static inline bool //
1747wuffs_base__range_ii_u32__is_empty(const wuffs_base__range_ii_u32* r) {
1748 return r->min_incl > r->max_incl;
1749}
1750
1751static inline bool //
1752wuffs_base__range_ii_u32__equals(const wuffs_base__range_ii_u32* r,
1753 wuffs_base__range_ii_u32 s) {
1754 return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
1755 (wuffs_base__range_ii_u32__is_empty(r) &&
1756 wuffs_base__range_ii_u32__is_empty(&s));
1757}
1758
1759static inline wuffs_base__range_ii_u32 //
1760wuffs_base__range_ii_u32__intersect(const wuffs_base__range_ii_u32* r,
1761 wuffs_base__range_ii_u32 s) {
1762 wuffs_base__range_ii_u32 t;
1763 t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
1764 t.max_incl = wuffs_base__u32__min(r->max_incl, s.max_incl);
1765 return t;
1766}
1767
1768static inline wuffs_base__range_ii_u32 //
1769wuffs_base__range_ii_u32__unite(const wuffs_base__range_ii_u32* r,
1770 wuffs_base__range_ii_u32 s) {
1771 if (wuffs_base__range_ii_u32__is_empty(r)) {
1772 return s;
1773 }
1774 if (wuffs_base__range_ii_u32__is_empty(&s)) {
1775 return *r;
1776 }
1777 wuffs_base__range_ii_u32 t;
1778 t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);
1779 t.max_incl = wuffs_base__u32__max(r->max_incl, s.max_incl);
1780 return t;
1781}
1782
1783static inline bool //
1784wuffs_base__range_ii_u32__contains(const wuffs_base__range_ii_u32* r,
1785 uint32_t x) {
1786 return (r->min_incl <= x) && (x <= r->max_incl);
1787}
1788
1789static inline bool //
1790wuffs_base__range_ii_u32__contains_range(const wuffs_base__range_ii_u32* r,
1791 wuffs_base__range_ii_u32 s) {
1792 return wuffs_base__range_ii_u32__equals(
1793 &s, wuffs_base__range_ii_u32__intersect(r, s));
1794}
1795
1796#ifdef __cplusplus
1797
1798inline bool //
1799wuffs_base__range_ii_u32::is_empty() const {
1800 return wuffs_base__range_ii_u32__is_empty(this);
1801}
1802
1803inline bool //
1804wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) const {
1805 return wuffs_base__range_ii_u32__equals(this, s);
1806}
1807
1808inline wuffs_base__range_ii_u32 //
1809wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) const {
1810 return wuffs_base__range_ii_u32__intersect(this, s);
1811}
1812
1813inline wuffs_base__range_ii_u32 //
1814wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) const {
1815 return wuffs_base__range_ii_u32__unite(this, s);
1816}
1817
1818inline bool //
1819wuffs_base__range_ii_u32::contains(uint32_t x) const {
1820 return wuffs_base__range_ii_u32__contains(this, x);
1821}
1822
1823inline bool //
1824wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) const {
1825 return wuffs_base__range_ii_u32__contains_range(this, s);
1826}
1827
1828#endif // __cplusplus
1829
1830// --------
1831
1832typedef struct wuffs_base__range_ie_u32__struct {
1833 uint32_t min_incl;
1834 uint32_t max_excl;
1835
1836#ifdef __cplusplus
1837 inline bool is_empty() const;
1838 inline bool equals(wuffs_base__range_ie_u32__struct s) const;
1839 inline wuffs_base__range_ie_u32__struct intersect(
1840 wuffs_base__range_ie_u32__struct s) const;
1841 inline wuffs_base__range_ie_u32__struct unite(
1842 wuffs_base__range_ie_u32__struct s) const;
1843 inline bool contains(uint32_t x) const;
1844 inline bool contains_range(wuffs_base__range_ie_u32__struct s) const;
1845 inline uint32_t length() const;
1846#endif // __cplusplus
1847
1848} wuffs_base__range_ie_u32;
1849
1850static inline wuffs_base__range_ie_u32 //
1851wuffs_base__empty_range_ie_u32() {
1852 wuffs_base__range_ie_u32 ret;
1853 ret.min_incl = 0;
1854 ret.max_excl = 0;
1855 return ret;
1856}
1857
1858static inline wuffs_base__range_ie_u32 //
1859wuffs_base__make_range_ie_u32(uint32_t min_incl, uint32_t max_excl) {
1860 wuffs_base__range_ie_u32 ret;
1861 ret.min_incl = min_incl;
1862 ret.max_excl = max_excl;
1863 return ret;
1864}
1865
1866static inline bool //
1867wuffs_base__range_ie_u32__is_empty(const wuffs_base__range_ie_u32* r) {
1868 return r->min_incl >= r->max_excl;
1869}
1870
1871static inline bool //
1872wuffs_base__range_ie_u32__equals(const wuffs_base__range_ie_u32* r,
1873 wuffs_base__range_ie_u32 s) {
1874 return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
1875 (wuffs_base__range_ie_u32__is_empty(r) &&
1876 wuffs_base__range_ie_u32__is_empty(&s));
1877}
1878
1879static inline wuffs_base__range_ie_u32 //
1880wuffs_base__range_ie_u32__intersect(const wuffs_base__range_ie_u32* r,
1881 wuffs_base__range_ie_u32 s) {
1882 wuffs_base__range_ie_u32 t;
1883 t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
1884 t.max_excl = wuffs_base__u32__min(r->max_excl, s.max_excl);
1885 return t;
1886}
1887
1888static inline wuffs_base__range_ie_u32 //
1889wuffs_base__range_ie_u32__unite(const wuffs_base__range_ie_u32* r,
1890 wuffs_base__range_ie_u32 s) {
1891 if (wuffs_base__range_ie_u32__is_empty(r)) {
1892 return s;
1893 }
1894 if (wuffs_base__range_ie_u32__is_empty(&s)) {
1895 return *r;
1896 }
1897 wuffs_base__range_ie_u32 t;
1898 t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);
1899 t.max_excl = wuffs_base__u32__max(r->max_excl, s.max_excl);
1900 return t;
1901}
1902
1903static inline bool //
1904wuffs_base__range_ie_u32__contains(const wuffs_base__range_ie_u32* r,
1905 uint32_t x) {
1906 return (r->min_incl <= x) && (x < r->max_excl);
1907}
1908
1909static inline bool //
1910wuffs_base__range_ie_u32__contains_range(const wuffs_base__range_ie_u32* r,
1911 wuffs_base__range_ie_u32 s) {
1912 return wuffs_base__range_ie_u32__equals(
1913 &s, wuffs_base__range_ie_u32__intersect(r, s));
1914}
1915
1916static inline uint32_t //
1917wuffs_base__range_ie_u32__length(const wuffs_base__range_ie_u32* r) {
1918 return wuffs_base__u32__sat_sub(r->max_excl, r->min_incl);
1919}
1920
1921#ifdef __cplusplus
1922
1923inline bool //
1924wuffs_base__range_ie_u32::is_empty() const {
1925 return wuffs_base__range_ie_u32__is_empty(this);
1926}
1927
1928inline bool //
1929wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) const {
1930 return wuffs_base__range_ie_u32__equals(this, s);
1931}
1932
1933inline wuffs_base__range_ie_u32 //
1934wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) const {
1935 return wuffs_base__range_ie_u32__intersect(this, s);
1936}
1937
1938inline wuffs_base__range_ie_u32 //
1939wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) const {
1940 return wuffs_base__range_ie_u32__unite(this, s);
1941}
1942
1943inline bool //
1944wuffs_base__range_ie_u32::contains(uint32_t x) const {
1945 return wuffs_base__range_ie_u32__contains(this, x);
1946}
1947
1948inline bool //
1949wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) const {
1950 return wuffs_base__range_ie_u32__contains_range(this, s);
1951}
1952
1953inline uint32_t //
1954wuffs_base__range_ie_u32::length() const {
1955 return wuffs_base__range_ie_u32__length(this);
1956}
1957
1958#endif // __cplusplus
1959
1960// --------
1961
1962typedef struct wuffs_base__range_ii_u64__struct {
1963 uint64_t min_incl;
1964 uint64_t max_incl;
1965
1966#ifdef __cplusplus
1967 inline bool is_empty() const;
1968 inline bool equals(wuffs_base__range_ii_u64__struct s) const;
1969 inline wuffs_base__range_ii_u64__struct intersect(
1970 wuffs_base__range_ii_u64__struct s) const;
1971 inline wuffs_base__range_ii_u64__struct unite(
1972 wuffs_base__range_ii_u64__struct s) const;
1973 inline bool contains(uint64_t x) const;
1974 inline bool contains_range(wuffs_base__range_ii_u64__struct s) const;
1975#endif // __cplusplus
1976
1977} wuffs_base__range_ii_u64;
1978
1979static inline wuffs_base__range_ii_u64 //
1980wuffs_base__empty_range_ii_u64() {
1981 wuffs_base__range_ii_u64 ret;
1982 ret.min_incl = 0;
1983 ret.max_incl = 0;
1984 return ret;
1985}
1986
1987static inline wuffs_base__range_ii_u64 //
1988wuffs_base__make_range_ii_u64(uint64_t min_incl, uint64_t max_incl) {
1989 wuffs_base__range_ii_u64 ret;
1990 ret.min_incl = min_incl;
1991 ret.max_incl = max_incl;
1992 return ret;
1993}
1994
1995static inline bool //
1996wuffs_base__range_ii_u64__is_empty(const wuffs_base__range_ii_u64* r) {
1997 return r->min_incl > r->max_incl;
1998}
1999
2000static inline bool //
2001wuffs_base__range_ii_u64__equals(const wuffs_base__range_ii_u64* r,
2002 wuffs_base__range_ii_u64 s) {
2003 return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
2004 (wuffs_base__range_ii_u64__is_empty(r) &&
2005 wuffs_base__range_ii_u64__is_empty(&s));
2006}
2007
2008static inline wuffs_base__range_ii_u64 //
2009wuffs_base__range_ii_u64__intersect(const wuffs_base__range_ii_u64* r,
2010 wuffs_base__range_ii_u64 s) {
2011 wuffs_base__range_ii_u64 t;
2012 t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
2013 t.max_incl = wuffs_base__u64__min(r->max_incl, s.max_incl);
2014 return t;
2015}
2016
2017static inline wuffs_base__range_ii_u64 //
2018wuffs_base__range_ii_u64__unite(const wuffs_base__range_ii_u64* r,
2019 wuffs_base__range_ii_u64 s) {
2020 if (wuffs_base__range_ii_u64__is_empty(r)) {
2021 return s;
2022 }
2023 if (wuffs_base__range_ii_u64__is_empty(&s)) {
2024 return *r;
2025 }
2026 wuffs_base__range_ii_u64 t;
2027 t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);
2028 t.max_incl = wuffs_base__u64__max(r->max_incl, s.max_incl);
2029 return t;
2030}
2031
2032static inline bool //
2033wuffs_base__range_ii_u64__contains(const wuffs_base__range_ii_u64* r,
2034 uint64_t x) {
2035 return (r->min_incl <= x) && (x <= r->max_incl);
2036}
2037
2038static inline bool //
2039wuffs_base__range_ii_u64__contains_range(const wuffs_base__range_ii_u64* r,
2040 wuffs_base__range_ii_u64 s) {
2041 return wuffs_base__range_ii_u64__equals(
2042 &s, wuffs_base__range_ii_u64__intersect(r, s));
2043}
2044
2045#ifdef __cplusplus
2046
2047inline bool //
2048wuffs_base__range_ii_u64::is_empty() const {
2049 return wuffs_base__range_ii_u64__is_empty(this);
2050}
2051
2052inline bool //
2053wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) const {
2054 return wuffs_base__range_ii_u64__equals(this, s);
2055}
2056
2057inline wuffs_base__range_ii_u64 //
2058wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) const {
2059 return wuffs_base__range_ii_u64__intersect(this, s);
2060}
2061
2062inline wuffs_base__range_ii_u64 //
2063wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) const {
2064 return wuffs_base__range_ii_u64__unite(this, s);
2065}
2066
2067inline bool //
2068wuffs_base__range_ii_u64::contains(uint64_t x) const {
2069 return wuffs_base__range_ii_u64__contains(this, x);
2070}
2071
2072inline bool //
2073wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) const {
2074 return wuffs_base__range_ii_u64__contains_range(this, s);
2075}
2076
2077#endif // __cplusplus
2078
2079// --------
2080
2081typedef struct wuffs_base__range_ie_u64__struct {
2082 uint64_t min_incl;
2083 uint64_t max_excl;
2084
2085#ifdef __cplusplus
2086 inline bool is_empty() const;
2087 inline bool equals(wuffs_base__range_ie_u64__struct s) const;
2088 inline wuffs_base__range_ie_u64__struct intersect(
2089 wuffs_base__range_ie_u64__struct s) const;
2090 inline wuffs_base__range_ie_u64__struct unite(
2091 wuffs_base__range_ie_u64__struct s) const;
2092 inline bool contains(uint64_t x) const;
2093 inline bool contains_range(wuffs_base__range_ie_u64__struct s) const;
2094 inline uint64_t length() const;
2095#endif // __cplusplus
2096
2097} wuffs_base__range_ie_u64;
2098
2099static inline wuffs_base__range_ie_u64 //
2100wuffs_base__empty_range_ie_u64() {
2101 wuffs_base__range_ie_u64 ret;
2102 ret.min_incl = 0;
2103 ret.max_excl = 0;
2104 return ret;
2105}
2106
2107static inline wuffs_base__range_ie_u64 //
2108wuffs_base__make_range_ie_u64(uint64_t min_incl, uint64_t max_excl) {
2109 wuffs_base__range_ie_u64 ret;
2110 ret.min_incl = min_incl;
2111 ret.max_excl = max_excl;
2112 return ret;
2113}
2114
2115static inline bool //
2116wuffs_base__range_ie_u64__is_empty(const wuffs_base__range_ie_u64* r) {
2117 return r->min_incl >= r->max_excl;
2118}
2119
2120static inline bool //
2121wuffs_base__range_ie_u64__equals(const wuffs_base__range_ie_u64* r,
2122 wuffs_base__range_ie_u64 s) {
2123 return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
2124 (wuffs_base__range_ie_u64__is_empty(r) &&
2125 wuffs_base__range_ie_u64__is_empty(&s));
2126}
2127
2128static inline wuffs_base__range_ie_u64 //
2129wuffs_base__range_ie_u64__intersect(const wuffs_base__range_ie_u64* r,
2130 wuffs_base__range_ie_u64 s) {
2131 wuffs_base__range_ie_u64 t;
2132 t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
2133 t.max_excl = wuffs_base__u64__min(r->max_excl, s.max_excl);
2134 return t;
2135}
2136
2137static inline wuffs_base__range_ie_u64 //
2138wuffs_base__range_ie_u64__unite(const wuffs_base__range_ie_u64* r,
2139 wuffs_base__range_ie_u64 s) {
2140 if (wuffs_base__range_ie_u64__is_empty(r)) {
2141 return s;
2142 }
2143 if (wuffs_base__range_ie_u64__is_empty(&s)) {
2144 return *r;
2145 }
2146 wuffs_base__range_ie_u64 t;
2147 t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);
2148 t.max_excl = wuffs_base__u64__max(r->max_excl, s.max_excl);
2149 return t;
2150}
2151
2152static inline bool //
2153wuffs_base__range_ie_u64__contains(const wuffs_base__range_ie_u64* r,
2154 uint64_t x) {
2155 return (r->min_incl <= x) && (x < r->max_excl);
2156}
2157
2158static inline bool //
2159wuffs_base__range_ie_u64__contains_range(const wuffs_base__range_ie_u64* r,
2160 wuffs_base__range_ie_u64 s) {
2161 return wuffs_base__range_ie_u64__equals(
2162 &s, wuffs_base__range_ie_u64__intersect(r, s));
2163}
2164
2165static inline uint64_t //
2166wuffs_base__range_ie_u64__length(const wuffs_base__range_ie_u64* r) {
2167 return wuffs_base__u64__sat_sub(r->max_excl, r->min_incl);
2168}
2169
2170#ifdef __cplusplus
2171
2172inline bool //
2173wuffs_base__range_ie_u64::is_empty() const {
2174 return wuffs_base__range_ie_u64__is_empty(this);
2175}
2176
2177inline bool //
2178wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) const {
2179 return wuffs_base__range_ie_u64__equals(this, s);
2180}
2181
2182inline wuffs_base__range_ie_u64 //
2183wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) const {
2184 return wuffs_base__range_ie_u64__intersect(this, s);
2185}
2186
2187inline wuffs_base__range_ie_u64 //
2188wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) const {
2189 return wuffs_base__range_ie_u64__unite(this, s);
2190}
2191
2192inline bool //
2193wuffs_base__range_ie_u64::contains(uint64_t x) const {
2194 return wuffs_base__range_ie_u64__contains(this, x);
2195}
2196
2197inline bool //
2198wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) const {
2199 return wuffs_base__range_ie_u64__contains_range(this, s);
2200}
2201
2202inline uint64_t //
2203wuffs_base__range_ie_u64::length() const {
2204 return wuffs_base__range_ie_u64__length(this);
2205}
2206
2207#endif // __cplusplus
2208
2209// --------
2210
2211typedef struct wuffs_base__rect_ii_u32__struct {
2212 uint32_t min_incl_x;
2213 uint32_t min_incl_y;
2214 uint32_t max_incl_x;
2215 uint32_t max_incl_y;
2216
2217#ifdef __cplusplus
2218 inline bool is_empty() const;
2219 inline bool equals(wuffs_base__rect_ii_u32__struct s) const;
2220 inline wuffs_base__rect_ii_u32__struct intersect(
2221 wuffs_base__rect_ii_u32__struct s) const;
2222 inline wuffs_base__rect_ii_u32__struct unite(
2223 wuffs_base__rect_ii_u32__struct s) const;
2224 inline bool contains(uint32_t x, uint32_t y) const;
2225 inline bool contains_rect(wuffs_base__rect_ii_u32__struct s) const;
2226#endif // __cplusplus
2227
2228} wuffs_base__rect_ii_u32;
2229
2230static inline wuffs_base__rect_ii_u32 //
2231wuffs_base__empty_rect_ii_u32() {
2232 wuffs_base__rect_ii_u32 ret;
2233 ret.min_incl_x = 0;
2234 ret.min_incl_y = 0;
2235 ret.max_incl_x = 0;
2236 ret.max_incl_y = 0;
2237 return ret;
2238}
2239
2240static inline wuffs_base__rect_ii_u32 //
2241wuffs_base__make_rect_ii_u32(uint32_t min_incl_x,
2242 uint32_t min_incl_y,
2243 uint32_t max_incl_x,
2244 uint32_t max_incl_y) {
2245 wuffs_base__rect_ii_u32 ret;
2246 ret.min_incl_x = min_incl_x;
2247 ret.min_incl_y = min_incl_y;
2248 ret.max_incl_x = max_incl_x;
2249 ret.max_incl_y = max_incl_y;
2250 return ret;
2251}
2252
2253static inline bool //
2254wuffs_base__rect_ii_u32__is_empty(const wuffs_base__rect_ii_u32* r) {
2255 return (r->min_incl_x > r->max_incl_x) || (r->min_incl_y > r->max_incl_y);
2256}
2257
2258static inline bool //
2259wuffs_base__rect_ii_u32__equals(const wuffs_base__rect_ii_u32* r,
2260 wuffs_base__rect_ii_u32 s) {
2261 return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
2262 r->max_incl_x == s.max_incl_x && r->max_incl_y == s.max_incl_y) ||
2263 (wuffs_base__rect_ii_u32__is_empty(r) &&
2264 wuffs_base__rect_ii_u32__is_empty(&s));
2265}
2266
2267static inline wuffs_base__rect_ii_u32 //
2268wuffs_base__rect_ii_u32__intersect(const wuffs_base__rect_ii_u32* r,
2269 wuffs_base__rect_ii_u32 s) {
2270 wuffs_base__rect_ii_u32 t;
2271 t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
2272 t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);
2273 t.max_incl_x = wuffs_base__u32__min(r->max_incl_x, s.max_incl_x);
2274 t.max_incl_y = wuffs_base__u32__min(r->max_incl_y, s.max_incl_y);
2275 return t;
2276}
2277
2278static inline wuffs_base__rect_ii_u32 //
2279wuffs_base__rect_ii_u32__unite(const wuffs_base__rect_ii_u32* r,
2280 wuffs_base__rect_ii_u32 s) {
2281 if (wuffs_base__rect_ii_u32__is_empty(r)) {
2282 return s;
2283 }
2284 if (wuffs_base__rect_ii_u32__is_empty(&s)) {
2285 return *r;
2286 }
2287 wuffs_base__rect_ii_u32 t;
2288 t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);
2289 t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);
2290 t.max_incl_x = wuffs_base__u32__max(r->max_incl_x, s.max_incl_x);
2291 t.max_incl_y = wuffs_base__u32__max(r->max_incl_y, s.max_incl_y);
2292 return t;
2293}
2294
2295static inline bool //
2296wuffs_base__rect_ii_u32__contains(const wuffs_base__rect_ii_u32* r,
2297 uint32_t x,
2298 uint32_t y) {
2299 return (r->min_incl_x <= x) && (x <= r->max_incl_x) && (r->min_incl_y <= y) &&
2300 (y <= r->max_incl_y);
2301}
2302
2303static inline bool //
2304wuffs_base__rect_ii_u32__contains_rect(const wuffs_base__rect_ii_u32* r,
2305 wuffs_base__rect_ii_u32 s) {
2306 return wuffs_base__rect_ii_u32__equals(
2307 &s, wuffs_base__rect_ii_u32__intersect(r, s));
2308}
2309
2310#ifdef __cplusplus
2311
2312inline bool //
2313wuffs_base__rect_ii_u32::is_empty() const {
2314 return wuffs_base__rect_ii_u32__is_empty(this);
2315}
2316
2317inline bool //
2318wuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) const {
2319 return wuffs_base__rect_ii_u32__equals(this, s);
2320}
2321
2322inline wuffs_base__rect_ii_u32 //
2323wuffs_base__rect_ii_u32::intersect(wuffs_base__rect_ii_u32 s) const {
2324 return wuffs_base__rect_ii_u32__intersect(this, s);
2325}
2326
2327inline wuffs_base__rect_ii_u32 //
2328wuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) const {
2329 return wuffs_base__rect_ii_u32__unite(this, s);
2330}
2331
2332inline bool //
2333wuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) const {
2334 return wuffs_base__rect_ii_u32__contains(this, x, y);
2335}
2336
2337inline bool //
2338wuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) const {
2339 return wuffs_base__rect_ii_u32__contains_rect(this, s);
2340}
2341
2342#endif // __cplusplus
2343
2344// --------
2345
2346typedef struct wuffs_base__rect_ie_u32__struct {
2347 uint32_t min_incl_x;
2348 uint32_t min_incl_y;
2349 uint32_t max_excl_x;
2350 uint32_t max_excl_y;
2351
2352#ifdef __cplusplus
2353 inline bool is_empty() const;
2354 inline bool equals(wuffs_base__rect_ie_u32__struct s) const;
2355 inline wuffs_base__rect_ie_u32__struct intersect(
2356 wuffs_base__rect_ie_u32__struct s) const;
2357 inline wuffs_base__rect_ie_u32__struct unite(
2358 wuffs_base__rect_ie_u32__struct s) const;
2359 inline bool contains(uint32_t x, uint32_t y) const;
2360 inline bool contains_rect(wuffs_base__rect_ie_u32__struct s) const;
2361 inline uint32_t width() const;
2362 inline uint32_t height() const;
2363#endif // __cplusplus
2364
2365} wuffs_base__rect_ie_u32;
2366
2367static inline wuffs_base__rect_ie_u32 //
2368wuffs_base__empty_rect_ie_u32() {
2369 wuffs_base__rect_ie_u32 ret;
2370 ret.min_incl_x = 0;
2371 ret.min_incl_y = 0;
2372 ret.max_excl_x = 0;
2373 ret.max_excl_y = 0;
2374 return ret;
2375}
2376
2377static inline wuffs_base__rect_ie_u32 //
2378wuffs_base__make_rect_ie_u32(uint32_t min_incl_x,
2379 uint32_t min_incl_y,
2380 uint32_t max_excl_x,
2381 uint32_t max_excl_y) {
2382 wuffs_base__rect_ie_u32 ret;
2383 ret.min_incl_x = min_incl_x;
2384 ret.min_incl_y = min_incl_y;
2385 ret.max_excl_x = max_excl_x;
2386 ret.max_excl_y = max_excl_y;
2387 return ret;
2388}
2389
2390static inline bool //
2391wuffs_base__rect_ie_u32__is_empty(const wuffs_base__rect_ie_u32* r) {
2392 return (r->min_incl_x >= r->max_excl_x) || (r->min_incl_y >= r->max_excl_y);
2393}
2394
2395static inline bool //
2396wuffs_base__rect_ie_u32__equals(const wuffs_base__rect_ie_u32* r,
2397 wuffs_base__rect_ie_u32 s) {
2398 return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
2399 r->max_excl_x == s.max_excl_x && r->max_excl_y == s.max_excl_y) ||
2400 (wuffs_base__rect_ie_u32__is_empty(r) &&
2401 wuffs_base__rect_ie_u32__is_empty(&s));
2402}
2403
2404static inline wuffs_base__rect_ie_u32 //
2405wuffs_base__rect_ie_u32__intersect(const wuffs_base__rect_ie_u32* r,
2406 wuffs_base__rect_ie_u32 s) {
2407 wuffs_base__rect_ie_u32 t;
2408 t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
2409 t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);
2410 t.max_excl_x = wuffs_base__u32__min(r->max_excl_x, s.max_excl_x);
2411 t.max_excl_y = wuffs_base__u32__min(r->max_excl_y, s.max_excl_y);
2412 return t;
2413}
2414
2415static inline wuffs_base__rect_ie_u32 //
2416wuffs_base__rect_ie_u32__unite(const wuffs_base__rect_ie_u32* r,
2417 wuffs_base__rect_ie_u32 s) {
2418 if (wuffs_base__rect_ie_u32__is_empty(r)) {
2419 return s;
2420 }
2421 if (wuffs_base__rect_ie_u32__is_empty(&s)) {
2422 return *r;
2423 }
2424 wuffs_base__rect_ie_u32 t;
2425 t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);
2426 t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);
2427 t.max_excl_x = wuffs_base__u32__max(r->max_excl_x, s.max_excl_x);
2428 t.max_excl_y = wuffs_base__u32__max(r->max_excl_y, s.max_excl_y);
2429 return t;
2430}
2431
2432static inline bool //
2433wuffs_base__rect_ie_u32__contains(const wuffs_base__rect_ie_u32* r,
2434 uint32_t x,
2435 uint32_t y) {
2436 return (r->min_incl_x <= x) && (x < r->max_excl_x) && (r->min_incl_y <= y) &&
2437 (y < r->max_excl_y);
2438}
2439
2440static inline bool //
2441wuffs_base__rect_ie_u32__contains_rect(const wuffs_base__rect_ie_u32* r,
2442 wuffs_base__rect_ie_u32 s) {
2443 return wuffs_base__rect_ie_u32__equals(
2444 &s, wuffs_base__rect_ie_u32__intersect(r, s));
2445}
2446
2447static inline uint32_t //
2448wuffs_base__rect_ie_u32__width(const wuffs_base__rect_ie_u32* r) {
2449 return wuffs_base__u32__sat_sub(r->max_excl_x, r->min_incl_x);
2450}
2451
2452static inline uint32_t //
2453wuffs_base__rect_ie_u32__height(const wuffs_base__rect_ie_u32* r) {
2454 return wuffs_base__u32__sat_sub(r->max_excl_y, r->min_incl_y);
2455}
2456
2457#ifdef __cplusplus
2458
2459inline bool //
2460wuffs_base__rect_ie_u32::is_empty() const {
2461 return wuffs_base__rect_ie_u32__is_empty(this);
2462}
2463
2464inline bool //
2465wuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) const {
2466 return wuffs_base__rect_ie_u32__equals(this, s);
2467}
2468
2469inline wuffs_base__rect_ie_u32 //
2470wuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) const {
2471 return wuffs_base__rect_ie_u32__intersect(this, s);
2472}
2473
2474inline wuffs_base__rect_ie_u32 //
2475wuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) const {
2476 return wuffs_base__rect_ie_u32__unite(this, s);
2477}
2478
2479inline bool //
2480wuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) const {
2481 return wuffs_base__rect_ie_u32__contains(this, x, y);
2482}
2483
2484inline bool //
2485wuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) const {
2486 return wuffs_base__rect_ie_u32__contains_rect(this, s);
2487}
2488
2489inline uint32_t //
2490wuffs_base__rect_ie_u32::width() const {
2491 return wuffs_base__rect_ie_u32__width(this);
2492}
2493
2494inline uint32_t //
2495wuffs_base__rect_ie_u32::height() const {
2496 return wuffs_base__rect_ie_u32__height(this);
2497}
2498
2499#endif // __cplusplus
2500
2501// ---------------- More Information
2502
2503// wuffs_base__more_information holds additional fields, typically when a Wuffs
2504// method returns a [note status](/doc/note/statuses.md).
2505//
2506// The flavor field follows the base38 namespace
2507// convention](/doc/note/base38-and-fourcc.md). The other fields' semantics
2508// depends on the flavor.
2509typedef struct wuffs_base__more_information__struct {
2510 uint32_t flavor;
2511 uint32_t w;
2512 uint64_t x;
2513 uint64_t y;
2514 uint64_t z;
2515
2516#ifdef __cplusplus
2517 inline void set(uint32_t flavor_arg,
2518 uint32_t w_arg,
2519 uint64_t x_arg,
2520 uint64_t y_arg,
2521 uint64_t z_arg);
2522 inline uint32_t io_redirect__fourcc() const;
2523 inline wuffs_base__range_ie_u64 io_redirect__range() const;
2524 inline uint64_t io_seek__position() const;
2525 inline uint32_t metadata__fourcc() const;
Nigel Taobf9dab32021-11-18 19:19:55 +11002526 // Deprecated: use metadata_raw_passthrough__range.
Nigel Taoe360a532021-04-05 22:47:03 +10002527 inline wuffs_base__range_ie_u64 metadata__range() const;
Nigel Taobf9dab32021-11-18 19:19:55 +11002528 inline wuffs_base__range_ie_u64 metadata_raw_passthrough__range() const;
2529 inline int32_t metadata_parsed__chrm(uint32_t component) const;
2530 inline uint32_t metadata_parsed__gama() const;
2531 inline uint32_t metadata_parsed__srgb() const;
Nigel Taoe360a532021-04-05 22:47:03 +10002532#endif // __cplusplus
2533
2534} wuffs_base__more_information;
2535
2536#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__IO_REDIRECT 1
2537#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__IO_SEEK 2
Nigel Taobf9dab32021-11-18 19:19:55 +11002538// Deprecated: use
2539// WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH.
Nigel Taoe360a532021-04-05 22:47:03 +10002540#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA 3
Nigel Taobf9dab32021-11-18 19:19:55 +11002541#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH 3
2542#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_TRANSFORM 4
2543#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED 5
Nigel Taoe360a532021-04-05 22:47:03 +10002544
2545static inline wuffs_base__more_information //
2546wuffs_base__empty_more_information() {
2547 wuffs_base__more_information ret;
2548 ret.flavor = 0;
2549 ret.w = 0;
2550 ret.x = 0;
2551 ret.y = 0;
2552 ret.z = 0;
2553 return ret;
2554}
2555
2556static inline void //
2557wuffs_base__more_information__set(wuffs_base__more_information* m,
2558 uint32_t flavor,
2559 uint32_t w,
2560 uint64_t x,
2561 uint64_t y,
2562 uint64_t z) {
2563 if (!m) {
2564 return;
2565 }
2566 m->flavor = flavor;
2567 m->w = w;
2568 m->x = x;
2569 m->y = y;
2570 m->z = z;
2571}
2572
2573static inline uint32_t //
2574wuffs_base__more_information__io_redirect__fourcc(
2575 const wuffs_base__more_information* m) {
2576 return m->w;
2577}
2578
2579static inline wuffs_base__range_ie_u64 //
2580wuffs_base__more_information__io_redirect__range(
2581 const wuffs_base__more_information* m) {
2582 wuffs_base__range_ie_u64 ret;
2583 ret.min_incl = m->y;
2584 ret.max_excl = m->z;
2585 return ret;
2586}
2587
2588static inline uint64_t //
2589wuffs_base__more_information__io_seek__position(
2590 const wuffs_base__more_information* m) {
2591 return m->x;
2592}
2593
2594static inline uint32_t //
2595wuffs_base__more_information__metadata__fourcc(
2596 const wuffs_base__more_information* m) {
2597 return m->w;
2598}
2599
Nigel Taobf9dab32021-11-18 19:19:55 +11002600// Deprecated: use
2601// wuffs_base__more_information__metadata_raw_passthrough__range.
Nigel Taoe360a532021-04-05 22:47:03 +10002602static inline wuffs_base__range_ie_u64 //
2603wuffs_base__more_information__metadata__range(
2604 const wuffs_base__more_information* m) {
2605 wuffs_base__range_ie_u64 ret;
2606 ret.min_incl = m->y;
2607 ret.max_excl = m->z;
2608 return ret;
2609}
2610
Nigel Taobf9dab32021-11-18 19:19:55 +11002611static inline wuffs_base__range_ie_u64 //
2612wuffs_base__more_information__metadata_raw_passthrough__range(
2613 const wuffs_base__more_information* m) {
2614 wuffs_base__range_ie_u64 ret;
2615 ret.min_incl = m->y;
2616 ret.max_excl = m->z;
2617 return ret;
2618}
2619
2620#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__WHITE_X 0
2621#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__WHITE_Y 1
2622#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__RED_X 2
2623#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__RED_Y 3
2624#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__GREEN_X 4
2625#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__GREEN_Y 5
2626#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__BLUE_X 6
2627#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__BLUE_Y 7
2628
2629// wuffs_base__more_information__metadata_parsed__chrm returns chromaticity
2630// values (scaled by 100000) like the PNG "cHRM" chunk. For example, the sRGB
2631// color space corresponds to:
2632// - ETC__CHRM__WHITE_X 31270
2633// - ETC__CHRM__WHITE_Y 32900
2634// - ETC__CHRM__RED_X 64000
2635// - ETC__CHRM__RED_Y 33000
2636// - ETC__CHRM__GREEN_X 30000
2637// - ETC__CHRM__GREEN_Y 60000
2638// - ETC__CHRM__BLUE_X 15000
2639// - ETC__CHRM__BLUE_Y 6000
2640//
2641// See
2642// https://ciechanow.ski/color-spaces/#chromaticity-and-white-point-coordinates
2643static inline int32_t //
2644wuffs_base__more_information__metadata_parsed__chrm(
2645 const wuffs_base__more_information* m,
2646 uint32_t component) {
2647 // After the flavor and the w field (holding a FourCC), a
2648 // wuffs_base__more_information holds 24 bytes of data in three uint64_t
2649 // typed fields (x, y and z). We pack the eight chromaticity values (wx, wy,
2650 // rx, ..., by), basically int24_t values, into 24 bytes like this:
2651 // - LSB MSB
2652 // - x: wx wx wx wy wy wy rx rx
2653 // - y: rx ry ry ry gx gx gx gy
2654 // - z: gy gy bx bx bx by by by
2655 uint32_t u = 0;
2656 switch (component & 7) {
2657 case 0:
2658 u = ((uint32_t)(m->x >> 0));
2659 break;
2660 case 1:
2661 u = ((uint32_t)(m->x >> 24));
2662 break;
2663 case 2:
2664 u = ((uint32_t)((m->x >> 48) | (m->y << 16)));
2665 break;
2666 case 3:
2667 u = ((uint32_t)(m->y >> 8));
2668 break;
2669 case 4:
2670 u = ((uint32_t)(m->y >> 32));
2671 break;
2672 case 5:
2673 u = ((uint32_t)((m->y >> 56) | (m->z << 8)));
2674 break;
2675 case 6:
2676 u = ((uint32_t)(m->z >> 16));
2677 break;
2678 case 7:
2679 u = ((uint32_t)(m->z >> 40));
2680 break;
2681 }
2682 // The left-right shifts sign-extend from 24-bit to 32-bit integers.
2683 return ((int32_t)(u << 8)) >> 8;
2684}
2685
2686// wuffs_base__more_information__metadata_parsed__gama returns inverse gamma
2687// correction values (scaled by 100000) like the PNG "gAMA" chunk. For example,
2688// for gamma = 2.2, this returns 45455 (approximating 100000 / 2.2).
2689static inline uint32_t //
2690wuffs_base__more_information__metadata_parsed__gama(
2691 const wuffs_base__more_information* m) {
2692 return ((uint32_t)(m->x));
2693}
2694
2695#define WUFFS_BASE__SRGB_RENDERING_INTENT__PERCEPTUAL 0
2696#define WUFFS_BASE__SRGB_RENDERING_INTENT__RELATIVE_COLORIMETRIC 1
2697#define WUFFS_BASE__SRGB_RENDERING_INTENT__SATURATION 2
2698#define WUFFS_BASE__SRGB_RENDERING_INTENT__ABSOLUTE_COLORIMETRIC 3
2699
2700// wuffs_base__more_information__metadata_parsed__srgb returns the sRGB
2701// rendering intent like the PNG "sRGB" chunk.
2702static inline uint32_t //
2703wuffs_base__more_information__metadata_parsed__srgb(
2704 const wuffs_base__more_information* m) {
2705 return m->x & 3;
2706}
2707
Nigel Taoe360a532021-04-05 22:47:03 +10002708#ifdef __cplusplus
2709
2710inline void //
2711wuffs_base__more_information::set(uint32_t flavor_arg,
2712 uint32_t w_arg,
2713 uint64_t x_arg,
2714 uint64_t y_arg,
2715 uint64_t z_arg) {
2716 wuffs_base__more_information__set(this, flavor_arg, w_arg, x_arg, y_arg,
2717 z_arg);
2718}
2719
2720inline uint32_t //
2721wuffs_base__more_information::io_redirect__fourcc() const {
2722 return wuffs_base__more_information__io_redirect__fourcc(this);
2723}
2724
2725inline wuffs_base__range_ie_u64 //
2726wuffs_base__more_information::io_redirect__range() const {
2727 return wuffs_base__more_information__io_redirect__range(this);
2728}
2729
2730inline uint64_t //
2731wuffs_base__more_information::io_seek__position() const {
2732 return wuffs_base__more_information__io_seek__position(this);
2733}
2734
2735inline uint32_t //
2736wuffs_base__more_information::metadata__fourcc() const {
2737 return wuffs_base__more_information__metadata__fourcc(this);
2738}
2739
2740inline wuffs_base__range_ie_u64 //
2741wuffs_base__more_information::metadata__range() const {
2742 return wuffs_base__more_information__metadata__range(this);
2743}
2744
Nigel Taobf9dab32021-11-18 19:19:55 +11002745inline wuffs_base__range_ie_u64 //
2746wuffs_base__more_information::metadata_raw_passthrough__range() const {
2747 return wuffs_base__more_information__metadata_raw_passthrough__range(this);
2748}
2749
2750inline int32_t //
2751wuffs_base__more_information::metadata_parsed__chrm(uint32_t component) const {
2752 return wuffs_base__more_information__metadata_parsed__chrm(this, component);
2753}
2754
2755inline uint32_t //
2756wuffs_base__more_information::metadata_parsed__gama() const {
2757 return wuffs_base__more_information__metadata_parsed__gama(this);
2758}
2759
2760inline uint32_t //
2761wuffs_base__more_information::metadata_parsed__srgb() const {
2762 return wuffs_base__more_information__metadata_parsed__srgb(this);
2763}
2764
Nigel Taoe360a532021-04-05 22:47:03 +10002765#endif // __cplusplus
2766
2767// ---------------- I/O
2768//
2769// See (/doc/note/io-input-output.md).
2770
2771// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's
2772// data.
2773typedef struct wuffs_base__io_buffer_meta__struct {
2774 size_t wi; // Write index. Invariant: wi <= len.
2775 size_t ri; // Read index. Invariant: ri <= wi.
2776 uint64_t pos; // Buffer position (relative to the start of stream).
2777 bool closed; // No further writes are expected.
2778} wuffs_base__io_buffer_meta;
2779
2780// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length) plus
2781// additional metadata.
2782//
2783// A value with all fields zero is a valid, empty buffer.
2784typedef struct wuffs_base__io_buffer__struct {
2785 wuffs_base__slice_u8 data;
2786 wuffs_base__io_buffer_meta meta;
2787
2788#ifdef __cplusplus
2789 inline bool is_valid() const;
2790 inline void compact();
2791 inline size_t reader_length() const;
2792 inline uint8_t* reader_pointer() const;
2793 inline uint64_t reader_position() const;
2794 inline wuffs_base__slice_u8 reader_slice() const;
2795 inline size_t writer_length() const;
2796 inline uint8_t* writer_pointer() const;
2797 inline uint64_t writer_position() const;
2798 inline wuffs_base__slice_u8 writer_slice() const;
2799
2800 // Deprecated: use reader_position.
2801 inline uint64_t reader_io_position() const;
2802 // Deprecated: use writer_position.
2803 inline uint64_t writer_io_position() const;
2804#endif // __cplusplus
2805
2806} wuffs_base__io_buffer;
2807
2808static inline wuffs_base__io_buffer //
2809wuffs_base__make_io_buffer(wuffs_base__slice_u8 data,
2810 wuffs_base__io_buffer_meta meta) {
2811 wuffs_base__io_buffer ret;
2812 ret.data = data;
2813 ret.meta = meta;
2814 return ret;
2815}
2816
2817static inline wuffs_base__io_buffer_meta //
2818wuffs_base__make_io_buffer_meta(size_t wi,
2819 size_t ri,
2820 uint64_t pos,
2821 bool closed) {
2822 wuffs_base__io_buffer_meta ret;
2823 ret.wi = wi;
2824 ret.ri = ri;
2825 ret.pos = pos;
2826 ret.closed = closed;
2827 return ret;
2828}
2829
2830static inline wuffs_base__io_buffer //
2831wuffs_base__ptr_u8__reader(uint8_t* ptr, size_t len, bool closed) {
2832 wuffs_base__io_buffer ret;
2833 ret.data.ptr = ptr;
2834 ret.data.len = len;
2835 ret.meta.wi = len;
2836 ret.meta.ri = 0;
2837 ret.meta.pos = 0;
2838 ret.meta.closed = closed;
2839 return ret;
2840}
2841
2842static inline wuffs_base__io_buffer //
2843wuffs_base__ptr_u8__writer(uint8_t* ptr, size_t len) {
2844 wuffs_base__io_buffer ret;
2845 ret.data.ptr = ptr;
2846 ret.data.len = len;
2847 ret.meta.wi = 0;
2848 ret.meta.ri = 0;
2849 ret.meta.pos = 0;
2850 ret.meta.closed = false;
2851 return ret;
2852}
2853
2854static inline wuffs_base__io_buffer //
2855wuffs_base__slice_u8__reader(wuffs_base__slice_u8 s, bool closed) {
2856 wuffs_base__io_buffer ret;
2857 ret.data.ptr = s.ptr;
2858 ret.data.len = s.len;
2859 ret.meta.wi = s.len;
2860 ret.meta.ri = 0;
2861 ret.meta.pos = 0;
2862 ret.meta.closed = closed;
2863 return ret;
2864}
2865
2866static inline wuffs_base__io_buffer //
2867wuffs_base__slice_u8__writer(wuffs_base__slice_u8 s) {
2868 wuffs_base__io_buffer ret;
2869 ret.data.ptr = s.ptr;
2870 ret.data.len = s.len;
2871 ret.meta.wi = 0;
2872 ret.meta.ri = 0;
2873 ret.meta.pos = 0;
2874 ret.meta.closed = false;
2875 return ret;
2876}
2877
2878static inline wuffs_base__io_buffer //
2879wuffs_base__empty_io_buffer() {
2880 wuffs_base__io_buffer ret;
2881 ret.data.ptr = NULL;
2882 ret.data.len = 0;
2883 ret.meta.wi = 0;
2884 ret.meta.ri = 0;
2885 ret.meta.pos = 0;
2886 ret.meta.closed = false;
2887 return ret;
2888}
2889
2890static inline wuffs_base__io_buffer_meta //
2891wuffs_base__empty_io_buffer_meta() {
2892 wuffs_base__io_buffer_meta ret;
2893 ret.wi = 0;
2894 ret.ri = 0;
2895 ret.pos = 0;
2896 ret.closed = false;
2897 return ret;
2898}
2899
2900static inline bool //
2901wuffs_base__io_buffer__is_valid(const wuffs_base__io_buffer* buf) {
2902 if (buf) {
2903 if (buf->data.ptr) {
2904 return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);
2905 } else {
2906 return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);
2907 }
2908 }
2909 return false;
2910}
2911
2912// wuffs_base__io_buffer__compact moves any written but unread bytes to the
2913// start of the buffer.
2914static inline void //
2915wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
2916 if (!buf || (buf->meta.ri == 0)) {
2917 return;
2918 }
2919 buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
2920 size_t n = buf->meta.wi - buf->meta.ri;
2921 if (n != 0) {
2922 memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);
2923 }
2924 buf->meta.wi = n;
2925 buf->meta.ri = 0;
2926}
2927
2928// Deprecated. Use wuffs_base__io_buffer__reader_position.
2929static inline uint64_t //
2930wuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {
2931 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
2932}
2933
2934static inline size_t //
2935wuffs_base__io_buffer__reader_length(const wuffs_base__io_buffer* buf) {
2936 return buf ? buf->meta.wi - buf->meta.ri : 0;
2937}
2938
2939static inline uint8_t* //
2940wuffs_base__io_buffer__reader_pointer(const wuffs_base__io_buffer* buf) {
2941 return buf ? (buf->data.ptr + buf->meta.ri) : NULL;
2942}
2943
2944static inline uint64_t //
2945wuffs_base__io_buffer__reader_position(const wuffs_base__io_buffer* buf) {
2946 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
2947}
2948
2949static inline wuffs_base__slice_u8 //
2950wuffs_base__io_buffer__reader_slice(const wuffs_base__io_buffer* buf) {
2951 return buf ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.ri,
2952 buf->meta.wi - buf->meta.ri)
2953 : wuffs_base__empty_slice_u8();
2954}
2955
2956// Deprecated. Use wuffs_base__io_buffer__writer_position.
2957static inline uint64_t //
2958wuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {
2959 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
2960}
2961
2962static inline size_t //
2963wuffs_base__io_buffer__writer_length(const wuffs_base__io_buffer* buf) {
2964 return buf ? buf->data.len - buf->meta.wi : 0;
2965}
2966
2967static inline uint8_t* //
2968wuffs_base__io_buffer__writer_pointer(const wuffs_base__io_buffer* buf) {
2969 return buf ? (buf->data.ptr + buf->meta.wi) : NULL;
2970}
2971
2972static inline uint64_t //
2973wuffs_base__io_buffer__writer_position(const wuffs_base__io_buffer* buf) {
2974 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
2975}
2976
2977static inline wuffs_base__slice_u8 //
2978wuffs_base__io_buffer__writer_slice(const wuffs_base__io_buffer* buf) {
2979 return buf ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.wi,
2980 buf->data.len - buf->meta.wi)
2981 : wuffs_base__empty_slice_u8();
2982}
2983
2984#ifdef __cplusplus
2985
2986inline bool //
2987wuffs_base__io_buffer::is_valid() const {
2988 return wuffs_base__io_buffer__is_valid(this);
2989}
2990
2991inline void //
2992wuffs_base__io_buffer::compact() {
2993 wuffs_base__io_buffer__compact(this);
2994}
2995
2996inline uint64_t //
2997wuffs_base__io_buffer::reader_io_position() const {
2998 return wuffs_base__io_buffer__reader_io_position(this);
2999}
3000
3001inline size_t //
3002wuffs_base__io_buffer::reader_length() const {
3003 return wuffs_base__io_buffer__reader_length(this);
3004}
3005
3006inline uint8_t* //
3007wuffs_base__io_buffer::reader_pointer() const {
3008 return wuffs_base__io_buffer__reader_pointer(this);
3009}
3010
3011inline uint64_t //
3012wuffs_base__io_buffer::reader_position() const {
3013 return wuffs_base__io_buffer__reader_position(this);
3014}
3015
3016inline wuffs_base__slice_u8 //
3017wuffs_base__io_buffer::reader_slice() const {
3018 return wuffs_base__io_buffer__reader_slice(this);
3019}
3020
3021inline uint64_t //
3022wuffs_base__io_buffer::writer_io_position() const {
3023 return wuffs_base__io_buffer__writer_io_position(this);
3024}
3025
3026inline size_t //
3027wuffs_base__io_buffer::writer_length() const {
3028 return wuffs_base__io_buffer__writer_length(this);
3029}
3030
3031inline uint8_t* //
3032wuffs_base__io_buffer::writer_pointer() const {
3033 return wuffs_base__io_buffer__writer_pointer(this);
3034}
3035
3036inline uint64_t //
3037wuffs_base__io_buffer::writer_position() const {
3038 return wuffs_base__io_buffer__writer_position(this);
3039}
3040
3041inline wuffs_base__slice_u8 //
3042wuffs_base__io_buffer::writer_slice() const {
3043 return wuffs_base__io_buffer__writer_slice(this);
3044}
3045
3046#endif // __cplusplus
3047
3048// ---------------- Tokens
3049
3050// wuffs_base__token is an element of a byte stream's tokenization.
3051//
3052// See https://github.com/google/wuffs/blob/main/doc/note/tokens.md
3053typedef struct wuffs_base__token__struct {
3054 uint64_t repr;
3055
3056#ifdef __cplusplus
3057 inline int64_t value() const;
3058 inline int64_t value_extension() const;
3059 inline int64_t value_major() const;
3060 inline int64_t value_base_category() const;
3061 inline uint64_t value_minor() const;
3062 inline uint64_t value_base_detail() const;
3063 inline int64_t value_base_detail__sign_extended() const;
3064 inline bool continued() const;
3065 inline uint64_t length() const;
3066#endif // __cplusplus
3067
3068} wuffs_base__token;
3069
3070static inline wuffs_base__token //
3071wuffs_base__make_token(uint64_t repr) {
3072 wuffs_base__token ret;
3073 ret.repr = repr;
3074 return ret;
3075}
3076
3077// --------
3078
3079#define WUFFS_BASE__TOKEN__LENGTH__MAX_INCL 0xFFFF
3080
3081#define WUFFS_BASE__TOKEN__VALUE__SHIFT 17
3082#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT 17
3083#define WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT 42
3084#define WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT 17
3085#define WUFFS_BASE__TOKEN__VALUE_BASE_CATEGORY__SHIFT 38
3086#define WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT 17
3087#define WUFFS_BASE__TOKEN__CONTINUED__SHIFT 16
3088#define WUFFS_BASE__TOKEN__LENGTH__SHIFT 0
3089
3090#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__NUM_BITS 46
3091
3092// --------
3093
3094#define WUFFS_BASE__TOKEN__VBC__FILLER 0
3095#define WUFFS_BASE__TOKEN__VBC__STRUCTURE 1
3096#define WUFFS_BASE__TOKEN__VBC__STRING 2
3097#define WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT 3
3098#define WUFFS_BASE__TOKEN__VBC__LITERAL 4
3099#define WUFFS_BASE__TOKEN__VBC__NUMBER 5
3100#define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED 6
3101#define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED 7
3102
3103// --------
3104
3105#define WUFFS_BASE__TOKEN__VBD__FILLER__PUNCTUATION 0x00001
3106#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_BLOCK 0x00002
3107#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_LINE 0x00004
3108
3109// COMMENT_ANY is a bit-wise or of COMMENT_BLOCK AND COMMENT_LINE.
3110#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_ANY 0x00006
3111
3112// --------
3113
3114#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH 0x00001
3115#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP 0x00002
3116#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE 0x00010
3117#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST 0x00020
3118#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT 0x00040
3119#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE 0x01000
3120#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST 0x02000
3121#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT 0x04000
3122
3123// --------
3124
3125// DEFINITELY_FOO means that the destination bytes (and also the source bytes,
3126// for 1_DST_1_SRC_COPY) are in the FOO format. Definitely means that the lack
3127// of the bit means "maybe FOO". It does not necessarily mean "not FOO".
3128//
3129// CHAIN_ETC means that decoding the entire token chain forms a UTF-8 or ASCII
3130// string, not just this current token. CHAIN_ETC_UTF_8 therefore distinguishes
3131// Unicode (UTF-8) strings from byte strings. MUST means that the the token
3132// producer (e.g. parser) must verify this. SHOULD means that the token
3133// consumer (e.g. renderer) should verify this.
3134//
3135// When a CHAIN_ETC_UTF_8 bit is set, the parser must ensure that non-ASCII
3136// code points (with multi-byte UTF-8 encodings) do not straddle token
3137// boundaries. Checking UTF-8 validity can inspect each token separately.
3138//
3139// The lack of any particular bit is conservative: it is valid for all-ASCII
3140// strings, in a single- or multi-token chain, to have none of these bits set.
3141#define WUFFS_BASE__TOKEN__VBD__STRING__DEFINITELY_UTF_8 0x00001
3142#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8 0x00002
3143#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_SHOULD_BE_UTF_8 0x00004
3144#define WUFFS_BASE__TOKEN__VBD__STRING__DEFINITELY_ASCII 0x00010
3145#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_ASCII 0x00020
3146#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_SHOULD_BE_ASCII 0x00040
3147
3148// CONVERT_D_DST_S_SRC means that multiples of S source bytes (possibly padded)
3149// produces multiples of D destination bytes. For example,
3150// CONVERT_1_DST_4_SRC_BACKSLASH_X means a source like "\\x23\\x67\\xAB", where
3151// 12 src bytes encode 3 dst bytes.
3152//
3153// Post-processing may further transform those D destination bytes (e.g. treat
3154// "\\xFF" as the Unicode code point U+00FF instead of the byte 0xFF), but that
3155// is out of scope of this VBD's semantics.
3156//
3157// When src is the empty string, multiple conversion algorithms are applicable
3158// (so these bits are not necessarily mutually exclusive), all producing the
3159// same empty dst string.
3160#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP 0x00100
3161#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY 0x00200
3162#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_2_SRC_HEXADECIMAL 0x00400
3163#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X 0x00800
3164#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_3_DST_4_SRC_BASE_64_STD 0x01000
3165#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_3_DST_4_SRC_BASE_64_URL 0x02000
3166#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_4_DST_5_SRC_ASCII_85 0x04000
3167#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_5_DST_8_SRC_BASE_32_HEX 0x08000
3168#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_5_DST_8_SRC_BASE_32_STD 0x10000
3169
3170// --------
3171
3172#define WUFFS_BASE__TOKEN__VBD__LITERAL__UNDEFINED 0x00001
3173#define WUFFS_BASE__TOKEN__VBD__LITERAL__NULL 0x00002
3174#define WUFFS_BASE__TOKEN__VBD__LITERAL__FALSE 0x00004
3175#define WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE 0x00008
3176
3177// --------
3178
3179// For a source string of "123" or "0x9A", it is valid for a tokenizer to
3180// return any combination of:
3181// - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT.
3182// - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED.
3183// - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED.
3184//
3185// For a source string of "+123" or "-0x9A", only the first two are valid.
3186//
3187// For a source string of "123.", only the first one is valid.
3188#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT 0x00001
3189#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED 0x00002
3190#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED 0x00004
3191
3192#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF 0x00010
3193#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF 0x00020
3194#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN 0x00040
3195#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN 0x00080
3196
3197// The number 300 might be represented as "\x01\x2C", "\x2C\x01\x00\x00" or
3198// "300", which are big-endian, little-endian or text. For binary formats, the
3199// token length (after adjusting for FORMAT_IGNORE_ETC) discriminates
3200// e.g. u16 little-endian vs u32 little-endian.
3201#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN 0x00100
3202#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_LITTLE_ENDIAN 0x00200
3203#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT 0x00400
3204
3205#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE 0x01000
3206
3207// --------
3208
3209// wuffs_base__token__value returns the token's high 46 bits, sign-extended. A
3210// negative value means an extended token, non-negative means a simple token.
3211static inline int64_t //
3212wuffs_base__token__value(const wuffs_base__token* t) {
3213 return ((int64_t)(t->repr)) >> WUFFS_BASE__TOKEN__VALUE__SHIFT;
3214}
3215
3216// wuffs_base__token__value_extension returns a negative value if the token was
3217// not an extended token.
3218static inline int64_t //
3219wuffs_base__token__value_extension(const wuffs_base__token* t) {
3220 return (~(int64_t)(t->repr)) >> WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT;
3221}
3222
3223// wuffs_base__token__value_major returns a negative value if the token was not
3224// a simple token.
3225static inline int64_t //
3226wuffs_base__token__value_major(const wuffs_base__token* t) {
3227 return ((int64_t)(t->repr)) >> WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT;
3228}
3229
3230// wuffs_base__token__value_base_category returns a negative value if the token
3231// was not a simple token.
3232static inline int64_t //
3233wuffs_base__token__value_base_category(const wuffs_base__token* t) {
3234 return ((int64_t)(t->repr)) >> WUFFS_BASE__TOKEN__VALUE_BASE_CATEGORY__SHIFT;
3235}
3236
3237static inline uint64_t //
3238wuffs_base__token__value_minor(const wuffs_base__token* t) {
3239 return (t->repr >> WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) & 0x1FFFFFF;
3240}
3241
3242static inline uint64_t //
3243wuffs_base__token__value_base_detail(const wuffs_base__token* t) {
3244 return (t->repr >> WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT) & 0x1FFFFF;
3245}
3246
3247static inline int64_t //
3248wuffs_base__token__value_base_detail__sign_extended(
3249 const wuffs_base__token* t) {
3250 // The VBD is 21 bits in the middle of t->repr. Left shift the high (64 - 21
3251 // - ETC__SHIFT) bits off, then right shift (sign-extending) back down.
3252 uint64_t u = t->repr << (43 - WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT);
3253 return ((int64_t)u) >> 43;
3254}
3255
3256static inline bool //
3257wuffs_base__token__continued(const wuffs_base__token* t) {
3258 return t->repr & 0x10000;
3259}
3260
3261static inline uint64_t //
3262wuffs_base__token__length(const wuffs_base__token* t) {
3263 return (t->repr >> WUFFS_BASE__TOKEN__LENGTH__SHIFT) & 0xFFFF;
3264}
3265
3266#ifdef __cplusplus
3267
3268inline int64_t //
3269wuffs_base__token::value() const {
3270 return wuffs_base__token__value(this);
3271}
3272
3273inline int64_t //
3274wuffs_base__token::value_extension() const {
3275 return wuffs_base__token__value_extension(this);
3276}
3277
3278inline int64_t //
3279wuffs_base__token::value_major() const {
3280 return wuffs_base__token__value_major(this);
3281}
3282
3283inline int64_t //
3284wuffs_base__token::value_base_category() const {
3285 return wuffs_base__token__value_base_category(this);
3286}
3287
3288inline uint64_t //
3289wuffs_base__token::value_minor() const {
3290 return wuffs_base__token__value_minor(this);
3291}
3292
3293inline uint64_t //
3294wuffs_base__token::value_base_detail() const {
3295 return wuffs_base__token__value_base_detail(this);
3296}
3297
3298inline int64_t //
3299wuffs_base__token::value_base_detail__sign_extended() const {
3300 return wuffs_base__token__value_base_detail__sign_extended(this);
3301}
3302
3303inline bool //
3304wuffs_base__token::continued() const {
3305 return wuffs_base__token__continued(this);
3306}
3307
3308inline uint64_t //
3309wuffs_base__token::length() const {
3310 return wuffs_base__token__length(this);
3311}
3312
3313#endif // __cplusplus
3314
3315// --------
3316
3317typedef WUFFS_BASE__SLICE(wuffs_base__token) wuffs_base__slice_token;
3318
3319static inline wuffs_base__slice_token //
3320wuffs_base__make_slice_token(wuffs_base__token* ptr, size_t len) {
3321 wuffs_base__slice_token ret;
3322 ret.ptr = ptr;
3323 ret.len = len;
3324 return ret;
3325}
3326
3327static inline wuffs_base__slice_token //
3328wuffs_base__empty_slice_token() {
3329 wuffs_base__slice_token ret;
3330 ret.ptr = NULL;
3331 ret.len = 0;
3332 return ret;
3333}
3334
3335// --------
3336
3337// wuffs_base__token_buffer_meta is the metadata for a
3338// wuffs_base__token_buffer's data.
3339typedef struct wuffs_base__token_buffer_meta__struct {
3340 size_t wi; // Write index. Invariant: wi <= len.
3341 size_t ri; // Read index. Invariant: ri <= wi.
3342 uint64_t pos; // Position of the buffer start relative to the stream start.
3343 bool closed; // No further writes are expected.
3344} wuffs_base__token_buffer_meta;
3345
3346// wuffs_base__token_buffer is a 1-dimensional buffer (a pointer and length)
3347// plus additional metadata.
3348//
3349// A value with all fields zero is a valid, empty buffer.
3350typedef struct wuffs_base__token_buffer__struct {
3351 wuffs_base__slice_token data;
3352 wuffs_base__token_buffer_meta meta;
3353
3354#ifdef __cplusplus
3355 inline bool is_valid() const;
3356 inline void compact();
3357 inline uint64_t reader_length() const;
3358 inline wuffs_base__token* reader_pointer() const;
3359 inline wuffs_base__slice_token reader_slice() const;
3360 inline uint64_t reader_token_position() const;
3361 inline uint64_t writer_length() const;
3362 inline uint64_t writer_token_position() const;
3363 inline wuffs_base__token* writer_pointer() const;
3364 inline wuffs_base__slice_token writer_slice() const;
3365#endif // __cplusplus
3366
3367} wuffs_base__token_buffer;
3368
3369static inline wuffs_base__token_buffer //
3370wuffs_base__make_token_buffer(wuffs_base__slice_token data,
3371 wuffs_base__token_buffer_meta meta) {
3372 wuffs_base__token_buffer ret;
3373 ret.data = data;
3374 ret.meta = meta;
3375 return ret;
3376}
3377
3378static inline wuffs_base__token_buffer_meta //
3379wuffs_base__make_token_buffer_meta(size_t wi,
3380 size_t ri,
3381 uint64_t pos,
3382 bool closed) {
3383 wuffs_base__token_buffer_meta ret;
3384 ret.wi = wi;
3385 ret.ri = ri;
3386 ret.pos = pos;
3387 ret.closed = closed;
3388 return ret;
3389}
3390
3391static inline wuffs_base__token_buffer //
3392wuffs_base__slice_token__reader(wuffs_base__slice_token s, bool closed) {
3393 wuffs_base__token_buffer ret;
3394 ret.data.ptr = s.ptr;
3395 ret.data.len = s.len;
3396 ret.meta.wi = s.len;
3397 ret.meta.ri = 0;
3398 ret.meta.pos = 0;
3399 ret.meta.closed = closed;
3400 return ret;
3401}
3402
3403static inline wuffs_base__token_buffer //
3404wuffs_base__slice_token__writer(wuffs_base__slice_token s) {
3405 wuffs_base__token_buffer ret;
3406 ret.data.ptr = s.ptr;
3407 ret.data.len = s.len;
3408 ret.meta.wi = 0;
3409 ret.meta.ri = 0;
3410 ret.meta.pos = 0;
3411 ret.meta.closed = false;
3412 return ret;
3413}
3414
3415static inline wuffs_base__token_buffer //
3416wuffs_base__empty_token_buffer() {
3417 wuffs_base__token_buffer ret;
3418 ret.data.ptr = NULL;
3419 ret.data.len = 0;
3420 ret.meta.wi = 0;
3421 ret.meta.ri = 0;
3422 ret.meta.pos = 0;
3423 ret.meta.closed = false;
3424 return ret;
3425}
3426
3427static inline wuffs_base__token_buffer_meta //
3428wuffs_base__empty_token_buffer_meta() {
3429 wuffs_base__token_buffer_meta ret;
3430 ret.wi = 0;
3431 ret.ri = 0;
3432 ret.pos = 0;
3433 ret.closed = false;
3434 return ret;
3435}
3436
3437static inline bool //
3438wuffs_base__token_buffer__is_valid(const wuffs_base__token_buffer* buf) {
3439 if (buf) {
3440 if (buf->data.ptr) {
3441 return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);
3442 } else {
3443 return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);
3444 }
3445 }
3446 return false;
3447}
3448
3449// wuffs_base__token_buffer__compact moves any written but unread tokens to the
3450// start of the buffer.
3451static inline void //
3452wuffs_base__token_buffer__compact(wuffs_base__token_buffer* buf) {
3453 if (!buf || (buf->meta.ri == 0)) {
3454 return;
3455 }
3456 buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
3457 size_t n = buf->meta.wi - buf->meta.ri;
3458 if (n != 0) {
3459 memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri,
3460 n * sizeof(wuffs_base__token));
3461 }
3462 buf->meta.wi = n;
3463 buf->meta.ri = 0;
3464}
3465
3466static inline uint64_t //
3467wuffs_base__token_buffer__reader_length(const wuffs_base__token_buffer* buf) {
3468 return buf ? buf->meta.wi - buf->meta.ri : 0;
3469}
3470
3471static inline wuffs_base__token* //
3472wuffs_base__token_buffer__reader_pointer(const wuffs_base__token_buffer* buf) {
3473 return buf ? (buf->data.ptr + buf->meta.ri) : NULL;
3474}
3475
3476static inline wuffs_base__slice_token //
3477wuffs_base__token_buffer__reader_slice(const wuffs_base__token_buffer* buf) {
3478 return buf ? wuffs_base__make_slice_token(buf->data.ptr + buf->meta.ri,
3479 buf->meta.wi - buf->meta.ri)
3480 : wuffs_base__empty_slice_token();
3481}
3482
3483static inline uint64_t //
3484wuffs_base__token_buffer__reader_token_position(
3485 const wuffs_base__token_buffer* buf) {
3486 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
3487}
3488
3489static inline uint64_t //
3490wuffs_base__token_buffer__writer_length(const wuffs_base__token_buffer* buf) {
3491 return buf ? buf->data.len - buf->meta.wi : 0;
3492}
3493
3494static inline wuffs_base__token* //
3495wuffs_base__token_buffer__writer_pointer(const wuffs_base__token_buffer* buf) {
3496 return buf ? (buf->data.ptr + buf->meta.wi) : NULL;
3497}
3498
3499static inline wuffs_base__slice_token //
3500wuffs_base__token_buffer__writer_slice(const wuffs_base__token_buffer* buf) {
3501 return buf ? wuffs_base__make_slice_token(buf->data.ptr + buf->meta.wi,
3502 buf->data.len - buf->meta.wi)
3503 : wuffs_base__empty_slice_token();
3504}
3505
3506static inline uint64_t //
3507wuffs_base__token_buffer__writer_token_position(
3508 const wuffs_base__token_buffer* buf) {
3509 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
3510}
3511
3512#ifdef __cplusplus
3513
3514inline bool //
3515wuffs_base__token_buffer::is_valid() const {
3516 return wuffs_base__token_buffer__is_valid(this);
3517}
3518
3519inline void //
3520wuffs_base__token_buffer::compact() {
3521 wuffs_base__token_buffer__compact(this);
3522}
3523
3524inline uint64_t //
3525wuffs_base__token_buffer::reader_length() const {
3526 return wuffs_base__token_buffer__reader_length(this);
3527}
3528
3529inline wuffs_base__token* //
3530wuffs_base__token_buffer::reader_pointer() const {
3531 return wuffs_base__token_buffer__reader_pointer(this);
3532}
3533
3534inline wuffs_base__slice_token //
3535wuffs_base__token_buffer::reader_slice() const {
3536 return wuffs_base__token_buffer__reader_slice(this);
3537}
3538
3539inline uint64_t //
3540wuffs_base__token_buffer::reader_token_position() const {
3541 return wuffs_base__token_buffer__reader_token_position(this);
3542}
3543
3544inline uint64_t //
3545wuffs_base__token_buffer::writer_length() const {
3546 return wuffs_base__token_buffer__writer_length(this);
3547}
3548
3549inline wuffs_base__token* //
3550wuffs_base__token_buffer::writer_pointer() const {
3551 return wuffs_base__token_buffer__writer_pointer(this);
3552}
3553
3554inline wuffs_base__slice_token //
3555wuffs_base__token_buffer::writer_slice() const {
3556 return wuffs_base__token_buffer__writer_slice(this);
3557}
3558
3559inline uint64_t //
3560wuffs_base__token_buffer::writer_token_position() const {
3561 return wuffs_base__token_buffer__writer_token_position(this);
3562}
3563
3564#endif // __cplusplus
3565
3566// ---------------- Memory Allocation
3567
3568// The memory allocation related functions in this section aren't used by Wuffs
3569// per se, but they may be helpful to the code that uses Wuffs.
3570
3571// wuffs_base__malloc_slice_uxx wraps calling a malloc-like function, except
3572// that it takes a uint64_t number of elements instead of a size_t size in
3573// bytes, and it returns a slice (a pointer and a length) instead of just a
3574// pointer.
3575//
3576// You can pass the C stdlib's malloc as the malloc_func.
3577//
3578// It returns an empty slice (containing a NULL ptr field) if (num_uxx *
3579// sizeof(uintxx_t)) would overflow SIZE_MAX.
3580
3581static inline wuffs_base__slice_u8 //
3582wuffs_base__malloc_slice_u8(void* (*malloc_func)(size_t), uint64_t num_u8) {
3583 if (malloc_func && (num_u8 <= (SIZE_MAX / sizeof(uint8_t)))) {
3584 void* p = (*malloc_func)((size_t)(num_u8 * sizeof(uint8_t)));
3585 if (p) {
3586 return wuffs_base__make_slice_u8((uint8_t*)(p), (size_t)num_u8);
3587 }
3588 }
3589 return wuffs_base__make_slice_u8(NULL, 0);
3590}
3591
3592static inline wuffs_base__slice_u16 //
3593wuffs_base__malloc_slice_u16(void* (*malloc_func)(size_t), uint64_t num_u16) {
3594 if (malloc_func && (num_u16 <= (SIZE_MAX / sizeof(uint16_t)))) {
3595 void* p = (*malloc_func)((size_t)(num_u16 * sizeof(uint16_t)));
3596 if (p) {
3597 return wuffs_base__make_slice_u16((uint16_t*)(p), (size_t)num_u16);
3598 }
3599 }
3600 return wuffs_base__make_slice_u16(NULL, 0);
3601}
3602
3603static inline wuffs_base__slice_u32 //
3604wuffs_base__malloc_slice_u32(void* (*malloc_func)(size_t), uint64_t num_u32) {
3605 if (malloc_func && (num_u32 <= (SIZE_MAX / sizeof(uint32_t)))) {
3606 void* p = (*malloc_func)((size_t)(num_u32 * sizeof(uint32_t)));
3607 if (p) {
3608 return wuffs_base__make_slice_u32((uint32_t*)(p), (size_t)num_u32);
3609 }
3610 }
3611 return wuffs_base__make_slice_u32(NULL, 0);
3612}
3613
3614static inline wuffs_base__slice_u64 //
3615wuffs_base__malloc_slice_u64(void* (*malloc_func)(size_t), uint64_t num_u64) {
3616 if (malloc_func && (num_u64 <= (SIZE_MAX / sizeof(uint64_t)))) {
3617 void* p = (*malloc_func)((size_t)(num_u64 * sizeof(uint64_t)));
3618 if (p) {
3619 return wuffs_base__make_slice_u64((uint64_t*)(p), (size_t)num_u64);
3620 }
3621 }
3622 return wuffs_base__make_slice_u64(NULL, 0);
3623}
3624
3625// ---------------- Images
3626
3627// wuffs_base__color_u32_argb_premul is an 8 bit per channel premultiplied
3628// Alpha, Red, Green, Blue color, as a uint32_t value. Its value is always
3629// 0xAARRGGBB (Alpha most significant, Blue least), regardless of endianness.
3630typedef uint32_t wuffs_base__color_u32_argb_premul;
3631
3632// wuffs_base__color_u32_argb_premul__is_valid returns whether c's Red, Green
3633// and Blue channels are all less than or equal to its Alpha channel. c uses
3634// premultiplied alpha, so 50% opaque 100% saturated red is 0x7F7F_0000 and a
3635// value like 0x7F80_0000 is invalid.
3636static inline bool //
3637wuffs_base__color_u32_argb_premul__is_valid(
3638 wuffs_base__color_u32_argb_premul c) {
3639 uint32_t a = 0xFF & (c >> 24);
3640 uint32_t r = 0xFF & (c >> 16);
3641 uint32_t g = 0xFF & (c >> 8);
3642 uint32_t b = 0xFF & (c >> 0);
3643 return (a >= r) && (a >= g) && (a >= b);
3644}
3645
3646static inline uint16_t //
3647wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
3648 wuffs_base__color_u32_argb_premul c) {
3649 uint32_t r5 = 0xF800 & (c >> 8);
3650 uint32_t g6 = 0x07E0 & (c >> 5);
3651 uint32_t b5 = 0x001F & (c >> 3);
3652 return (uint16_t)(r5 | g6 | b5);
3653}
3654
3655static inline wuffs_base__color_u32_argb_premul //
3656wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(uint16_t rgb_565) {
3657 uint32_t b5 = 0x1F & (rgb_565 >> 0);
3658 uint32_t b = (b5 << 3) | (b5 >> 2);
3659 uint32_t g6 = 0x3F & (rgb_565 >> 5);
3660 uint32_t g = (g6 << 2) | (g6 >> 4);
3661 uint32_t r5 = 0x1F & (rgb_565 >> 11);
3662 uint32_t r = (r5 << 3) | (r5 >> 2);
3663 return 0xFF000000 | (r << 16) | (g << 8) | (b << 0);
3664}
3665
3666static inline uint8_t //
3667wuffs_base__color_u32_argb_premul__as__color_u8_gray(
3668 wuffs_base__color_u32_argb_premul c) {
3669 // Work in 16-bit color.
3670 uint32_t cr = 0x101 * (0xFF & (c >> 16));
3671 uint32_t cg = 0x101 * (0xFF & (c >> 8));
3672 uint32_t cb = 0x101 * (0xFF & (c >> 0));
3673
3674 // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
3675 // as those given by the JFIF specification.
3676 //
3677 // Note that 19595 + 38470 + 7471 equals 65536, also known as (1 << 16). We
3678 // shift by 24, not just by 16, because the return value is 8-bit color, not
3679 // 16-bit color.
3680 uint32_t weighted_average = (19595 * cr) + (38470 * cg) + (7471 * cb) + 32768;
3681 return (uint8_t)(weighted_average >> 24);
3682}
3683
3684static inline uint16_t //
3685wuffs_base__color_u32_argb_premul__as__color_u16_gray(
3686 wuffs_base__color_u32_argb_premul c) {
3687 // Work in 16-bit color.
3688 uint32_t cr = 0x101 * (0xFF & (c >> 16));
3689 uint32_t cg = 0x101 * (0xFF & (c >> 8));
3690 uint32_t cb = 0x101 * (0xFF & (c >> 0));
3691
3692 // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
3693 // as those given by the JFIF specification.
3694 //
3695 // Note that 19595 + 38470 + 7471 equals 65536, also known as (1 << 16).
3696 uint32_t weighted_average = (19595 * cr) + (38470 * cg) + (7471 * cb) + 32768;
3697 return (uint16_t)(weighted_average >> 16);
3698}
3699
3700// wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul converts
3701// from non-premultiplied alpha to premultiplied alpha.
3702static inline wuffs_base__color_u32_argb_premul //
3703wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
3704 uint32_t argb_nonpremul) {
3705 // Multiplying by 0x101 (twice, once for alpha and once for color) converts
3706 // from 8-bit to 16-bit color. Shifting right by 8 undoes that.
3707 //
3708 // Working in the higher bit depth can produce slightly different (and
3709 // arguably slightly more accurate) results. For example, given 8-bit blue
3710 // and alpha of 0x80 and 0x81:
3711 //
3712 // - ((0x80 * 0x81 ) / 0xFF ) = 0x40 = 0x40
3713 // - ((0x8080 * 0x8181) / 0xFFFF) >> 8 = 0x4101 >> 8 = 0x41
3714 uint32_t a = 0xFF & (argb_nonpremul >> 24);
3715 uint32_t a16 = a * (0x101 * 0x101);
3716
3717 uint32_t r = 0xFF & (argb_nonpremul >> 16);
3718 r = ((r * a16) / 0xFFFF) >> 8;
3719 uint32_t g = 0xFF & (argb_nonpremul >> 8);
3720 g = ((g * a16) / 0xFFFF) >> 8;
3721 uint32_t b = 0xFF & (argb_nonpremul >> 0);
3722 b = ((b * a16) / 0xFFFF) >> 8;
3723
3724 return (a << 24) | (r << 16) | (g << 8) | (b << 0);
3725}
3726
3727// wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul converts
3728// from premultiplied alpha to non-premultiplied alpha.
3729static inline uint32_t //
3730wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
3731 wuffs_base__color_u32_argb_premul c) {
3732 uint32_t a = 0xFF & (c >> 24);
3733 if (a == 0xFF) {
3734 return c;
3735 } else if (a == 0) {
3736 return 0;
3737 }
3738 uint32_t a16 = a * 0x101;
3739
3740 uint32_t r = 0xFF & (c >> 16);
3741 r = ((r * (0x101 * 0xFFFF)) / a16) >> 8;
3742 uint32_t g = 0xFF & (c >> 8);
3743 g = ((g * (0x101 * 0xFFFF)) / a16) >> 8;
3744 uint32_t b = 0xFF & (c >> 0);
3745 b = ((b * (0x101 * 0xFFFF)) / a16) >> 8;
3746
3747 return (a << 24) | (r << 16) | (g << 8) | (b << 0);
3748}
3749
3750// wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul converts
3751// from 4x16LE non-premultiplied alpha to 4x8 premultiplied alpha.
3752static inline wuffs_base__color_u32_argb_premul //
3753wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
3754 uint64_t argb_nonpremul) {
3755 uint32_t a16 = ((uint32_t)(0xFFFF & (argb_nonpremul >> 48)));
3756
3757 uint32_t r16 = ((uint32_t)(0xFFFF & (argb_nonpremul >> 32)));
3758 r16 = (r16 * a16) / 0xFFFF;
3759 uint32_t g16 = ((uint32_t)(0xFFFF & (argb_nonpremul >> 16)));
3760 g16 = (g16 * a16) / 0xFFFF;
3761 uint32_t b16 = ((uint32_t)(0xFFFF & (argb_nonpremul >> 0)));
3762 b16 = (b16 * a16) / 0xFFFF;
3763
3764 return ((a16 >> 8) << 24) | ((r16 >> 8) << 16) | ((g16 >> 8) << 8) |
3765 ((b16 >> 8) << 0);
3766}
3767
3768// wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul converts
3769// from 4x8 premultiplied alpha to 4x16LE non-premultiplied alpha.
3770static inline uint64_t //
3771wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(
3772 wuffs_base__color_u32_argb_premul c) {
3773 uint32_t a = 0xFF & (c >> 24);
3774 if (a == 0xFF) {
3775 uint64_t r16 = 0x101 * (0xFF & (c >> 16));
3776 uint64_t g16 = 0x101 * (0xFF & (c >> 8));
3777 uint64_t b16 = 0x101 * (0xFF & (c >> 0));
3778 return 0xFFFF000000000000u | (r16 << 32) | (g16 << 16) | (b16 << 0);
3779 } else if (a == 0) {
3780 return 0;
3781 }
3782 uint64_t a16 = a * 0x101;
3783
3784 uint64_t r = 0xFF & (c >> 16);
3785 uint64_t r16 = (r * (0x101 * 0xFFFF)) / a16;
3786 uint64_t g = 0xFF & (c >> 8);
3787 uint64_t g16 = (g * (0x101 * 0xFFFF)) / a16;
3788 uint64_t b = 0xFF & (c >> 0);
3789 uint64_t b16 = (b * (0x101 * 0xFFFF)) / a16;
3790
3791 return (a16 << 48) | (r16 << 32) | (g16 << 16) | (b16 << 0);
3792}
3793
3794static inline uint64_t //
3795wuffs_base__color_u32__as__color_u64(uint32_t c) {
3796 uint64_t a16 = 0x101 * (0xFF & (c >> 24));
3797 uint64_t r16 = 0x101 * (0xFF & (c >> 16));
3798 uint64_t g16 = 0x101 * (0xFF & (c >> 8));
3799 uint64_t b16 = 0x101 * (0xFF & (c >> 0));
3800 return (a16 << 48) | (r16 << 32) | (g16 << 16) | (b16 << 0);
3801}
3802
3803static inline uint32_t //
3804wuffs_base__color_u64__as__color_u32(uint64_t c) {
3805 uint32_t a = ((uint32_t)(0xFF & (c >> 56)));
3806 uint32_t r = ((uint32_t)(0xFF & (c >> 40)));
3807 uint32_t g = ((uint32_t)(0xFF & (c >> 24)));
3808 uint32_t b = ((uint32_t)(0xFF & (c >> 8)));
3809 return (a << 24) | (r << 16) | (g << 8) | (b << 0);
3810}
3811
3812// --------
3813
3814typedef uint8_t wuffs_base__pixel_blend;
3815
3816// wuffs_base__pixel_blend encodes how to blend source and destination pixels,
3817// accounting for transparency. It encompasses the Porter-Duff compositing
3818// operators as well as the other blending modes defined by PDF.
3819//
3820// TODO: implement the other modes.
3821#define WUFFS_BASE__PIXEL_BLEND__SRC ((wuffs_base__pixel_blend)0)
3822#define WUFFS_BASE__PIXEL_BLEND__SRC_OVER ((wuffs_base__pixel_blend)1)
3823
3824// --------
3825
3826// wuffs_base__pixel_alpha_transparency is a pixel format's alpha channel
3827// model. It is a property of the pixel format in general, not of a specific
3828// pixel. An RGBA pixel format (with alpha) can still have fully opaque pixels.
3829typedef uint32_t wuffs_base__pixel_alpha_transparency;
3830
3831#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__OPAQUE 0
3832#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__NONPREMULTIPLIED_ALPHA 1
3833#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__PREMULTIPLIED_ALPHA 2
3834#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__BINARY_ALPHA 3
3835
3836// Deprecated: use WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__NONPREMULTIPLIED_ALPHA
3837// instead.
3838#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__NON_PREMULTIPLIED_ALPHA 1
3839
3840// --------
3841
3842#define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4
3843
3844#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0
3845#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3
3846
3847// A palette is 256 entries × 4 bytes per entry (e.g. BGRA).
3848#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH 1024
3849
3850// wuffs_base__pixel_format encodes the format of the bytes that constitute an
3851// image frame's pixel data.
3852//
3853// See https://github.com/google/wuffs/blob/main/doc/note/pixel-formats.md
3854//
3855// Do not manipulate its bits directly; they are private implementation
3856// details. Use methods such as wuffs_base__pixel_format__num_planes instead.
3857typedef struct wuffs_base__pixel_format__struct {
3858 uint32_t repr;
3859
3860#ifdef __cplusplus
3861 inline bool is_valid() const;
3862 inline uint32_t bits_per_pixel() const;
3863 inline bool is_direct() const;
3864 inline bool is_indexed() const;
3865 inline bool is_interleaved() const;
3866 inline bool is_planar() const;
3867 inline uint32_t num_planes() const;
3868 inline wuffs_base__pixel_alpha_transparency transparency() const;
3869#endif // __cplusplus
3870
3871} wuffs_base__pixel_format;
3872
3873static inline wuffs_base__pixel_format //
3874wuffs_base__make_pixel_format(uint32_t repr) {
3875 wuffs_base__pixel_format f;
3876 f.repr = repr;
3877 return f;
3878}
3879
3880// Common 8-bit-depth pixel formats. This list is not exhaustive; not all valid
3881// wuffs_base__pixel_format values are present.
3882
3883#define WUFFS_BASE__PIXEL_FORMAT__INVALID 0x00000000
3884
3885#define WUFFS_BASE__PIXEL_FORMAT__A 0x02000008
3886
3887#define WUFFS_BASE__PIXEL_FORMAT__Y 0x20000008
3888#define WUFFS_BASE__PIXEL_FORMAT__Y_16LE 0x2000000B
3889#define WUFFS_BASE__PIXEL_FORMAT__Y_16BE 0x2010000B
3890#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL 0x21000008
3891#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL 0x22000008
3892
3893#define WUFFS_BASE__PIXEL_FORMAT__YCBCR 0x40020888
3894#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL 0x41038888
3895#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK 0x50038888
3896
3897#define WUFFS_BASE__PIXEL_FORMAT__YCOCG 0x60020888
3898#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL 0x61038888
3899#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK 0x70038888
3900
3901#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL 0x81040008
3902#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL 0x82040008
3903#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY 0x83040008
3904
3905#define WUFFS_BASE__PIXEL_FORMAT__BGR_565 0x80000565
3906#define WUFFS_BASE__PIXEL_FORMAT__BGR 0x80000888
3907#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL 0x81008888
3908#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE 0x8100BBBB
3909#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL 0x82008888
3910#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE 0x8200BBBB
3911#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY 0x83008888
3912#define WUFFS_BASE__PIXEL_FORMAT__BGRX 0x90008888
3913
3914#define WUFFS_BASE__PIXEL_FORMAT__RGB 0xA0000888
3915#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL 0xA1008888
3916#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE 0xA100BBBB
3917#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL 0xA2008888
3918#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE 0xA200BBBB
3919#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY 0xA3008888
3920#define WUFFS_BASE__PIXEL_FORMAT__RGBX 0xB0008888
3921
3922#define WUFFS_BASE__PIXEL_FORMAT__CMY 0xC0020888
3923#define WUFFS_BASE__PIXEL_FORMAT__CMYK 0xD0038888
3924
3925extern const uint32_t wuffs_base__pixel_format__bits_per_channel[16];
3926
3927static inline bool //
3928wuffs_base__pixel_format__is_valid(const wuffs_base__pixel_format* f) {
3929 return f->repr != 0;
3930}
3931
3932// wuffs_base__pixel_format__bits_per_pixel returns the number of bits per
3933// pixel for interleaved pixel formats, and returns 0 for planar pixel formats.
3934static inline uint32_t //
3935wuffs_base__pixel_format__bits_per_pixel(const wuffs_base__pixel_format* f) {
3936 if (((f->repr >> 16) & 0x03) != 0) {
3937 return 0;
3938 }
3939 return wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 0)] +
3940 wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 4)] +
3941 wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 8)] +
3942 wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 12)];
3943}
3944
3945static inline bool //
3946wuffs_base__pixel_format__is_direct(const wuffs_base__pixel_format* f) {
3947 return ((f->repr >> 18) & 0x01) == 0;
3948}
3949
3950static inline bool //
3951wuffs_base__pixel_format__is_indexed(const wuffs_base__pixel_format* f) {
3952 return ((f->repr >> 18) & 0x01) != 0;
3953}
3954
3955static inline bool //
3956wuffs_base__pixel_format__is_interleaved(const wuffs_base__pixel_format* f) {
3957 return ((f->repr >> 16) & 0x03) == 0;
3958}
3959
3960static inline bool //
3961wuffs_base__pixel_format__is_planar(const wuffs_base__pixel_format* f) {
3962 return ((f->repr >> 16) & 0x03) != 0;
3963}
3964
3965static inline uint32_t //
3966wuffs_base__pixel_format__num_planes(const wuffs_base__pixel_format* f) {
3967 return ((f->repr >> 16) & 0x03) + 1;
3968}
3969
3970static inline wuffs_base__pixel_alpha_transparency //
3971wuffs_base__pixel_format__transparency(const wuffs_base__pixel_format* f) {
3972 return (wuffs_base__pixel_alpha_transparency)((f->repr >> 24) & 0x03);
3973}
3974
3975#ifdef __cplusplus
3976
3977inline bool //
3978wuffs_base__pixel_format::is_valid() const {
3979 return wuffs_base__pixel_format__is_valid(this);
3980}
3981
3982inline uint32_t //
3983wuffs_base__pixel_format::bits_per_pixel() const {
3984 return wuffs_base__pixel_format__bits_per_pixel(this);
3985}
3986
3987inline bool //
3988wuffs_base__pixel_format::is_direct() const {
3989 return wuffs_base__pixel_format__is_direct(this);
3990}
3991
3992inline bool //
3993wuffs_base__pixel_format::is_indexed() const {
3994 return wuffs_base__pixel_format__is_indexed(this);
3995}
3996
3997inline bool //
3998wuffs_base__pixel_format::is_interleaved() const {
3999 return wuffs_base__pixel_format__is_interleaved(this);
4000}
4001
4002inline bool //
4003wuffs_base__pixel_format::is_planar() const {
4004 return wuffs_base__pixel_format__is_planar(this);
4005}
4006
4007inline uint32_t //
4008wuffs_base__pixel_format::num_planes() const {
4009 return wuffs_base__pixel_format__num_planes(this);
4010}
4011
4012inline wuffs_base__pixel_alpha_transparency //
4013wuffs_base__pixel_format::transparency() const {
4014 return wuffs_base__pixel_format__transparency(this);
4015}
4016
4017#endif // __cplusplus
4018
4019// --------
4020
4021// wuffs_base__pixel_subsampling encodes whether sample values cover one pixel
4022// or cover multiple pixels.
4023//
4024// See https://github.com/google/wuffs/blob/main/doc/note/pixel-subsampling.md
4025//
4026// Do not manipulate its bits directly; they are private implementation
4027// details. Use methods such as wuffs_base__pixel_subsampling__bias_x instead.
4028typedef struct wuffs_base__pixel_subsampling__struct {
4029 uint32_t repr;
4030
4031#ifdef __cplusplus
4032 inline uint32_t bias_x(uint32_t plane) const;
4033 inline uint32_t denominator_x(uint32_t plane) const;
4034 inline uint32_t bias_y(uint32_t plane) const;
4035 inline uint32_t denominator_y(uint32_t plane) const;
4036#endif // __cplusplus
4037
4038} wuffs_base__pixel_subsampling;
4039
4040static inline wuffs_base__pixel_subsampling //
4041wuffs_base__make_pixel_subsampling(uint32_t repr) {
4042 wuffs_base__pixel_subsampling s;
4043 s.repr = repr;
4044 return s;
4045}
4046
4047#define WUFFS_BASE__PIXEL_SUBSAMPLING__NONE 0x00000000
4048
4049#define WUFFS_BASE__PIXEL_SUBSAMPLING__444 0x000000
4050#define WUFFS_BASE__PIXEL_SUBSAMPLING__440 0x010100
4051#define WUFFS_BASE__PIXEL_SUBSAMPLING__422 0x101000
4052#define WUFFS_BASE__PIXEL_SUBSAMPLING__420 0x111100
4053#define WUFFS_BASE__PIXEL_SUBSAMPLING__411 0x303000
4054#define WUFFS_BASE__PIXEL_SUBSAMPLING__410 0x313100
4055
4056static inline uint32_t //
4057wuffs_base__pixel_subsampling__bias_x(const wuffs_base__pixel_subsampling* s,
4058 uint32_t plane) {
4059 uint32_t shift = ((plane & 0x03) * 8) + 6;
4060 return (s->repr >> shift) & 0x03;
4061}
4062
4063static inline uint32_t //
4064wuffs_base__pixel_subsampling__denominator_x(
4065 const wuffs_base__pixel_subsampling* s,
4066 uint32_t plane) {
4067 uint32_t shift = ((plane & 0x03) * 8) + 4;
4068 return ((s->repr >> shift) & 0x03) + 1;
4069}
4070
4071static inline uint32_t //
4072wuffs_base__pixel_subsampling__bias_y(const wuffs_base__pixel_subsampling* s,
4073 uint32_t plane) {
4074 uint32_t shift = ((plane & 0x03) * 8) + 2;
4075 return (s->repr >> shift) & 0x03;
4076}
4077
4078static inline uint32_t //
4079wuffs_base__pixel_subsampling__denominator_y(
4080 const wuffs_base__pixel_subsampling* s,
4081 uint32_t plane) {
4082 uint32_t shift = ((plane & 0x03) * 8) + 0;
4083 return ((s->repr >> shift) & 0x03) + 1;
4084}
4085
4086#ifdef __cplusplus
4087
4088inline uint32_t //
4089wuffs_base__pixel_subsampling::bias_x(uint32_t plane) const {
4090 return wuffs_base__pixel_subsampling__bias_x(this, plane);
4091}
4092
4093inline uint32_t //
4094wuffs_base__pixel_subsampling::denominator_x(uint32_t plane) const {
4095 return wuffs_base__pixel_subsampling__denominator_x(this, plane);
4096}
4097
4098inline uint32_t //
4099wuffs_base__pixel_subsampling::bias_y(uint32_t plane) const {
4100 return wuffs_base__pixel_subsampling__bias_y(this, plane);
4101}
4102
4103inline uint32_t //
4104wuffs_base__pixel_subsampling::denominator_y(uint32_t plane) const {
4105 return wuffs_base__pixel_subsampling__denominator_y(this, plane);
4106}
4107
4108#endif // __cplusplus
4109
4110// --------
4111
4112typedef struct wuffs_base__pixel_config__struct {
4113 // Do not access the private_impl's fields directly. There is no API/ABI
4114 // compatibility or safety guarantee if you do so.
4115 struct {
4116 wuffs_base__pixel_format pixfmt;
4117 wuffs_base__pixel_subsampling pixsub;
4118 uint32_t width;
4119 uint32_t height;
4120 } private_impl;
4121
4122#ifdef __cplusplus
4123 inline void set(uint32_t pixfmt_repr,
4124 uint32_t pixsub_repr,
4125 uint32_t width,
4126 uint32_t height);
4127 inline void invalidate();
4128 inline bool is_valid() const;
4129 inline wuffs_base__pixel_format pixel_format() const;
4130 inline wuffs_base__pixel_subsampling pixel_subsampling() const;
4131 inline wuffs_base__rect_ie_u32 bounds() const;
4132 inline uint32_t width() const;
4133 inline uint32_t height() const;
4134 inline uint64_t pixbuf_len() const;
4135#endif // __cplusplus
4136
4137} wuffs_base__pixel_config;
4138
4139static inline wuffs_base__pixel_config //
4140wuffs_base__null_pixel_config() {
4141 wuffs_base__pixel_config ret;
4142 ret.private_impl.pixfmt.repr = 0;
4143 ret.private_impl.pixsub.repr = 0;
4144 ret.private_impl.width = 0;
4145 ret.private_impl.height = 0;
4146 return ret;
4147}
4148
4149// TODO: Should this function return bool? An error type?
4150static inline void //
4151wuffs_base__pixel_config__set(wuffs_base__pixel_config* c,
4152 uint32_t pixfmt_repr,
4153 uint32_t pixsub_repr,
4154 uint32_t width,
4155 uint32_t height) {
4156 if (!c) {
4157 return;
4158 }
4159 if (pixfmt_repr) {
4160 uint64_t wh = ((uint64_t)width) * ((uint64_t)height);
4161 // TODO: handle things other than 1 byte per pixel.
4162 if (wh <= ((uint64_t)SIZE_MAX)) {
4163 c->private_impl.pixfmt.repr = pixfmt_repr;
4164 c->private_impl.pixsub.repr = pixsub_repr;
4165 c->private_impl.width = width;
4166 c->private_impl.height = height;
4167 return;
4168 }
4169 }
4170
4171 c->private_impl.pixfmt.repr = 0;
4172 c->private_impl.pixsub.repr = 0;
4173 c->private_impl.width = 0;
4174 c->private_impl.height = 0;
4175}
4176
4177static inline void //
4178wuffs_base__pixel_config__invalidate(wuffs_base__pixel_config* c) {
4179 if (c) {
4180 c->private_impl.pixfmt.repr = 0;
4181 c->private_impl.pixsub.repr = 0;
4182 c->private_impl.width = 0;
4183 c->private_impl.height = 0;
4184 }
4185}
4186
4187static inline bool //
4188wuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) {
4189 return c && c->private_impl.pixfmt.repr;
4190}
4191
4192static inline wuffs_base__pixel_format //
4193wuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) {
4194 return c ? c->private_impl.pixfmt : wuffs_base__make_pixel_format(0);
4195}
4196
4197static inline wuffs_base__pixel_subsampling //
4198wuffs_base__pixel_config__pixel_subsampling(const wuffs_base__pixel_config* c) {
4199 return c ? c->private_impl.pixsub : wuffs_base__make_pixel_subsampling(0);
4200}
4201
4202static inline wuffs_base__rect_ie_u32 //
4203wuffs_base__pixel_config__bounds(const wuffs_base__pixel_config* c) {
4204 if (c) {
4205 wuffs_base__rect_ie_u32 ret;
4206 ret.min_incl_x = 0;
4207 ret.min_incl_y = 0;
4208 ret.max_excl_x = c->private_impl.width;
4209 ret.max_excl_y = c->private_impl.height;
4210 return ret;
4211 }
4212
4213 wuffs_base__rect_ie_u32 ret;
4214 ret.min_incl_x = 0;
4215 ret.min_incl_y = 0;
4216 ret.max_excl_x = 0;
4217 ret.max_excl_y = 0;
4218 return ret;
4219}
4220
4221static inline uint32_t //
4222wuffs_base__pixel_config__width(const wuffs_base__pixel_config* c) {
4223 return c ? c->private_impl.width : 0;
4224}
4225
4226static inline uint32_t //
4227wuffs_base__pixel_config__height(const wuffs_base__pixel_config* c) {
4228 return c ? c->private_impl.height : 0;
4229}
4230
4231// TODO: this is the right API for planar (not interleaved) pixbufs? Should it
4232// allow decoding into a color model different from the format's intrinsic one?
4233// For example, decoding a JPEG image straight to RGBA instead of to YCbCr?
4234static inline uint64_t //
4235wuffs_base__pixel_config__pixbuf_len(const wuffs_base__pixel_config* c) {
4236 if (!c) {
4237 return 0;
4238 }
4239 if (wuffs_base__pixel_format__is_planar(&c->private_impl.pixfmt)) {
4240 // TODO: support planar pixel formats, concious of pixel subsampling.
4241 return 0;
4242 }
4243 uint32_t bits_per_pixel =
4244 wuffs_base__pixel_format__bits_per_pixel(&c->private_impl.pixfmt);
4245 if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
4246 // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
4247 return 0;
4248 }
4249 uint64_t bytes_per_pixel = bits_per_pixel / 8;
4250
4251 uint64_t n =
4252 ((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);
4253 if (n > (UINT64_MAX / bytes_per_pixel)) {
4254 return 0;
4255 }
4256 n *= bytes_per_pixel;
4257
4258 if (wuffs_base__pixel_format__is_indexed(&c->private_impl.pixfmt)) {
4259 if (n >
4260 (UINT64_MAX - WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH)) {
4261 return 0;
4262 }
4263 n += WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4264 }
4265
4266 return n;
4267}
4268
4269#ifdef __cplusplus
4270
4271inline void //
4272wuffs_base__pixel_config::set(uint32_t pixfmt_repr,
4273 uint32_t pixsub_repr,
4274 uint32_t width,
4275 uint32_t height) {
4276 wuffs_base__pixel_config__set(this, pixfmt_repr, pixsub_repr, width, height);
4277}
4278
4279inline void //
4280wuffs_base__pixel_config::invalidate() {
4281 wuffs_base__pixel_config__invalidate(this);
4282}
4283
4284inline bool //
4285wuffs_base__pixel_config::is_valid() const {
4286 return wuffs_base__pixel_config__is_valid(this);
4287}
4288
4289inline wuffs_base__pixel_format //
4290wuffs_base__pixel_config::pixel_format() const {
4291 return wuffs_base__pixel_config__pixel_format(this);
4292}
4293
4294inline wuffs_base__pixel_subsampling //
4295wuffs_base__pixel_config::pixel_subsampling() const {
4296 return wuffs_base__pixel_config__pixel_subsampling(this);
4297}
4298
4299inline wuffs_base__rect_ie_u32 //
4300wuffs_base__pixel_config::bounds() const {
4301 return wuffs_base__pixel_config__bounds(this);
4302}
4303
4304inline uint32_t //
4305wuffs_base__pixel_config::width() const {
4306 return wuffs_base__pixel_config__width(this);
4307}
4308
4309inline uint32_t //
4310wuffs_base__pixel_config::height() const {
4311 return wuffs_base__pixel_config__height(this);
4312}
4313
4314inline uint64_t //
4315wuffs_base__pixel_config::pixbuf_len() const {
4316 return wuffs_base__pixel_config__pixbuf_len(this);
4317}
4318
4319#endif // __cplusplus
4320
4321// --------
4322
4323typedef struct wuffs_base__image_config__struct {
4324 wuffs_base__pixel_config pixcfg;
4325
4326 // Do not access the private_impl's fields directly. There is no API/ABI
4327 // compatibility or safety guarantee if you do so.
4328 struct {
4329 uint64_t first_frame_io_position;
4330 bool first_frame_is_opaque;
4331 } private_impl;
4332
4333#ifdef __cplusplus
4334 inline void set(uint32_t pixfmt_repr,
4335 uint32_t pixsub_repr,
4336 uint32_t width,
4337 uint32_t height,
4338 uint64_t first_frame_io_position,
4339 bool first_frame_is_opaque);
4340 inline void invalidate();
4341 inline bool is_valid() const;
4342 inline uint64_t first_frame_io_position() const;
4343 inline bool first_frame_is_opaque() const;
4344#endif // __cplusplus
4345
4346} wuffs_base__image_config;
4347
4348static inline wuffs_base__image_config //
4349wuffs_base__null_image_config() {
4350 wuffs_base__image_config ret;
4351 ret.pixcfg = wuffs_base__null_pixel_config();
4352 ret.private_impl.first_frame_io_position = 0;
4353 ret.private_impl.first_frame_is_opaque = false;
4354 return ret;
4355}
4356
4357// TODO: Should this function return bool? An error type?
4358static inline void //
4359wuffs_base__image_config__set(wuffs_base__image_config* c,
4360 uint32_t pixfmt_repr,
4361 uint32_t pixsub_repr,
4362 uint32_t width,
4363 uint32_t height,
4364 uint64_t first_frame_io_position,
4365 bool first_frame_is_opaque) {
4366 if (!c) {
4367 return;
4368 }
4369 if (pixfmt_repr) {
4370 c->pixcfg.private_impl.pixfmt.repr = pixfmt_repr;
4371 c->pixcfg.private_impl.pixsub.repr = pixsub_repr;
4372 c->pixcfg.private_impl.width = width;
4373 c->pixcfg.private_impl.height = height;
4374 c->private_impl.first_frame_io_position = first_frame_io_position;
4375 c->private_impl.first_frame_is_opaque = first_frame_is_opaque;
4376 return;
4377 }
4378
4379 c->pixcfg.private_impl.pixfmt.repr = 0;
4380 c->pixcfg.private_impl.pixsub.repr = 0;
4381 c->pixcfg.private_impl.width = 0;
4382 c->pixcfg.private_impl.height = 0;
4383 c->private_impl.first_frame_io_position = 0;
4384 c->private_impl.first_frame_is_opaque = 0;
4385}
4386
4387static inline void //
4388wuffs_base__image_config__invalidate(wuffs_base__image_config* c) {
4389 if (c) {
4390 c->pixcfg.private_impl.pixfmt.repr = 0;
4391 c->pixcfg.private_impl.pixsub.repr = 0;
4392 c->pixcfg.private_impl.width = 0;
4393 c->pixcfg.private_impl.height = 0;
4394 c->private_impl.first_frame_io_position = 0;
4395 c->private_impl.first_frame_is_opaque = 0;
4396 }
4397}
4398
4399static inline bool //
4400wuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {
4401 return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));
4402}
4403
4404static inline uint64_t //
4405wuffs_base__image_config__first_frame_io_position(
4406 const wuffs_base__image_config* c) {
4407 return c ? c->private_impl.first_frame_io_position : 0;
4408}
4409
4410static inline bool //
4411wuffs_base__image_config__first_frame_is_opaque(
4412 const wuffs_base__image_config* c) {
4413 return c ? c->private_impl.first_frame_is_opaque : false;
4414}
4415
4416#ifdef __cplusplus
4417
4418inline void //
4419wuffs_base__image_config::set(uint32_t pixfmt_repr,
4420 uint32_t pixsub_repr,
4421 uint32_t width,
4422 uint32_t height,
4423 uint64_t first_frame_io_position,
4424 bool first_frame_is_opaque) {
4425 wuffs_base__image_config__set(this, pixfmt_repr, pixsub_repr, width, height,
4426 first_frame_io_position, first_frame_is_opaque);
4427}
4428
4429inline void //
4430wuffs_base__image_config::invalidate() {
4431 wuffs_base__image_config__invalidate(this);
4432}
4433
4434inline bool //
4435wuffs_base__image_config::is_valid() const {
4436 return wuffs_base__image_config__is_valid(this);
4437}
4438
4439inline uint64_t //
4440wuffs_base__image_config::first_frame_io_position() const {
4441 return wuffs_base__image_config__first_frame_io_position(this);
4442}
4443
4444inline bool //
4445wuffs_base__image_config::first_frame_is_opaque() const {
4446 return wuffs_base__image_config__first_frame_is_opaque(this);
4447}
4448
4449#endif // __cplusplus
4450
4451// --------
4452
4453// wuffs_base__animation_disposal encodes, for an animated image, how to
4454// dispose of a frame after displaying it:
4455// - None means to draw the next frame on top of this one.
4456// - Restore Background means to clear the frame's dirty rectangle to "the
4457// background color" (in practice, this means transparent black) before
4458// drawing the next frame.
4459// - Restore Previous means to undo the current frame, so that the next frame
4460// is drawn on top of the previous one.
4461typedef uint8_t wuffs_base__animation_disposal;
4462
4463#define WUFFS_BASE__ANIMATION_DISPOSAL__NONE ((wuffs_base__animation_disposal)0)
4464#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND \
4465 ((wuffs_base__animation_disposal)1)
4466#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS \
4467 ((wuffs_base__animation_disposal)2)
4468
4469// --------
4470
4471typedef struct wuffs_base__frame_config__struct {
4472 // Do not access the private_impl's fields directly. There is no API/ABI
4473 // compatibility or safety guarantee if you do so.
4474 struct {
4475 wuffs_base__rect_ie_u32 bounds;
4476 wuffs_base__flicks duration;
4477 uint64_t index;
4478 uint64_t io_position;
4479 wuffs_base__animation_disposal disposal;
4480 bool opaque_within_bounds;
4481 bool overwrite_instead_of_blend;
4482 wuffs_base__color_u32_argb_premul background_color;
4483 } private_impl;
4484
4485#ifdef __cplusplus
4486 inline void set(wuffs_base__rect_ie_u32 bounds,
4487 wuffs_base__flicks duration,
4488 uint64_t index,
4489 uint64_t io_position,
4490 wuffs_base__animation_disposal disposal,
4491 bool opaque_within_bounds,
4492 bool overwrite_instead_of_blend,
4493 wuffs_base__color_u32_argb_premul background_color);
4494 inline wuffs_base__rect_ie_u32 bounds() const;
4495 inline uint32_t width() const;
4496 inline uint32_t height() const;
4497 inline wuffs_base__flicks duration() const;
4498 inline uint64_t index() const;
4499 inline uint64_t io_position() const;
4500 inline wuffs_base__animation_disposal disposal() const;
4501 inline bool opaque_within_bounds() const;
4502 inline bool overwrite_instead_of_blend() const;
4503 inline wuffs_base__color_u32_argb_premul background_color() const;
4504#endif // __cplusplus
4505
4506} wuffs_base__frame_config;
4507
4508static inline wuffs_base__frame_config //
4509wuffs_base__null_frame_config() {
4510 wuffs_base__frame_config ret;
4511 ret.private_impl.bounds = wuffs_base__make_rect_ie_u32(0, 0, 0, 0);
4512 ret.private_impl.duration = 0;
4513 ret.private_impl.index = 0;
4514 ret.private_impl.io_position = 0;
4515 ret.private_impl.disposal = 0;
4516 ret.private_impl.opaque_within_bounds = false;
4517 ret.private_impl.overwrite_instead_of_blend = false;
4518 return ret;
4519}
4520
4521static inline void //
4522wuffs_base__frame_config__set(
4523 wuffs_base__frame_config* c,
4524 wuffs_base__rect_ie_u32 bounds,
4525 wuffs_base__flicks duration,
4526 uint64_t index,
4527 uint64_t io_position,
4528 wuffs_base__animation_disposal disposal,
4529 bool opaque_within_bounds,
4530 bool overwrite_instead_of_blend,
4531 wuffs_base__color_u32_argb_premul background_color) {
4532 if (!c) {
4533 return;
4534 }
4535
4536 c->private_impl.bounds = bounds;
4537 c->private_impl.duration = duration;
4538 c->private_impl.index = index;
4539 c->private_impl.io_position = io_position;
4540 c->private_impl.disposal = disposal;
4541 c->private_impl.opaque_within_bounds = opaque_within_bounds;
4542 c->private_impl.overwrite_instead_of_blend = overwrite_instead_of_blend;
4543 c->private_impl.background_color = background_color;
4544}
4545
4546static inline wuffs_base__rect_ie_u32 //
4547wuffs_base__frame_config__bounds(const wuffs_base__frame_config* c) {
4548 if (c) {
4549 return c->private_impl.bounds;
4550 }
4551
4552 wuffs_base__rect_ie_u32 ret;
4553 ret.min_incl_x = 0;
4554 ret.min_incl_y = 0;
4555 ret.max_excl_x = 0;
4556 ret.max_excl_y = 0;
4557 return ret;
4558}
4559
4560static inline uint32_t //
4561wuffs_base__frame_config__width(const wuffs_base__frame_config* c) {
4562 return c ? wuffs_base__rect_ie_u32__width(&c->private_impl.bounds) : 0;
4563}
4564
4565static inline uint32_t //
4566wuffs_base__frame_config__height(const wuffs_base__frame_config* c) {
4567 return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;
4568}
4569
4570// wuffs_base__frame_config__duration returns the amount of time to display
4571// this frame. Zero means to display forever - a still (non-animated) image.
4572static inline wuffs_base__flicks //
4573wuffs_base__frame_config__duration(const wuffs_base__frame_config* c) {
4574 return c ? c->private_impl.duration : 0;
4575}
4576
4577// wuffs_base__frame_config__index returns the index of this frame. The first
4578// frame in an image has index 0, the second frame has index 1, and so on.
4579static inline uint64_t //
4580wuffs_base__frame_config__index(const wuffs_base__frame_config* c) {
4581 return c ? c->private_impl.index : 0;
4582}
4583
4584// wuffs_base__frame_config__io_position returns the I/O stream position before
4585// the frame config.
4586static inline uint64_t //
4587wuffs_base__frame_config__io_position(const wuffs_base__frame_config* c) {
4588 return c ? c->private_impl.io_position : 0;
4589}
4590
4591// wuffs_base__frame_config__disposal returns, for an animated image, how to
4592// dispose of this frame after displaying it.
4593static inline wuffs_base__animation_disposal //
4594wuffs_base__frame_config__disposal(const wuffs_base__frame_config* c) {
4595 return c ? c->private_impl.disposal : 0;
4596}
4597
4598// wuffs_base__frame_config__opaque_within_bounds returns whether all pixels
4599// within the frame's bounds are fully opaque. It makes no claim about pixels
4600// outside the frame bounds but still inside the overall image. The two
4601// bounding rectangles can differ for animated images.
4602//
4603// Its semantics are conservative. It is valid for a fully opaque frame to have
4604// this value be false: a false negative.
4605//
4606// If true, drawing the frame with WUFFS_BASE__PIXEL_BLEND__SRC and
4607// WUFFS_BASE__PIXEL_BLEND__SRC_OVER should be equivalent, in terms of
4608// resultant pixels, but the former may be faster.
4609static inline bool //
4610wuffs_base__frame_config__opaque_within_bounds(
4611 const wuffs_base__frame_config* c) {
4612 return c && c->private_impl.opaque_within_bounds;
4613}
4614
4615// wuffs_base__frame_config__overwrite_instead_of_blend returns, for an
4616// animated image, whether to ignore the previous image state (within the frame
4617// bounds) when drawing this incremental frame. Equivalently, whether to use
4618// WUFFS_BASE__PIXEL_BLEND__SRC instead of WUFFS_BASE__PIXEL_BLEND__SRC_OVER.
4619//
4620// The WebP spec (https://developers.google.com/speed/webp/docs/riff_container)
4621// calls this the "Blending method" bit. WebP's "Do not blend" corresponds to
4622// Wuffs' "overwrite_instead_of_blend".
4623static inline bool //
4624wuffs_base__frame_config__overwrite_instead_of_blend(
4625 const wuffs_base__frame_config* c) {
4626 return c && c->private_impl.overwrite_instead_of_blend;
4627}
4628
4629static inline wuffs_base__color_u32_argb_premul //
4630wuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {
4631 return c ? c->private_impl.background_color : 0;
4632}
4633
4634#ifdef __cplusplus
4635
4636inline void //
4637wuffs_base__frame_config::set(
4638 wuffs_base__rect_ie_u32 bounds,
4639 wuffs_base__flicks duration,
4640 uint64_t index,
4641 uint64_t io_position,
4642 wuffs_base__animation_disposal disposal,
4643 bool opaque_within_bounds,
4644 bool overwrite_instead_of_blend,
4645 wuffs_base__color_u32_argb_premul background_color) {
4646 wuffs_base__frame_config__set(this, bounds, duration, index, io_position,
4647 disposal, opaque_within_bounds,
4648 overwrite_instead_of_blend, background_color);
4649}
4650
4651inline wuffs_base__rect_ie_u32 //
4652wuffs_base__frame_config::bounds() const {
4653 return wuffs_base__frame_config__bounds(this);
4654}
4655
4656inline uint32_t //
4657wuffs_base__frame_config::width() const {
4658 return wuffs_base__frame_config__width(this);
4659}
4660
4661inline uint32_t //
4662wuffs_base__frame_config::height() const {
4663 return wuffs_base__frame_config__height(this);
4664}
4665
4666inline wuffs_base__flicks //
4667wuffs_base__frame_config::duration() const {
4668 return wuffs_base__frame_config__duration(this);
4669}
4670
4671inline uint64_t //
4672wuffs_base__frame_config::index() const {
4673 return wuffs_base__frame_config__index(this);
4674}
4675
4676inline uint64_t //
4677wuffs_base__frame_config::io_position() const {
4678 return wuffs_base__frame_config__io_position(this);
4679}
4680
4681inline wuffs_base__animation_disposal //
4682wuffs_base__frame_config::disposal() const {
4683 return wuffs_base__frame_config__disposal(this);
4684}
4685
4686inline bool //
4687wuffs_base__frame_config::opaque_within_bounds() const {
4688 return wuffs_base__frame_config__opaque_within_bounds(this);
4689}
4690
4691inline bool //
4692wuffs_base__frame_config::overwrite_instead_of_blend() const {
4693 return wuffs_base__frame_config__overwrite_instead_of_blend(this);
4694}
4695
4696inline wuffs_base__color_u32_argb_premul //
4697wuffs_base__frame_config::background_color() const {
4698 return wuffs_base__frame_config__background_color(this);
4699}
4700
4701#endif // __cplusplus
4702
4703// --------
4704
4705typedef struct wuffs_base__pixel_buffer__struct {
4706 wuffs_base__pixel_config pixcfg;
4707
4708 // Do not access the private_impl's fields directly. There is no API/ABI
4709 // compatibility or safety guarantee if you do so.
4710 struct {
4711 wuffs_base__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];
4712 // TODO: color spaces.
4713 } private_impl;
4714
4715#ifdef __cplusplus
4716 inline wuffs_base__status set_interleaved(
4717 const wuffs_base__pixel_config* pixcfg,
4718 wuffs_base__table_u8 primary_memory,
4719 wuffs_base__slice_u8 palette_memory);
4720 inline wuffs_base__status set_from_slice(
4721 const wuffs_base__pixel_config* pixcfg,
4722 wuffs_base__slice_u8 pixbuf_memory);
4723 inline wuffs_base__status set_from_table(
4724 const wuffs_base__pixel_config* pixcfg,
4725 wuffs_base__table_u8 primary_memory);
4726 inline wuffs_base__slice_u8 palette();
4727 inline wuffs_base__slice_u8 palette_or_else(wuffs_base__slice_u8 fallback);
4728 inline wuffs_base__pixel_format pixel_format() const;
4729 inline wuffs_base__table_u8 plane(uint32_t p);
4730 inline wuffs_base__color_u32_argb_premul color_u32_at(uint32_t x,
4731 uint32_t y) const;
4732 inline wuffs_base__status set_color_u32_at(
4733 uint32_t x,
4734 uint32_t y,
4735 wuffs_base__color_u32_argb_premul color);
4736 inline wuffs_base__status set_color_u32_fill_rect(
4737 wuffs_base__rect_ie_u32 rect,
4738 wuffs_base__color_u32_argb_premul color);
4739#endif // __cplusplus
4740
4741} wuffs_base__pixel_buffer;
4742
4743static inline wuffs_base__pixel_buffer //
4744wuffs_base__null_pixel_buffer() {
4745 wuffs_base__pixel_buffer ret;
4746 ret.pixcfg = wuffs_base__null_pixel_config();
4747 ret.private_impl.planes[0] = wuffs_base__empty_table_u8();
4748 ret.private_impl.planes[1] = wuffs_base__empty_table_u8();
4749 ret.private_impl.planes[2] = wuffs_base__empty_table_u8();
4750 ret.private_impl.planes[3] = wuffs_base__empty_table_u8();
4751 return ret;
4752}
4753
4754static inline wuffs_base__status //
4755wuffs_base__pixel_buffer__set_interleaved(
4756 wuffs_base__pixel_buffer* pb,
4757 const wuffs_base__pixel_config* pixcfg,
4758 wuffs_base__table_u8 primary_memory,
4759 wuffs_base__slice_u8 palette_memory) {
4760 if (!pb) {
4761 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
4762 }
4763 memset(pb, 0, sizeof(*pb));
4764 if (!pixcfg ||
4765 wuffs_base__pixel_format__is_planar(&pixcfg->private_impl.pixfmt)) {
4766 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4767 }
4768 if (wuffs_base__pixel_format__is_indexed(&pixcfg->private_impl.pixfmt) &&
4769 (palette_memory.len <
4770 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH)) {
4771 return wuffs_base__make_status(
4772 wuffs_base__error__bad_argument_length_too_short);
4773 }
4774 uint32_t bits_per_pixel =
4775 wuffs_base__pixel_format__bits_per_pixel(&pixcfg->private_impl.pixfmt);
4776 if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
4777 // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
4778 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
4779 }
4780 uint64_t bytes_per_pixel = bits_per_pixel / 8;
4781
4782 uint64_t width_in_bytes =
4783 ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;
4784 if ((width_in_bytes > primary_memory.width) ||
4785 (pixcfg->private_impl.height > primary_memory.height)) {
4786 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4787 }
4788
4789 pb->pixcfg = *pixcfg;
4790 pb->private_impl.planes[0] = primary_memory;
4791 if (wuffs_base__pixel_format__is_indexed(&pixcfg->private_impl.pixfmt)) {
4792 wuffs_base__table_u8* tab =
4793 &pb->private_impl
4794 .planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
4795 tab->ptr = palette_memory.ptr;
4796 tab->width = WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4797 tab->height = 1;
4798 tab->stride = WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4799 }
4800 return wuffs_base__make_status(NULL);
4801}
4802
4803static inline wuffs_base__status //
4804wuffs_base__pixel_buffer__set_from_slice(wuffs_base__pixel_buffer* pb,
4805 const wuffs_base__pixel_config* pixcfg,
4806 wuffs_base__slice_u8 pixbuf_memory) {
4807 if (!pb) {
4808 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
4809 }
4810 memset(pb, 0, sizeof(*pb));
4811 if (!pixcfg) {
4812 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4813 }
4814 if (wuffs_base__pixel_format__is_planar(&pixcfg->private_impl.pixfmt)) {
4815 // TODO: support planar pixel formats, concious of pixel subsampling.
4816 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
4817 }
4818 uint32_t bits_per_pixel =
4819 wuffs_base__pixel_format__bits_per_pixel(&pixcfg->private_impl.pixfmt);
4820 if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
4821 // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
4822 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
4823 }
4824 uint64_t bytes_per_pixel = bits_per_pixel / 8;
4825
4826 uint8_t* ptr = pixbuf_memory.ptr;
4827 uint64_t len = pixbuf_memory.len;
4828 if (wuffs_base__pixel_format__is_indexed(&pixcfg->private_impl.pixfmt)) {
4829 // Split a WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH byte
4830 // chunk (1024 bytes = 256 palette entries × 4 bytes per entry) from the
4831 // start of pixbuf_memory. We split from the start, not the end, so that
4832 // the both chunks' pointers have the same alignment as the original
4833 // pointer, up to an alignment of 1024.
4834 if (len < WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
4835 return wuffs_base__make_status(
4836 wuffs_base__error__bad_argument_length_too_short);
4837 }
4838 wuffs_base__table_u8* tab =
4839 &pb->private_impl
4840 .planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
4841 tab->ptr = ptr;
4842 tab->width = WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4843 tab->height = 1;
4844 tab->stride = WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4845 ptr += WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4846 len -= WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4847 }
4848
4849 uint64_t wh = ((uint64_t)pixcfg->private_impl.width) *
4850 ((uint64_t)pixcfg->private_impl.height);
4851 size_t width = (size_t)(pixcfg->private_impl.width);
4852 if ((wh > (UINT64_MAX / bytes_per_pixel)) ||
4853 (width > (SIZE_MAX / bytes_per_pixel))) {
4854 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4855 }
4856 wh *= bytes_per_pixel;
4857 width = ((size_t)(width * bytes_per_pixel));
4858 if (wh > len) {
4859 return wuffs_base__make_status(
4860 wuffs_base__error__bad_argument_length_too_short);
4861 }
4862
4863 pb->pixcfg = *pixcfg;
4864 wuffs_base__table_u8* tab = &pb->private_impl.planes[0];
4865 tab->ptr = ptr;
4866 tab->width = width;
4867 tab->height = pixcfg->private_impl.height;
4868 tab->stride = width;
4869 return wuffs_base__make_status(NULL);
4870}
4871
4872// Deprecated: does not handle indexed pixel configurations. Use
4873// wuffs_base__pixel_buffer__set_interleaved instead.
4874static inline wuffs_base__status //
4875wuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* pb,
4876 const wuffs_base__pixel_config* pixcfg,
4877 wuffs_base__table_u8 primary_memory) {
4878 if (!pb) {
4879 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
4880 }
4881 memset(pb, 0, sizeof(*pb));
4882 if (!pixcfg ||
4883 wuffs_base__pixel_format__is_indexed(&pixcfg->private_impl.pixfmt) ||
4884 wuffs_base__pixel_format__is_planar(&pixcfg->private_impl.pixfmt)) {
4885 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4886 }
4887 uint32_t bits_per_pixel =
4888 wuffs_base__pixel_format__bits_per_pixel(&pixcfg->private_impl.pixfmt);
4889 if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
4890 // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
4891 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
4892 }
4893 uint64_t bytes_per_pixel = bits_per_pixel / 8;
4894
4895 uint64_t width_in_bytes =
4896 ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;
4897 if ((width_in_bytes > primary_memory.width) ||
4898 (pixcfg->private_impl.height > primary_memory.height)) {
4899 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4900 }
4901
4902 pb->pixcfg = *pixcfg;
4903 pb->private_impl.planes[0] = primary_memory;
4904 return wuffs_base__make_status(NULL);
4905}
4906
4907// wuffs_base__pixel_buffer__palette returns the palette color data. If
4908// non-empty, it will have length
4909// WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH.
4910static inline wuffs_base__slice_u8 //
4911wuffs_base__pixel_buffer__palette(wuffs_base__pixel_buffer* pb) {
4912 if (pb &&
4913 wuffs_base__pixel_format__is_indexed(&pb->pixcfg.private_impl.pixfmt)) {
4914 wuffs_base__table_u8* tab =
4915 &pb->private_impl
4916 .planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
4917 if ((tab->width ==
4918 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) &&
4919 (tab->height == 1)) {
4920 return wuffs_base__make_slice_u8(
4921 tab->ptr, WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH);
4922 }
4923 }
4924 return wuffs_base__make_slice_u8(NULL, 0);
4925}
4926
4927static inline wuffs_base__slice_u8 //
4928wuffs_base__pixel_buffer__palette_or_else(wuffs_base__pixel_buffer* pb,
4929 wuffs_base__slice_u8 fallback) {
4930 if (pb &&
4931 wuffs_base__pixel_format__is_indexed(&pb->pixcfg.private_impl.pixfmt)) {
4932 wuffs_base__table_u8* tab =
4933 &pb->private_impl
4934 .planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
4935 if ((tab->width ==
4936 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) &&
4937 (tab->height == 1)) {
4938 return wuffs_base__make_slice_u8(
4939 tab->ptr, WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH);
4940 }
4941 }
4942 return fallback;
4943}
4944
4945static inline wuffs_base__pixel_format //
4946wuffs_base__pixel_buffer__pixel_format(const wuffs_base__pixel_buffer* pb) {
4947 if (pb) {
4948 return pb->pixcfg.private_impl.pixfmt;
4949 }
4950 return wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__INVALID);
4951}
4952
4953static inline wuffs_base__table_u8 //
4954wuffs_base__pixel_buffer__plane(wuffs_base__pixel_buffer* pb, uint32_t p) {
4955 if (pb && (p < WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX)) {
4956 return pb->private_impl.planes[p];
4957 }
4958
4959 wuffs_base__table_u8 ret;
4960 ret.ptr = NULL;
4961 ret.width = 0;
4962 ret.height = 0;
4963 ret.stride = 0;
4964 return ret;
4965}
4966
4967WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //
4968wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,
4969 uint32_t x,
4970 uint32_t y);
4971
4972WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
4973wuffs_base__pixel_buffer__set_color_u32_at(
4974 wuffs_base__pixel_buffer* pb,
4975 uint32_t x,
4976 uint32_t y,
4977 wuffs_base__color_u32_argb_premul color);
4978
4979WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
4980wuffs_base__pixel_buffer__set_color_u32_fill_rect(
4981 wuffs_base__pixel_buffer* pb,
4982 wuffs_base__rect_ie_u32 rect,
4983 wuffs_base__color_u32_argb_premul color);
4984
4985#ifdef __cplusplus
4986
4987inline wuffs_base__status //
4988wuffs_base__pixel_buffer::set_interleaved(
4989 const wuffs_base__pixel_config* pixcfg_arg,
4990 wuffs_base__table_u8 primary_memory,
4991 wuffs_base__slice_u8 palette_memory) {
4992 return wuffs_base__pixel_buffer__set_interleaved(
4993 this, pixcfg_arg, primary_memory, palette_memory);
4994}
4995
4996inline wuffs_base__status //
4997wuffs_base__pixel_buffer::set_from_slice(
4998 const wuffs_base__pixel_config* pixcfg_arg,
4999 wuffs_base__slice_u8 pixbuf_memory) {
5000 return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg_arg,
5001 pixbuf_memory);
5002}
5003
5004inline wuffs_base__status //
5005wuffs_base__pixel_buffer::set_from_table(
5006 const wuffs_base__pixel_config* pixcfg_arg,
5007 wuffs_base__table_u8 primary_memory) {
5008 return wuffs_base__pixel_buffer__set_from_table(this, pixcfg_arg,
5009 primary_memory);
5010}
5011
5012inline wuffs_base__slice_u8 //
5013wuffs_base__pixel_buffer::palette() {
5014 return wuffs_base__pixel_buffer__palette(this);
5015}
5016
5017inline wuffs_base__slice_u8 //
5018wuffs_base__pixel_buffer::palette_or_else(wuffs_base__slice_u8 fallback) {
5019 return wuffs_base__pixel_buffer__palette_or_else(this, fallback);
5020}
5021
5022inline wuffs_base__pixel_format //
5023wuffs_base__pixel_buffer::pixel_format() const {
5024 return wuffs_base__pixel_buffer__pixel_format(this);
5025}
5026
5027inline wuffs_base__table_u8 //
5028wuffs_base__pixel_buffer::plane(uint32_t p) {
5029 return wuffs_base__pixel_buffer__plane(this, p);
5030}
5031
5032inline wuffs_base__color_u32_argb_premul //
5033wuffs_base__pixel_buffer::color_u32_at(uint32_t x, uint32_t y) const {
5034 return wuffs_base__pixel_buffer__color_u32_at(this, x, y);
5035}
5036
5037WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
5038wuffs_base__pixel_buffer__set_color_u32_fill_rect(
5039 wuffs_base__pixel_buffer* pb,
5040 wuffs_base__rect_ie_u32 rect,
5041 wuffs_base__color_u32_argb_premul color);
5042
5043inline wuffs_base__status //
5044wuffs_base__pixel_buffer::set_color_u32_at(
5045 uint32_t x,
5046 uint32_t y,
5047 wuffs_base__color_u32_argb_premul color) {
5048 return wuffs_base__pixel_buffer__set_color_u32_at(this, x, y, color);
5049}
5050
5051inline wuffs_base__status //
5052wuffs_base__pixel_buffer::set_color_u32_fill_rect(
5053 wuffs_base__rect_ie_u32 rect,
5054 wuffs_base__color_u32_argb_premul color) {
5055 return wuffs_base__pixel_buffer__set_color_u32_fill_rect(this, rect, color);
5056}
5057
5058#endif // __cplusplus
5059
5060// --------
5061
5062typedef struct wuffs_base__decode_frame_options__struct {
5063 // Do not access the private_impl's fields directly. There is no API/ABI
5064 // compatibility or safety guarantee if you do so.
5065 struct {
5066 uint8_t TODO;
5067 } private_impl;
5068
5069#ifdef __cplusplus
5070#endif // __cplusplus
5071
5072} wuffs_base__decode_frame_options;
5073
5074#ifdef __cplusplus
5075
5076#endif // __cplusplus
5077
5078// --------
5079
5080// wuffs_base__pixel_palette__closest_element returns the index of the palette
5081// element that minimizes the sum of squared differences of the four ARGB
5082// channels, working in premultiplied alpha. Ties favor the smaller index.
5083//
5084// The palette_slice.len may equal (N*4), for N less than 256, which means that
5085// only the first N palette elements are considered. It returns 0 when N is 0.
5086//
5087// Applying this function on a per-pixel basis will not produce whole-of-image
5088// dithering.
5089WUFFS_BASE__MAYBE_STATIC uint8_t //
5090wuffs_base__pixel_palette__closest_element(
5091 wuffs_base__slice_u8 palette_slice,
5092 wuffs_base__pixel_format palette_format,
5093 wuffs_base__color_u32_argb_premul c);
5094
5095// --------
5096
5097// TODO: should the func type take restrict pointers?
5098typedef uint64_t (*wuffs_base__pixel_swizzler__func)(uint8_t* dst_ptr,
5099 size_t dst_len,
5100 uint8_t* dst_palette_ptr,
5101 size_t dst_palette_len,
5102 const uint8_t* src_ptr,
5103 size_t src_len);
5104
5105typedef uint64_t (*wuffs_base__pixel_swizzler__transparent_black_func)(
5106 uint8_t* dst_ptr,
5107 size_t dst_len,
5108 uint8_t* dst_palette_ptr,
5109 size_t dst_palette_len,
5110 uint64_t num_pixels,
5111 uint32_t dst_pixfmt_bytes_per_pixel);
5112
5113typedef struct wuffs_base__pixel_swizzler__struct {
5114 // Do not access the private_impl's fields directly. There is no API/ABI
5115 // compatibility or safety guarantee if you do so.
5116 struct {
5117 wuffs_base__pixel_swizzler__func func;
5118 wuffs_base__pixel_swizzler__transparent_black_func transparent_black_func;
5119 uint32_t dst_pixfmt_bytes_per_pixel;
5120 uint32_t src_pixfmt_bytes_per_pixel;
5121 } private_impl;
5122
5123#ifdef __cplusplus
5124 inline wuffs_base__status prepare(wuffs_base__pixel_format dst_pixfmt,
5125 wuffs_base__slice_u8 dst_palette,
5126 wuffs_base__pixel_format src_pixfmt,
5127 wuffs_base__slice_u8 src_palette,
5128 wuffs_base__pixel_blend blend);
5129 inline uint64_t swizzle_interleaved_from_slice(
5130 wuffs_base__slice_u8 dst,
5131 wuffs_base__slice_u8 dst_palette,
5132 wuffs_base__slice_u8 src) const;
5133#endif // __cplusplus
5134
5135} wuffs_base__pixel_swizzler;
5136
5137// wuffs_base__pixel_swizzler__prepare readies the pixel swizzler so that its
5138// other methods may be called.
5139//
5140// For modular builds that divide the base module into sub-modules, using this
5141// function requires the WUFFS_CONFIG__MODULE__BASE__PIXCONV sub-module, not
5142// just WUFFS_CONFIG__MODULE__BASE__CORE.
5143WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
5144wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
5145 wuffs_base__pixel_format dst_pixfmt,
5146 wuffs_base__slice_u8 dst_palette,
5147 wuffs_base__pixel_format src_pixfmt,
5148 wuffs_base__slice_u8 src_palette,
5149 wuffs_base__pixel_blend blend);
5150
5151// wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice converts pixels
5152// from a source format to a destination format.
5153//
5154// For modular builds that divide the base module into sub-modules, using this
5155// function requires the WUFFS_CONFIG__MODULE__BASE__PIXCONV sub-module, not
5156// just WUFFS_CONFIG__MODULE__BASE__CORE.
5157WUFFS_BASE__MAYBE_STATIC uint64_t //
5158wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(
5159 const wuffs_base__pixel_swizzler* p,
5160 wuffs_base__slice_u8 dst,
5161 wuffs_base__slice_u8 dst_palette,
5162 wuffs_base__slice_u8 src);
5163
5164#ifdef __cplusplus
5165
5166inline wuffs_base__status //
5167wuffs_base__pixel_swizzler::prepare(wuffs_base__pixel_format dst_pixfmt,
5168 wuffs_base__slice_u8 dst_palette,
5169 wuffs_base__pixel_format src_pixfmt,
5170 wuffs_base__slice_u8 src_palette,
5171 wuffs_base__pixel_blend blend) {
5172 return wuffs_base__pixel_swizzler__prepare(this, dst_pixfmt, dst_palette,
5173 src_pixfmt, src_palette, blend);
5174}
5175
5176uint64_t //
5177wuffs_base__pixel_swizzler::swizzle_interleaved_from_slice(
5178 wuffs_base__slice_u8 dst,
5179 wuffs_base__slice_u8 dst_palette,
5180 wuffs_base__slice_u8 src) const {
5181 return wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(
5182 this, dst, dst_palette, src);
5183}
5184
5185#endif // __cplusplus
5186
5187// ---------------- String Conversions
5188
5189// Options (bitwise or'ed together) for wuffs_base__parse_number_xxx
5190// functions. The XXX options apply to both integer and floating point. The FXX
5191// options apply only to floating point.
5192
5193#define WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS ((uint32_t)0x00000000)
5194
5195// WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES means to accept
5196// inputs like "00", "0644" and "00.7". By default, they are rejected.
5197#define WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES \
5198 ((uint32_t)0x00000001)
5199
5200// WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES means to accept inputs like
5201// "1__2" and "_3.141_592". By default, they are rejected.
5202#define WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES ((uint32_t)0x00000002)
5203
5204// WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA means to accept
5205// "1,5" and not "1.5" as one-and-a-half.
5206//
5207// If the caller wants to accept either, it is responsible for canonicalizing
5208// the input before calling wuffs_base__parse_number_fxx. The caller also has
5209// more context on e.g. exactly how to treat something like "$1,234".
5210#define WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA \
5211 ((uint32_t)0x00000010)
5212
5213// WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN means to reject inputs that
5214// would lead to infinite or Not-a-Number floating point values. By default,
5215// they are accepted.
5216//
5217// This affects the literal "inf" as input, but also affects inputs like
5218// "1e999" that would overflow double-precision floating point.
5219#define WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN ((uint32_t)0x00000020)
5220
5221// --------
5222
5223// Options (bitwise or'ed together) for wuffs_base__render_number_xxx
5224// functions. The XXX options apply to both integer and floating point. The FXX
5225// options apply only to floating point.
5226
5227#define WUFFS_BASE__RENDER_NUMBER_XXX__DEFAULT_OPTIONS ((uint32_t)0x00000000)
5228
5229// WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT means to render to the right side
5230// (higher indexes) of the destination slice, leaving any untouched bytes on
5231// the left side (lower indexes). The default is vice versa: rendering on the
5232// left with slack on the right.
5233#define WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT ((uint32_t)0x00000100)
5234
5235// WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN means to render the leading
5236// "+" for non-negative numbers: "+0" and "+12.3" instead of "0" and "12.3".
5237#define WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN ((uint32_t)0x00000200)
5238
5239// WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA means to render
5240// one-and-a-half as "1,5" instead of "1.5".
5241#define WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA \
5242 ((uint32_t)0x00001000)
5243
5244// WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ETC means whether to never
5245// (EXPONENT_ABSENT, equivalent to printf's "%f") or to always
5246// (EXPONENT_PRESENT, equivalent to printf's "%e") render a floating point
5247// number as "1.23e+05" instead of "123000".
5248//
5249// Having both bits set is the same has having neither bit set, where the
5250// notation used depends on whether the exponent is sufficiently large: "0.5"
5251// is preferred over "5e-01" but "5e-09" is preferred over "0.000000005".
5252#define WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT ((uint32_t)0x00002000)
5253#define WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT ((uint32_t)0x00004000)
5254
5255// WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION means to render the
5256// smallest number of digits so that parsing the resultant string will recover
5257// the same double-precision floating point number.
5258//
5259// For example, double-precision cannot distinguish between 0.3 and
5260// 0.299999999999999988897769753748434595763683319091796875, so when this bit
5261// is set, rendering the latter will produce "0.3" but rendering
5262// 0.3000000000000000444089209850062616169452667236328125 will produce
5263// "0.30000000000000004".
5264#define WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION \
5265 ((uint32_t)0x00008000)
5266
5267// ---------------- IEEE 754 Floating Point
5268
5269// wuffs_base__ieee_754_bit_representation__etc converts between a double
5270// precision numerical value and its IEEE 754 representations:
Nigel Taobf9dab32021-11-18 19:19:55 +11005271// - 16-bit: 1 sign bit, 5 exponent bits, 10 explicit significand bits.
5272// - 32-bit: 1 sign bit, 8 exponent bits, 23 explicit significand bits.
5273// - 64-bit: 1 sign bit, 11 exponent bits, 52 explicit significand bits.
Nigel Taoe360a532021-04-05 22:47:03 +10005274//
5275// For example, it converts between:
5276// - +1.0 and 0x3C00, 0x3F80_0000 or 0x3FF0_0000_0000_0000.
5277// - +5.5 and 0x4580, 0x40B0_0000 or 0x4016_0000_0000_0000.
5278// - -inf and 0xFC00, 0xFF80_0000 or 0xFFF0_0000_0000_0000.
5279//
5280// Converting from f64 to shorter formats (f16 or f32, represented in C as
5281// uint16_t and uint32_t) may be lossy. Such functions have names that look
5282// like etc_truncate, as converting finite numbers produce equal or smaller
5283// (closer-to-zero) finite numbers. For example, 1048576.0 is a perfectly valid
5284// f64 number, but converting it to a f16 (with truncation) produces 65504.0,
5285// the largest finite f16 number. Truncating a f64-typed value d to f32 does
5286// not always produce the same result as the C-style cast ((float)d), as
5287// casting can convert from finite numbers to infinite ones.
5288//
5289// Converting infinities or NaNs produces infinities or NaNs and always report
5290// no loss, even though there a multiple NaN representations so that round-
5291// tripping a f64-typed NaN may produce a different 64 bits. Nonetheless, the
5292// etc_truncate functions preserve a NaN's "quiet vs signaling" bit.
5293//
5294// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format
5295
5296typedef struct wuffs_base__lossy_value_u16__struct {
5297 uint16_t value;
5298 bool lossy;
5299} wuffs_base__lossy_value_u16;
5300
5301typedef struct wuffs_base__lossy_value_u32__struct {
5302 uint32_t value;
5303 bool lossy;
5304} wuffs_base__lossy_value_u32;
5305
5306WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16 //
5307wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f);
5308
5309WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32 //
5310wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f);
5311
5312static inline uint64_t //
5313wuffs_base__ieee_754_bit_representation__from_f64_to_u64(double f) {
5314 uint64_t u = 0;
5315 if (sizeof(uint64_t) == sizeof(double)) {
5316 memcpy(&u, &f, sizeof(uint64_t));
5317 }
5318 return u;
5319}
5320
5321static inline double //
5322wuffs_base__ieee_754_bit_representation__from_u16_to_f64(uint16_t u) {
5323 uint64_t v = ((uint64_t)(u & 0x8000)) << 48;
5324
5325 do {
5326 uint64_t exp = (u >> 10) & 0x1F;
5327 uint64_t man = u & 0x3FF;
5328 if (exp == 0x1F) { // Infinity or NaN.
5329 exp = 2047;
5330 } else if (exp != 0) { // Normal.
5331 exp += 1008; // 1008 = 1023 - 15, the difference in biases.
5332 } else if (man != 0) { // Subnormal but non-zero.
5333 uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);
5334 exp = 1062 - clz; // 1062 = 1008 + 64 - 10.
5335 man = 0x3FF & (man << (clz - 53));
5336 } else { // Zero.
5337 break;
5338 }
5339 v |= (exp << 52) | (man << 42);
5340 } while (0);
5341
5342 double f = 0;
5343 if (sizeof(uint64_t) == sizeof(double)) {
5344 memcpy(&f, &v, sizeof(uint64_t));
5345 }
5346 return f;
5347}
5348
5349static inline double //
5350wuffs_base__ieee_754_bit_representation__from_u32_to_f64(uint32_t u) {
5351 float f = 0;
5352 if (sizeof(uint32_t) == sizeof(float)) {
5353 memcpy(&f, &u, sizeof(uint32_t));
5354 }
5355 return (double)f;
5356}
5357
5358static inline double //
5359wuffs_base__ieee_754_bit_representation__from_u64_to_f64(uint64_t u) {
5360 double f = 0;
5361 if (sizeof(uint64_t) == sizeof(double)) {
5362 memcpy(&f, &u, sizeof(uint64_t));
5363 }
5364 return f;
5365}
5366
5367// ---------------- Parsing and Rendering Numbers
5368
5369// wuffs_base__parse_number_f64 parses the floating point number in s. For
5370// example, if s contains the bytes "1.5" then it will return the double 1.5.
5371//
5372// It returns an error if s does not contain a floating point number.
5373//
5374// It does not necessarily return an error if the conversion is lossy, e.g. if
5375// s is "0.3", which double-precision floating point cannot represent exactly.
5376//
5377// Similarly, the returned value may be infinite (and no error returned) even
5378// if s was not "inf", when the input is nominally finite but sufficiently
5379// larger than DBL_MAX, about 1.8e+308.
5380//
5381// It is similar to the C standard library's strtod function, but:
5382// - Errors are returned in-band (in a result type), not out-of-band (errno).
5383// - It takes a slice (a pointer and length), not a NUL-terminated C string.
5384// - It does not take an optional endptr argument. It does not allow a partial
5385// parse: it returns an error unless all of s is consumed.
5386// - It does not allow whitespace, leading or otherwise.
5387// - It does not allow hexadecimal floating point numbers.
5388// - It is not affected by i18n / l10n settings such as environment variables.
5389//
5390// The options argument can change these, but by default, it:
5391// - Allows "inf", "+Infinity" and "-NAN", case insensitive. Similarly,
5392// without an explicit opt-out, it would successfully parse "1e999" as
5393// infinity, even though it overflows double-precision floating point.
5394// - Rejects underscores. With an explicit opt-in, "_3.141_592" would
5395// successfully parse as an approximation to π.
5396// - Rejects unnecessary leading zeroes: "00", "0644" and "00.7".
5397// - Uses a dot '1.5' instead of a comma '1,5' for the decimal separator.
5398//
5399// For modular builds that divide the base module into sub-modules, using this
5400// function requires the WUFFS_CONFIG__MODULE__BASE__FLOATCONV sub-module, not
5401// just WUFFS_CONFIG__MODULE__BASE__CORE.
5402WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
5403wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options);
5404
5405// wuffs_base__parse_number_i64 parses the ASCII integer in s. For example, if
5406// s contains the bytes "-123" then it will return the int64_t -123.
5407//
5408// It returns an error if s does not contain an integer or if the integer
5409// within would overflow an int64_t.
5410//
5411// It is similar to wuffs_base__parse_number_u64 but it returns a signed
5412// integer, not an unsigned integer. It also allows a leading '+' or '-'.
5413//
5414// For modular builds that divide the base module into sub-modules, using this
5415// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5416// just WUFFS_CONFIG__MODULE__BASE__CORE.
5417WUFFS_BASE__MAYBE_STATIC wuffs_base__result_i64 //
5418wuffs_base__parse_number_i64(wuffs_base__slice_u8 s, uint32_t options);
5419
5420// wuffs_base__parse_number_u64 parses the ASCII integer in s. For example, if
5421// s contains the bytes "123" then it will return the uint64_t 123.
5422//
5423// It returns an error if s does not contain an integer or if the integer
5424// within would overflow a uint64_t.
5425//
5426// It is similar to the C standard library's strtoull function, but:
5427// - Errors are returned in-band (in a result type), not out-of-band (errno).
5428// - It takes a slice (a pointer and length), not a NUL-terminated C string.
5429// - It does not take an optional endptr argument. It does not allow a partial
5430// parse: it returns an error unless all of s is consumed.
5431// - It does not allow whitespace, leading or otherwise.
5432// - It does not allow a leading '+' or '-'.
5433// - It does not take a base argument (e.g. base 10 vs base 16). Instead, it
5434// always accepts both decimal (e.g "1234", "0d5678") and hexadecimal (e.g.
5435// "0x9aBC"). The caller is responsible for prior filtering of e.g. hex
5436// numbers if they are unwanted. For example, Wuffs' JSON decoder will only
5437// produce a wuffs_base__token for decimal numbers, not hexadecimal.
5438// - It is not affected by i18n / l10n settings such as environment variables.
5439//
5440// The options argument can change these, but by default, it:
5441// - Rejects underscores. With an explicit opt-in, "__0D_1_002" would
5442// successfully parse as "one thousand and two". Underscores are still
5443// rejected inside the optional 2-byte opening "0d" or "0X" that denotes
5444// base-10 or base-16.
5445// - Rejects unnecessary leading zeroes: "00" and "0644".
5446//
5447// For modular builds that divide the base module into sub-modules, using this
5448// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5449// just WUFFS_CONFIG__MODULE__BASE__CORE.
5450WUFFS_BASE__MAYBE_STATIC wuffs_base__result_u64 //
5451wuffs_base__parse_number_u64(wuffs_base__slice_u8 s, uint32_t options);
5452
5453// --------
5454
5455// WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL is the string length of
5456// "-9223372036854775808" and "+9223372036854775807", INT64_MIN and INT64_MAX.
5457#define WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL 20
5458
5459// WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL is the string length of
5460// "+18446744073709551615", UINT64_MAX.
5461#define WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL 21
5462
5463// wuffs_base__render_number_f64 writes the decimal encoding of x to dst and
5464// returns the number of bytes written. If dst is shorter than the entire
5465// encoding, it returns 0 (and no bytes are written).
5466//
5467// For those familiar with C's printf or Go's fmt.Printf functions:
5468// - "%e" means the WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT option.
5469// - "%f" means the WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT option.
5470// - "%g" means neither or both bits are set.
5471//
5472// The precision argument controls the number of digits rendered, excluding the
5473// exponent (the "e+05" in "1.23e+05"):
5474// - for "%e" and "%f" it is the number of digits after the decimal separator,
5475// - for "%g" it is the number of significant digits (and trailing zeroes are
5476// removed).
5477//
5478// A precision of 6 gives similar output to printf's defaults.
5479//
5480// A precision greater than 4095 is equivalent to 4095.
5481//
5482// The precision argument is ignored when the
5483// WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION option is set. This is
5484// similar to Go's strconv.FormatFloat with a negative (i.e. non-sensical)
5485// precision, but there is no corresponding feature in C's printf.
5486//
5487// Extreme values of x will be rendered as "NaN", "Inf" (or "+Inf" if the
5488// WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN option is set) or "-Inf".
5489//
5490// For modular builds that divide the base module into sub-modules, using this
5491// function requires the WUFFS_CONFIG__MODULE__BASE__FLOATCONV sub-module, not
5492// just WUFFS_CONFIG__MODULE__BASE__CORE.
5493WUFFS_BASE__MAYBE_STATIC size_t //
5494wuffs_base__render_number_f64(wuffs_base__slice_u8 dst,
5495 double x,
5496 uint32_t precision,
5497 uint32_t options);
5498
5499// wuffs_base__render_number_i64 writes the decimal encoding of x to dst and
5500// returns the number of bytes written. If dst is shorter than the entire
5501// encoding, it returns 0 (and no bytes are written).
5502//
5503// dst will never be too short if its length is at least 20, also known as
5504// WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL.
5505//
5506// For modular builds that divide the base module into sub-modules, using this
5507// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5508// just WUFFS_CONFIG__MODULE__BASE__CORE.
5509WUFFS_BASE__MAYBE_STATIC size_t //
5510wuffs_base__render_number_i64(wuffs_base__slice_u8 dst,
5511 int64_t x,
5512 uint32_t options);
5513
5514// wuffs_base__render_number_u64 writes the decimal encoding of x to dst and
5515// returns the number of bytes written. If dst is shorter than the entire
5516// encoding, it returns 0 (and no bytes are written).
5517//
5518// dst will never be too short if its length is at least 21, also known as
5519// WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL.
5520//
5521// For modular builds that divide the base module into sub-modules, using this
5522// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5523// just WUFFS_CONFIG__MODULE__BASE__CORE.
5524WUFFS_BASE__MAYBE_STATIC size_t //
5525wuffs_base__render_number_u64(wuffs_base__slice_u8 dst,
5526 uint64_t x,
5527 uint32_t options);
5528
5529// ---------------- Base-16
5530
5531// Options (bitwise or'ed together) for wuffs_base__base_16__xxx functions.
5532
5533#define WUFFS_BASE__BASE_16__DEFAULT_OPTIONS ((uint32_t)0x00000000)
5534
5535// wuffs_base__base_16__decode2 converts "6A6b" to "jk", where e.g. 'j' is
5536// U+006A. There are 2 src bytes for every dst byte.
5537//
5538// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),
5539// repeated. It may write nonsense bytes if not, although it will not read or
5540// write out of bounds.
5541//
5542// For modular builds that divide the base module into sub-modules, using this
5543// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5544// just WUFFS_CONFIG__MODULE__BASE__CORE.
5545WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5546wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
5547 wuffs_base__slice_u8 src,
5548 bool src_closed,
5549 uint32_t options);
5550
5551// wuffs_base__base_16__decode4 converts both "\\x6A\\x6b" and "??6a??6B" to
5552// "jk", where e.g. 'j' is U+006A. There are 4 src bytes for every dst byte.
5553//
5554// It assumes that the src bytes are two ignored bytes and then two hexadecimal
5555// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,
5556// although it will not read or write out of bounds.
5557//
5558// For modular builds that divide the base module into sub-modules, using this
5559// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5560// just WUFFS_CONFIG__MODULE__BASE__CORE.
5561WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5562wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
5563 wuffs_base__slice_u8 src,
5564 bool src_closed,
5565 uint32_t options);
5566
5567// wuffs_base__base_16__encode2 converts "jk" to "6A6B", where e.g. 'j' is
5568// U+006A. There are 2 dst bytes for every src byte.
5569//
5570// For modular builds that divide the base module into sub-modules, using this
5571// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5572// just WUFFS_CONFIG__MODULE__BASE__CORE.
5573WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5574wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
5575 wuffs_base__slice_u8 src,
5576 bool src_closed,
5577 uint32_t options);
5578
5579// wuffs_base__base_16__encode4 converts "jk" to "\\x6A\\x6B", where e.g. 'j'
5580// is U+006A. There are 4 dst bytes for every src byte.
5581//
5582// For modular builds that divide the base module into sub-modules, using this
5583// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5584// just WUFFS_CONFIG__MODULE__BASE__CORE.
5585WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5586wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
5587 wuffs_base__slice_u8 src,
5588 bool src_closed,
5589 uint32_t options);
5590
5591// ---------------- Base-64
5592
5593// Options (bitwise or'ed together) for wuffs_base__base_64__xxx functions.
5594
5595#define WUFFS_BASE__BASE_64__DEFAULT_OPTIONS ((uint32_t)0x00000000)
5596
5597// WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING means that, when decoding base-64,
5598// the input may (but does not need to) be padded with '=' bytes so that the
5599// overall encoded length in bytes is a multiple of 4. A successful decoding
5600// will return a num_src that includes those padding bytes.
5601//
5602// Excess padding (e.g. three final '='s) will be rejected as bad data.
5603#define WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING ((uint32_t)0x00000001)
5604
5605// WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING means that, when encoding base-64,
5606// the output will be padded with '=' bytes so that the overall encoded length
5607// in bytes is a multiple of 4.
5608#define WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING ((uint32_t)0x00000002)
5609
5610// WUFFS_BASE__BASE_64__URL_ALPHABET means that, for base-64, the URL-friendly
5611// and file-name-friendly alphabet be used, as per RFC 4648 section 5. When
5612// this option bit is off, the standard alphabet from section 4 is used.
5613#define WUFFS_BASE__BASE_64__URL_ALPHABET ((uint32_t)0x00000100)
5614
5615// wuffs_base__base_64__decode transforms base-64 encoded bytes from src to
5616// arbitrary bytes in dst.
5617//
5618// It will not permit line breaks or other whitespace in src. Filtering those
5619// out is the responsibility of the caller.
5620//
5621// For modular builds that divide the base module into sub-modules, using this
5622// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5623// just WUFFS_CONFIG__MODULE__BASE__CORE.
5624WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5625wuffs_base__base_64__decode(wuffs_base__slice_u8 dst,
5626 wuffs_base__slice_u8 src,
5627 bool src_closed,
5628 uint32_t options);
5629
5630// wuffs_base__base_64__encode transforms arbitrary bytes from src to base-64
5631// encoded bytes in dst.
5632//
5633// For modular builds that divide the base module into sub-modules, using this
5634// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5635// just WUFFS_CONFIG__MODULE__BASE__CORE.
5636WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5637wuffs_base__base_64__encode(wuffs_base__slice_u8 dst,
5638 wuffs_base__slice_u8 src,
5639 bool src_closed,
5640 uint32_t options);
5641
5642// ---------------- Unicode and UTF-8
5643
5644#define WUFFS_BASE__UNICODE_CODE_POINT__MIN_INCL 0x00000000
5645#define WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL 0x0010FFFF
5646
5647#define WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER 0x0000FFFD
5648
5649#define WUFFS_BASE__UNICODE_SURROGATE__MIN_INCL 0x0000D800
5650#define WUFFS_BASE__UNICODE_SURROGATE__MAX_INCL 0x0000DFFF
5651
5652#define WUFFS_BASE__ASCII__MIN_INCL 0x00
5653#define WUFFS_BASE__ASCII__MAX_INCL 0x7F
5654
5655#define WUFFS_BASE__UTF_8__BYTE_LENGTH__MIN_INCL 1
5656#define WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL 4
5657
5658#define WUFFS_BASE__UTF_8__BYTE_LENGTH_1__CODE_POINT__MIN_INCL 0x00000000
5659#define WUFFS_BASE__UTF_8__BYTE_LENGTH_1__CODE_POINT__MAX_INCL 0x0000007F
5660#define WUFFS_BASE__UTF_8__BYTE_LENGTH_2__CODE_POINT__MIN_INCL 0x00000080
5661#define WUFFS_BASE__UTF_8__BYTE_LENGTH_2__CODE_POINT__MAX_INCL 0x000007FF
5662#define WUFFS_BASE__UTF_8__BYTE_LENGTH_3__CODE_POINT__MIN_INCL 0x00000800
5663#define WUFFS_BASE__UTF_8__BYTE_LENGTH_3__CODE_POINT__MAX_INCL 0x0000FFFF
5664#define WUFFS_BASE__UTF_8__BYTE_LENGTH_4__CODE_POINT__MIN_INCL 0x00010000
5665#define WUFFS_BASE__UTF_8__BYTE_LENGTH_4__CODE_POINT__MAX_INCL 0x0010FFFF
5666
5667// --------
5668
5669// wuffs_base__utf_8__next__output is the type returned by
5670// wuffs_base__utf_8__next.
5671typedef struct wuffs_base__utf_8__next__output__struct {
5672 uint32_t code_point;
5673 uint32_t byte_length;
5674
5675#ifdef __cplusplus
5676 inline bool is_valid() const;
5677#endif // __cplusplus
5678
5679} wuffs_base__utf_8__next__output;
5680
5681static inline wuffs_base__utf_8__next__output //
5682wuffs_base__make_utf_8__next__output(uint32_t code_point,
5683 uint32_t byte_length) {
5684 wuffs_base__utf_8__next__output ret;
5685 ret.code_point = code_point;
5686 ret.byte_length = byte_length;
5687 return ret;
5688}
5689
5690static inline bool //
5691wuffs_base__utf_8__next__output__is_valid(
5692 const wuffs_base__utf_8__next__output* o) {
5693 if (o) {
5694 uint32_t cp = o->code_point;
5695 switch (o->byte_length) {
5696 case 1:
5697 return (cp <= 0x7F);
5698 case 2:
5699 return (0x080 <= cp) && (cp <= 0x7FF);
5700 case 3:
5701 // Avoid the 0xD800 ..= 0xDFFF surrogate range.
5702 return ((0x0800 <= cp) && (cp <= 0xD7FF)) ||
5703 ((0xE000 <= cp) && (cp <= 0xFFFF));
5704 case 4:
5705 return (0x00010000 <= cp) && (cp <= 0x0010FFFF);
5706 }
5707 }
5708 return false;
5709}
5710
5711#ifdef __cplusplus
5712
5713inline bool //
5714wuffs_base__utf_8__next__output::is_valid() const {
5715 return wuffs_base__utf_8__next__output__is_valid(this);
5716}
5717
5718#endif // __cplusplus
5719
5720// --------
5721
5722// wuffs_base__utf_8__encode writes the UTF-8 encoding of code_point to s and
5723// returns the number of bytes written. If code_point is invalid, or if s is
5724// shorter than the entire encoding, it returns 0 (and no bytes are written).
5725//
5726// s will never be too short if its length is at least 4, also known as
5727// WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL.
5728//
5729// For modular builds that divide the base module into sub-modules, using this
5730// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5731// WUFFS_CONFIG__MODULE__BASE__CORE.
5732WUFFS_BASE__MAYBE_STATIC size_t //
5733wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point);
5734
5735// wuffs_base__utf_8__next returns the next UTF-8 code point (and that code
5736// point's byte length) at the start of the read-only slice (s_ptr, s_len).
5737//
5738// There are exactly two cases in which this function returns something where
5739// wuffs_base__utf_8__next__output__is_valid is false:
5740// - If s is empty then it returns {.code_point=0, .byte_length=0}.
5741// - If s is non-empty and starts with invalid UTF-8 then it returns
5742// {.code_point=WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, .byte_length=1}.
5743//
5744// Otherwise, it returns something where
5745// wuffs_base__utf_8__next__output__is_valid is true.
5746//
5747// In any case, it always returns an output that satisfies both of:
5748// - (output.code_point <= WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL).
5749// - (output.byte_length <= s_len).
5750//
5751// If s is a sub-slice of a larger slice of valid UTF-8, but that sub-slice
5752// boundary occurs in the middle of a multi-byte UTF-8 encoding of a single
5753// code point, then this function may return something invalid. It is the
5754// caller's responsibility to split on or otherwise manage UTF-8 boundaries.
5755//
5756// For modular builds that divide the base module into sub-modules, using this
5757// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5758// WUFFS_CONFIG__MODULE__BASE__CORE.
5759WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
5760wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len);
5761
5762// wuffs_base__utf_8__next_from_end is like wuffs_base__utf_8__next except that
5763// it looks at the end of (s_ptr, s_len) instead of the start.
5764//
5765// For modular builds that divide the base module into sub-modules, using this
5766// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5767// WUFFS_CONFIG__MODULE__BASE__CORE.
5768WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
5769wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len);
5770
5771// wuffs_base__utf_8__longest_valid_prefix returns the largest n such that the
5772// sub-slice s[..n] is valid UTF-8, where s is the read-only slice (s_ptr,
5773// s_len).
5774//
5775// In particular, it returns s_len if and only if all of s is valid UTF-8.
5776//
5777// If s is a sub-slice of a larger slice of valid UTF-8, but that sub-slice
5778// boundary occurs in the middle of a multi-byte UTF-8 encoding of a single
5779// code point, then this function will return less than s_len. It is the
5780// caller's responsibility to split on or otherwise manage UTF-8 boundaries.
5781//
5782// For modular builds that divide the base module into sub-modules, using this
5783// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5784// WUFFS_CONFIG__MODULE__BASE__CORE.
5785WUFFS_BASE__MAYBE_STATIC size_t //
5786wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len);
5787
5788// wuffs_base__ascii__longest_valid_prefix returns the largest n such that the
5789// sub-slice s[..n] is valid ASCII, where s is the read-only slice (s_ptr,
5790// s_len).
5791//
5792// In particular, it returns s_len if and only if all of s is valid ASCII.
5793// Equivalently, when none of the bytes in s have the 0x80 high bit set.
5794//
5795// For modular builds that divide the base module into sub-modules, using this
5796// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5797// WUFFS_CONFIG__MODULE__BASE__CORE.
5798WUFFS_BASE__MAYBE_STATIC size_t //
5799wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len);
5800
5801// ---------------- Interface Declarations.
5802
5803// For modular builds that divide the base module into sub-modules, using these
5804// functions require the WUFFS_CONFIG__MODULE__BASE__INTERFACES sub-module, not
5805// just WUFFS_CONFIG__MODULE__BASE__CORE.
5806
5807// --------
5808
5809extern const char wuffs_base__hasher_u32__vtable_name[];
5810
5811typedef struct wuffs_base__hasher_u32__func_ptrs__struct {
5812 wuffs_base__empty_struct (*set_quirk_enabled)(
5813 void* self,
5814 uint32_t a_quirk,
5815 bool a_enabled);
5816 uint32_t (*update_u32)(
5817 void* self,
5818 wuffs_base__slice_u8 a_x);
5819} wuffs_base__hasher_u32__func_ptrs;
5820
5821typedef struct wuffs_base__hasher_u32__struct wuffs_base__hasher_u32;
5822
5823WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
5824wuffs_base__hasher_u32__set_quirk_enabled(
5825 wuffs_base__hasher_u32* self,
5826 uint32_t a_quirk,
5827 bool a_enabled);
5828
5829WUFFS_BASE__MAYBE_STATIC uint32_t
5830wuffs_base__hasher_u32__update_u32(
5831 wuffs_base__hasher_u32* self,
5832 wuffs_base__slice_u8 a_x);
5833
5834#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
5835
5836struct wuffs_base__hasher_u32__struct {
5837 struct {
5838 uint32_t magic;
5839 uint32_t active_coroutine;
5840 wuffs_base__vtable first_vtable;
5841 } private_impl;
5842
5843#ifdef __cplusplus
5844#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
5845 using unique_ptr = std::unique_ptr<wuffs_base__hasher_u32, decltype(&free)>;
5846#endif
5847
5848 inline wuffs_base__empty_struct
5849 set_quirk_enabled(
5850 uint32_t a_quirk,
5851 bool a_enabled) {
5852 return wuffs_base__hasher_u32__set_quirk_enabled(
5853 this, a_quirk, a_enabled);
5854 }
5855
5856 inline uint32_t
5857 update_u32(
5858 wuffs_base__slice_u8 a_x) {
5859 return wuffs_base__hasher_u32__update_u32(
5860 this, a_x);
5861 }
5862
5863#endif // __cplusplus
5864}; // struct wuffs_base__hasher_u32__struct
5865
5866#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
5867
5868// --------
5869
5870extern const char wuffs_base__image_decoder__vtable_name[];
5871
5872typedef struct wuffs_base__image_decoder__func_ptrs__struct {
5873 wuffs_base__status (*decode_frame)(
5874 void* self,
5875 wuffs_base__pixel_buffer* a_dst,
5876 wuffs_base__io_buffer* a_src,
5877 wuffs_base__pixel_blend a_blend,
5878 wuffs_base__slice_u8 a_workbuf,
5879 wuffs_base__decode_frame_options* a_opts);
5880 wuffs_base__status (*decode_frame_config)(
5881 void* self,
5882 wuffs_base__frame_config* a_dst,
5883 wuffs_base__io_buffer* a_src);
5884 wuffs_base__status (*decode_image_config)(
5885 void* self,
5886 wuffs_base__image_config* a_dst,
5887 wuffs_base__io_buffer* a_src);
5888 wuffs_base__rect_ie_u32 (*frame_dirty_rect)(
5889 const void* self);
5890 uint32_t (*num_animation_loops)(
5891 const void* self);
5892 uint64_t (*num_decoded_frame_configs)(
5893 const void* self);
5894 uint64_t (*num_decoded_frames)(
5895 const void* self);
5896 wuffs_base__status (*restart_frame)(
5897 void* self,
5898 uint64_t a_index,
5899 uint64_t a_io_position);
5900 wuffs_base__empty_struct (*set_quirk_enabled)(
5901 void* self,
5902 uint32_t a_quirk,
5903 bool a_enabled);
5904 wuffs_base__empty_struct (*set_report_metadata)(
5905 void* self,
5906 uint32_t a_fourcc,
5907 bool a_report);
5908 wuffs_base__status (*tell_me_more)(
5909 void* self,
5910 wuffs_base__io_buffer* a_dst,
5911 wuffs_base__more_information* a_minfo,
5912 wuffs_base__io_buffer* a_src);
5913 wuffs_base__range_ii_u64 (*workbuf_len)(
5914 const void* self);
5915} wuffs_base__image_decoder__func_ptrs;
5916
5917typedef struct wuffs_base__image_decoder__struct wuffs_base__image_decoder;
5918
5919WUFFS_BASE__MAYBE_STATIC wuffs_base__status
5920wuffs_base__image_decoder__decode_frame(
5921 wuffs_base__image_decoder* self,
5922 wuffs_base__pixel_buffer* a_dst,
5923 wuffs_base__io_buffer* a_src,
5924 wuffs_base__pixel_blend a_blend,
5925 wuffs_base__slice_u8 a_workbuf,
5926 wuffs_base__decode_frame_options* a_opts);
5927
5928WUFFS_BASE__MAYBE_STATIC wuffs_base__status
5929wuffs_base__image_decoder__decode_frame_config(
5930 wuffs_base__image_decoder* self,
5931 wuffs_base__frame_config* a_dst,
5932 wuffs_base__io_buffer* a_src);
5933
5934WUFFS_BASE__MAYBE_STATIC wuffs_base__status
5935wuffs_base__image_decoder__decode_image_config(
5936 wuffs_base__image_decoder* self,
5937 wuffs_base__image_config* a_dst,
5938 wuffs_base__io_buffer* a_src);
5939
5940WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
5941wuffs_base__image_decoder__frame_dirty_rect(
5942 const wuffs_base__image_decoder* self);
5943
5944WUFFS_BASE__MAYBE_STATIC uint32_t
5945wuffs_base__image_decoder__num_animation_loops(
5946 const wuffs_base__image_decoder* self);
5947
5948WUFFS_BASE__MAYBE_STATIC uint64_t
5949wuffs_base__image_decoder__num_decoded_frame_configs(
5950 const wuffs_base__image_decoder* self);
5951
5952WUFFS_BASE__MAYBE_STATIC uint64_t
5953wuffs_base__image_decoder__num_decoded_frames(
5954 const wuffs_base__image_decoder* self);
5955
5956WUFFS_BASE__MAYBE_STATIC wuffs_base__status
5957wuffs_base__image_decoder__restart_frame(
5958 wuffs_base__image_decoder* self,
5959 uint64_t a_index,
5960 uint64_t a_io_position);
5961
5962WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
5963wuffs_base__image_decoder__set_quirk_enabled(
5964 wuffs_base__image_decoder* self,
5965 uint32_t a_quirk,
5966 bool a_enabled);
5967
5968WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
5969wuffs_base__image_decoder__set_report_metadata(
5970 wuffs_base__image_decoder* self,
5971 uint32_t a_fourcc,
5972 bool a_report);
5973
5974WUFFS_BASE__MAYBE_STATIC wuffs_base__status
5975wuffs_base__image_decoder__tell_me_more(
5976 wuffs_base__image_decoder* self,
5977 wuffs_base__io_buffer* a_dst,
5978 wuffs_base__more_information* a_minfo,
5979 wuffs_base__io_buffer* a_src);
5980
5981WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
5982wuffs_base__image_decoder__workbuf_len(
5983 const wuffs_base__image_decoder* self);
5984
5985#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
5986
5987struct wuffs_base__image_decoder__struct {
5988 struct {
5989 uint32_t magic;
5990 uint32_t active_coroutine;
5991 wuffs_base__vtable first_vtable;
5992 } private_impl;
5993
5994#ifdef __cplusplus
5995#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
5996 using unique_ptr = std::unique_ptr<wuffs_base__image_decoder, decltype(&free)>;
5997#endif
5998
5999 inline wuffs_base__status
6000 decode_frame(
6001 wuffs_base__pixel_buffer* a_dst,
6002 wuffs_base__io_buffer* a_src,
6003 wuffs_base__pixel_blend a_blend,
6004 wuffs_base__slice_u8 a_workbuf,
6005 wuffs_base__decode_frame_options* a_opts) {
6006 return wuffs_base__image_decoder__decode_frame(
6007 this, a_dst, a_src, a_blend, a_workbuf, a_opts);
6008 }
6009
6010 inline wuffs_base__status
6011 decode_frame_config(
6012 wuffs_base__frame_config* a_dst,
6013 wuffs_base__io_buffer* a_src) {
6014 return wuffs_base__image_decoder__decode_frame_config(
6015 this, a_dst, a_src);
6016 }
6017
6018 inline wuffs_base__status
6019 decode_image_config(
6020 wuffs_base__image_config* a_dst,
6021 wuffs_base__io_buffer* a_src) {
6022 return wuffs_base__image_decoder__decode_image_config(
6023 this, a_dst, a_src);
6024 }
6025
6026 inline wuffs_base__rect_ie_u32
6027 frame_dirty_rect() const {
6028 return wuffs_base__image_decoder__frame_dirty_rect(this);
6029 }
6030
6031 inline uint32_t
6032 num_animation_loops() const {
6033 return wuffs_base__image_decoder__num_animation_loops(this);
6034 }
6035
6036 inline uint64_t
6037 num_decoded_frame_configs() const {
6038 return wuffs_base__image_decoder__num_decoded_frame_configs(this);
6039 }
6040
6041 inline uint64_t
6042 num_decoded_frames() const {
6043 return wuffs_base__image_decoder__num_decoded_frames(this);
6044 }
6045
6046 inline wuffs_base__status
6047 restart_frame(
6048 uint64_t a_index,
6049 uint64_t a_io_position) {
6050 return wuffs_base__image_decoder__restart_frame(
6051 this, a_index, a_io_position);
6052 }
6053
6054 inline wuffs_base__empty_struct
6055 set_quirk_enabled(
6056 uint32_t a_quirk,
6057 bool a_enabled) {
6058 return wuffs_base__image_decoder__set_quirk_enabled(
6059 this, a_quirk, a_enabled);
6060 }
6061
6062 inline wuffs_base__empty_struct
6063 set_report_metadata(
6064 uint32_t a_fourcc,
6065 bool a_report) {
6066 return wuffs_base__image_decoder__set_report_metadata(
6067 this, a_fourcc, a_report);
6068 }
6069
6070 inline wuffs_base__status
6071 tell_me_more(
6072 wuffs_base__io_buffer* a_dst,
6073 wuffs_base__more_information* a_minfo,
6074 wuffs_base__io_buffer* a_src) {
6075 return wuffs_base__image_decoder__tell_me_more(
6076 this, a_dst, a_minfo, a_src);
6077 }
6078
6079 inline wuffs_base__range_ii_u64
6080 workbuf_len() const {
6081 return wuffs_base__image_decoder__workbuf_len(this);
6082 }
6083
6084#endif // __cplusplus
6085}; // struct wuffs_base__image_decoder__struct
6086
6087#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6088
6089// --------
6090
6091extern const char wuffs_base__io_transformer__vtable_name[];
6092
6093typedef struct wuffs_base__io_transformer__func_ptrs__struct {
6094 wuffs_base__empty_struct (*set_quirk_enabled)(
6095 void* self,
6096 uint32_t a_quirk,
6097 bool a_enabled);
6098 wuffs_base__status (*transform_io)(
6099 void* self,
6100 wuffs_base__io_buffer* a_dst,
6101 wuffs_base__io_buffer* a_src,
6102 wuffs_base__slice_u8 a_workbuf);
6103 wuffs_base__range_ii_u64 (*workbuf_len)(
6104 const void* self);
6105} wuffs_base__io_transformer__func_ptrs;
6106
6107typedef struct wuffs_base__io_transformer__struct wuffs_base__io_transformer;
6108
6109WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6110wuffs_base__io_transformer__set_quirk_enabled(
6111 wuffs_base__io_transformer* self,
6112 uint32_t a_quirk,
6113 bool a_enabled);
6114
6115WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6116wuffs_base__io_transformer__transform_io(
6117 wuffs_base__io_transformer* self,
6118 wuffs_base__io_buffer* a_dst,
6119 wuffs_base__io_buffer* a_src,
6120 wuffs_base__slice_u8 a_workbuf);
6121
6122WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6123wuffs_base__io_transformer__workbuf_len(
6124 const wuffs_base__io_transformer* self);
6125
6126#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6127
6128struct wuffs_base__io_transformer__struct {
6129 struct {
6130 uint32_t magic;
6131 uint32_t active_coroutine;
6132 wuffs_base__vtable first_vtable;
6133 } private_impl;
6134
6135#ifdef __cplusplus
6136#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6137 using unique_ptr = std::unique_ptr<wuffs_base__io_transformer, decltype(&free)>;
6138#endif
6139
6140 inline wuffs_base__empty_struct
6141 set_quirk_enabled(
6142 uint32_t a_quirk,
6143 bool a_enabled) {
6144 return wuffs_base__io_transformer__set_quirk_enabled(
6145 this, a_quirk, a_enabled);
6146 }
6147
6148 inline wuffs_base__status
6149 transform_io(
6150 wuffs_base__io_buffer* a_dst,
6151 wuffs_base__io_buffer* a_src,
6152 wuffs_base__slice_u8 a_workbuf) {
6153 return wuffs_base__io_transformer__transform_io(
6154 this, a_dst, a_src, a_workbuf);
6155 }
6156
6157 inline wuffs_base__range_ii_u64
6158 workbuf_len() const {
6159 return wuffs_base__io_transformer__workbuf_len(this);
6160 }
6161
6162#endif // __cplusplus
6163}; // struct wuffs_base__io_transformer__struct
6164
6165#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6166
6167// --------
6168
6169extern const char wuffs_base__token_decoder__vtable_name[];
6170
6171typedef struct wuffs_base__token_decoder__func_ptrs__struct {
6172 wuffs_base__status (*decode_tokens)(
6173 void* self,
6174 wuffs_base__token_buffer* a_dst,
6175 wuffs_base__io_buffer* a_src,
6176 wuffs_base__slice_u8 a_workbuf);
6177 wuffs_base__empty_struct (*set_quirk_enabled)(
6178 void* self,
6179 uint32_t a_quirk,
6180 bool a_enabled);
6181 wuffs_base__range_ii_u64 (*workbuf_len)(
6182 const void* self);
6183} wuffs_base__token_decoder__func_ptrs;
6184
6185typedef struct wuffs_base__token_decoder__struct wuffs_base__token_decoder;
6186
6187WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6188wuffs_base__token_decoder__decode_tokens(
6189 wuffs_base__token_decoder* self,
6190 wuffs_base__token_buffer* a_dst,
6191 wuffs_base__io_buffer* a_src,
6192 wuffs_base__slice_u8 a_workbuf);
6193
6194WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6195wuffs_base__token_decoder__set_quirk_enabled(
6196 wuffs_base__token_decoder* self,
6197 uint32_t a_quirk,
6198 bool a_enabled);
6199
6200WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6201wuffs_base__token_decoder__workbuf_len(
6202 const wuffs_base__token_decoder* self);
6203
6204#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6205
6206struct wuffs_base__token_decoder__struct {
6207 struct {
6208 uint32_t magic;
6209 uint32_t active_coroutine;
6210 wuffs_base__vtable first_vtable;
6211 } private_impl;
6212
6213#ifdef __cplusplus
6214#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6215 using unique_ptr = std::unique_ptr<wuffs_base__token_decoder, decltype(&free)>;
6216#endif
6217
6218 inline wuffs_base__status
6219 decode_tokens(
6220 wuffs_base__token_buffer* a_dst,
6221 wuffs_base__io_buffer* a_src,
6222 wuffs_base__slice_u8 a_workbuf) {
6223 return wuffs_base__token_decoder__decode_tokens(
6224 this, a_dst, a_src, a_workbuf);
6225 }
6226
6227 inline wuffs_base__empty_struct
6228 set_quirk_enabled(
6229 uint32_t a_quirk,
6230 bool a_enabled) {
6231 return wuffs_base__token_decoder__set_quirk_enabled(
6232 this, a_quirk, a_enabled);
6233 }
6234
6235 inline wuffs_base__range_ii_u64
6236 workbuf_len() const {
6237 return wuffs_base__token_decoder__workbuf_len(this);
6238 }
6239
6240#endif // __cplusplus
6241}; // struct wuffs_base__token_decoder__struct
6242
6243#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6244
6245// ----------------
6246
6247#ifdef __cplusplus
6248} // extern "C"
6249#endif
6250
6251// ---------------- Status Codes
6252
6253// ---------------- Public Consts
6254
6255// ---------------- Struct Declarations
6256
6257typedef struct wuffs_adler32__hasher__struct wuffs_adler32__hasher;
6258
6259#ifdef __cplusplus
6260extern "C" {
6261#endif
6262
6263// ---------------- Public Initializer Prototypes
6264
6265// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
6266// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
6267//
6268// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
6269// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
6270
6271wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6272wuffs_adler32__hasher__initialize(
6273 wuffs_adler32__hasher* self,
6274 size_t sizeof_star_self,
6275 uint64_t wuffs_version,
6276 uint32_t options);
6277
6278size_t
6279sizeof__wuffs_adler32__hasher();
6280
6281// ---------------- Allocs
6282
6283// These functions allocate and initialize Wuffs structs. They return NULL if
6284// memory allocation fails. If they return non-NULL, there is no need to call
6285// wuffs_foo__bar__initialize, but the caller is responsible for eventually
6286// calling free on the returned pointer. That pointer is effectively a C++
6287// std::unique_ptr<T, decltype(&free)>.
6288
6289wuffs_adler32__hasher*
6290wuffs_adler32__hasher__alloc();
6291
6292static inline wuffs_base__hasher_u32*
6293wuffs_adler32__hasher__alloc_as__wuffs_base__hasher_u32() {
6294 return (wuffs_base__hasher_u32*)(wuffs_adler32__hasher__alloc());
6295}
6296
6297// ---------------- Upcasts
6298
6299static inline wuffs_base__hasher_u32*
6300wuffs_adler32__hasher__upcast_as__wuffs_base__hasher_u32(
6301 wuffs_adler32__hasher* p) {
6302 return (wuffs_base__hasher_u32*)p;
6303}
6304
6305// ---------------- Public Function Prototypes
6306
6307WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6308wuffs_adler32__hasher__set_quirk_enabled(
6309 wuffs_adler32__hasher* self,
6310 uint32_t a_quirk,
6311 bool a_enabled);
6312
6313WUFFS_BASE__MAYBE_STATIC uint32_t
6314wuffs_adler32__hasher__update_u32(
6315 wuffs_adler32__hasher* self,
6316 wuffs_base__slice_u8 a_x);
6317
6318#ifdef __cplusplus
6319} // extern "C"
6320#endif
6321
6322// ---------------- Struct Definitions
6323
6324// These structs' fields, and the sizeof them, are private implementation
6325// details that aren't guaranteed to be stable across Wuffs versions.
6326//
6327// See https://en.wikipedia.org/wiki/Opaque_pointer#C
6328
6329#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6330
6331struct wuffs_adler32__hasher__struct {
6332 // Do not access the private_impl's or private_data's fields directly. There
6333 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
6334 // the wuffs_foo__bar__baz functions.
6335 //
6336 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
6337 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
6338
6339 struct {
6340 uint32_t magic;
6341 uint32_t active_coroutine;
6342 wuffs_base__vtable vtable_for__wuffs_base__hasher_u32;
6343 wuffs_base__vtable null_vtable;
6344
6345 uint32_t f_state;
6346 bool f_started;
6347
6348 wuffs_base__empty_struct (*choosy_up)(
6349 wuffs_adler32__hasher* self,
6350 wuffs_base__slice_u8 a_x);
6351 } private_impl;
6352
6353#ifdef __cplusplus
6354#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6355 using unique_ptr = std::unique_ptr<wuffs_adler32__hasher, decltype(&free)>;
6356
6357 // On failure, the alloc_etc functions return nullptr. They don't throw.
6358
6359 static inline unique_ptr
6360 alloc() {
6361 return unique_ptr(wuffs_adler32__hasher__alloc(), &free);
6362 }
6363
6364 static inline wuffs_base__hasher_u32::unique_ptr
6365 alloc_as__wuffs_base__hasher_u32() {
6366 return wuffs_base__hasher_u32::unique_ptr(
6367 wuffs_adler32__hasher__alloc_as__wuffs_base__hasher_u32(), &free);
6368 }
6369#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6370
6371#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6372 // Disallow constructing or copying an object via standard C++ mechanisms,
6373 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
6374 // size and field layout is not part of the public, stable, memory-safe API.
6375 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
6376 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
6377 // their first argument) rather than tweaking bar.private_impl.qux fields.
6378 //
6379 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
6380 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
6381 // order to provide convenience methods. These forward on "this", so that you
6382 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
6383 wuffs_adler32__hasher__struct() = delete;
6384 wuffs_adler32__hasher__struct(const wuffs_adler32__hasher__struct&) = delete;
6385 wuffs_adler32__hasher__struct& operator=(
6386 const wuffs_adler32__hasher__struct&) = delete;
6387#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6388
6389#if !defined(WUFFS_IMPLEMENTATION)
6390 // As above, the size of the struct is not part of the public API, and unless
6391 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
6392 // allocated, not stack allocated. Its size is not intended to be known at
6393 // compile time, but it is unfortunately divulged as a side effect of
6394 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
6395 // instead of "sizeof T", invoking the operator. To make the two values
6396 // different, so that passing the latter will be rejected by the initialize
6397 // function, we add an arbitrary amount of dead weight.
6398 uint8_t dead_weight[123000000]; // 123 MB.
6399#endif // !defined(WUFFS_IMPLEMENTATION)
6400
6401 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6402 initialize(
6403 size_t sizeof_star_self,
6404 uint64_t wuffs_version,
6405 uint32_t options) {
6406 return wuffs_adler32__hasher__initialize(
6407 this, sizeof_star_self, wuffs_version, options);
6408 }
6409
6410 inline wuffs_base__hasher_u32*
6411 upcast_as__wuffs_base__hasher_u32() {
6412 return (wuffs_base__hasher_u32*)this;
6413 }
6414
6415 inline wuffs_base__empty_struct
6416 set_quirk_enabled(
6417 uint32_t a_quirk,
6418 bool a_enabled) {
6419 return wuffs_adler32__hasher__set_quirk_enabled(this, a_quirk, a_enabled);
6420 }
6421
6422 inline uint32_t
6423 update_u32(
6424 wuffs_base__slice_u8 a_x) {
6425 return wuffs_adler32__hasher__update_u32(this, a_x);
6426 }
6427
6428#endif // __cplusplus
6429}; // struct wuffs_adler32__hasher__struct
6430
6431#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6432
6433// ---------------- Status Codes
6434
6435extern const char wuffs_bmp__error__bad_header[];
6436extern const char wuffs_bmp__error__bad_rle_compression[];
6437extern const char wuffs_bmp__error__unsupported_bmp_file[];
6438
6439// ---------------- Public Consts
6440
6441#define WUFFS_BMP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
6442
6443// ---------------- Struct Declarations
6444
6445typedef struct wuffs_bmp__decoder__struct wuffs_bmp__decoder;
6446
6447#ifdef __cplusplus
6448extern "C" {
6449#endif
6450
6451// ---------------- Public Initializer Prototypes
6452
6453// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
6454// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
6455//
6456// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
6457// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
6458
6459wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6460wuffs_bmp__decoder__initialize(
6461 wuffs_bmp__decoder* self,
6462 size_t sizeof_star_self,
6463 uint64_t wuffs_version,
6464 uint32_t options);
6465
6466size_t
6467sizeof__wuffs_bmp__decoder();
6468
6469// ---------------- Allocs
6470
6471// These functions allocate and initialize Wuffs structs. They return NULL if
6472// memory allocation fails. If they return non-NULL, there is no need to call
6473// wuffs_foo__bar__initialize, but the caller is responsible for eventually
6474// calling free on the returned pointer. That pointer is effectively a C++
6475// std::unique_ptr<T, decltype(&free)>.
6476
6477wuffs_bmp__decoder*
6478wuffs_bmp__decoder__alloc();
6479
6480static inline wuffs_base__image_decoder*
6481wuffs_bmp__decoder__alloc_as__wuffs_base__image_decoder() {
6482 return (wuffs_base__image_decoder*)(wuffs_bmp__decoder__alloc());
6483}
6484
6485// ---------------- Upcasts
6486
6487static inline wuffs_base__image_decoder*
6488wuffs_bmp__decoder__upcast_as__wuffs_base__image_decoder(
6489 wuffs_bmp__decoder* p) {
6490 return (wuffs_base__image_decoder*)p;
6491}
6492
6493// ---------------- Public Function Prototypes
6494
6495WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6496wuffs_bmp__decoder__set_quirk_enabled(
6497 wuffs_bmp__decoder* self,
6498 uint32_t a_quirk,
6499 bool a_enabled);
6500
6501WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6502wuffs_bmp__decoder__decode_image_config(
6503 wuffs_bmp__decoder* self,
6504 wuffs_base__image_config* a_dst,
6505 wuffs_base__io_buffer* a_src);
6506
6507WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6508wuffs_bmp__decoder__decode_frame_config(
6509 wuffs_bmp__decoder* self,
6510 wuffs_base__frame_config* a_dst,
6511 wuffs_base__io_buffer* a_src);
6512
6513WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6514wuffs_bmp__decoder__decode_frame(
6515 wuffs_bmp__decoder* self,
6516 wuffs_base__pixel_buffer* a_dst,
6517 wuffs_base__io_buffer* a_src,
6518 wuffs_base__pixel_blend a_blend,
6519 wuffs_base__slice_u8 a_workbuf,
6520 wuffs_base__decode_frame_options* a_opts);
6521
6522WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
6523wuffs_bmp__decoder__frame_dirty_rect(
6524 const wuffs_bmp__decoder* self);
6525
6526WUFFS_BASE__MAYBE_STATIC uint32_t
6527wuffs_bmp__decoder__num_animation_loops(
6528 const wuffs_bmp__decoder* self);
6529
6530WUFFS_BASE__MAYBE_STATIC uint64_t
6531wuffs_bmp__decoder__num_decoded_frame_configs(
6532 const wuffs_bmp__decoder* self);
6533
6534WUFFS_BASE__MAYBE_STATIC uint64_t
6535wuffs_bmp__decoder__num_decoded_frames(
6536 const wuffs_bmp__decoder* self);
6537
6538WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6539wuffs_bmp__decoder__restart_frame(
6540 wuffs_bmp__decoder* self,
6541 uint64_t a_index,
6542 uint64_t a_io_position);
6543
6544WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6545wuffs_bmp__decoder__set_report_metadata(
6546 wuffs_bmp__decoder* self,
6547 uint32_t a_fourcc,
6548 bool a_report);
6549
6550WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6551wuffs_bmp__decoder__tell_me_more(
6552 wuffs_bmp__decoder* self,
6553 wuffs_base__io_buffer* a_dst,
6554 wuffs_base__more_information* a_minfo,
6555 wuffs_base__io_buffer* a_src);
6556
6557WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6558wuffs_bmp__decoder__workbuf_len(
6559 const wuffs_bmp__decoder* self);
6560
6561#ifdef __cplusplus
6562} // extern "C"
6563#endif
6564
6565// ---------------- Struct Definitions
6566
6567// These structs' fields, and the sizeof them, are private implementation
6568// details that aren't guaranteed to be stable across Wuffs versions.
6569//
6570// See https://en.wikipedia.org/wiki/Opaque_pointer#C
6571
6572#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6573
6574struct wuffs_bmp__decoder__struct {
6575 // Do not access the private_impl's or private_data's fields directly. There
6576 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
6577 // the wuffs_foo__bar__baz functions.
6578 //
6579 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
6580 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
6581
6582 struct {
6583 uint32_t magic;
6584 uint32_t active_coroutine;
6585 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
6586 wuffs_base__vtable null_vtable;
6587
6588 uint32_t f_width;
6589 uint32_t f_height;
6590 uint8_t f_call_sequence;
6591 bool f_top_down;
6592 uint32_t f_pad_per_row;
6593 uint32_t f_src_pixfmt;
6594 uint32_t f_io_redirect_fourcc;
6595 uint64_t f_io_redirect_pos;
6596 uint64_t f_frame_config_io_position;
6597 uint32_t f_bitmap_info_len;
6598 uint32_t f_padding;
6599 uint32_t f_bits_per_pixel;
6600 uint32_t f_compression;
6601 uint32_t f_channel_masks[4];
6602 uint8_t f_channel_shifts[4];
6603 uint8_t f_channel_num_bits[4];
6604 uint32_t f_dst_x;
6605 uint32_t f_dst_y;
6606 uint32_t f_dst_y_inc;
6607 uint32_t f_pending_pad;
6608 uint32_t f_rle_state;
6609 uint32_t f_rle_length;
6610 uint8_t f_rle_delta_x;
6611 bool f_rle_padded;
6612 wuffs_base__pixel_swizzler f_swizzler;
6613
6614 uint32_t p_decode_image_config[1];
6615 uint32_t p_decode_frame_config[1];
6616 uint32_t p_decode_frame[1];
6617 uint32_t p_read_palette[1];
6618 } private_impl;
6619
6620 struct {
6621 uint8_t f_scratch[2048];
6622 uint8_t f_src_palette[1024];
6623
6624 struct {
6625 uint64_t scratch;
6626 } s_decode_image_config[1];
6627 struct {
6628 wuffs_base__status v_status;
6629 uint64_t scratch;
6630 } s_decode_frame[1];
6631 struct {
6632 uint32_t v_i;
6633 uint64_t scratch;
6634 } s_read_palette[1];
6635 } private_data;
6636
6637#ifdef __cplusplus
6638#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6639 using unique_ptr = std::unique_ptr<wuffs_bmp__decoder, decltype(&free)>;
6640
6641 // On failure, the alloc_etc functions return nullptr. They don't throw.
6642
6643 static inline unique_ptr
6644 alloc() {
6645 return unique_ptr(wuffs_bmp__decoder__alloc(), &free);
6646 }
6647
6648 static inline wuffs_base__image_decoder::unique_ptr
6649 alloc_as__wuffs_base__image_decoder() {
6650 return wuffs_base__image_decoder::unique_ptr(
6651 wuffs_bmp__decoder__alloc_as__wuffs_base__image_decoder(), &free);
6652 }
6653#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6654
6655#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6656 // Disallow constructing or copying an object via standard C++ mechanisms,
6657 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
6658 // size and field layout is not part of the public, stable, memory-safe API.
6659 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
6660 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
6661 // their first argument) rather than tweaking bar.private_impl.qux fields.
6662 //
6663 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
6664 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
6665 // order to provide convenience methods. These forward on "this", so that you
6666 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
6667 wuffs_bmp__decoder__struct() = delete;
6668 wuffs_bmp__decoder__struct(const wuffs_bmp__decoder__struct&) = delete;
6669 wuffs_bmp__decoder__struct& operator=(
6670 const wuffs_bmp__decoder__struct&) = delete;
6671#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6672
6673#if !defined(WUFFS_IMPLEMENTATION)
6674 // As above, the size of the struct is not part of the public API, and unless
6675 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
6676 // allocated, not stack allocated. Its size is not intended to be known at
6677 // compile time, but it is unfortunately divulged as a side effect of
6678 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
6679 // instead of "sizeof T", invoking the operator. To make the two values
6680 // different, so that passing the latter will be rejected by the initialize
6681 // function, we add an arbitrary amount of dead weight.
6682 uint8_t dead_weight[123000000]; // 123 MB.
6683#endif // !defined(WUFFS_IMPLEMENTATION)
6684
6685 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6686 initialize(
6687 size_t sizeof_star_self,
6688 uint64_t wuffs_version,
6689 uint32_t options) {
6690 return wuffs_bmp__decoder__initialize(
6691 this, sizeof_star_self, wuffs_version, options);
6692 }
6693
6694 inline wuffs_base__image_decoder*
6695 upcast_as__wuffs_base__image_decoder() {
6696 return (wuffs_base__image_decoder*)this;
6697 }
6698
6699 inline wuffs_base__empty_struct
6700 set_quirk_enabled(
6701 uint32_t a_quirk,
6702 bool a_enabled) {
6703 return wuffs_bmp__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
6704 }
6705
6706 inline wuffs_base__status
6707 decode_image_config(
6708 wuffs_base__image_config* a_dst,
6709 wuffs_base__io_buffer* a_src) {
6710 return wuffs_bmp__decoder__decode_image_config(this, a_dst, a_src);
6711 }
6712
6713 inline wuffs_base__status
6714 decode_frame_config(
6715 wuffs_base__frame_config* a_dst,
6716 wuffs_base__io_buffer* a_src) {
6717 return wuffs_bmp__decoder__decode_frame_config(this, a_dst, a_src);
6718 }
6719
6720 inline wuffs_base__status
6721 decode_frame(
6722 wuffs_base__pixel_buffer* a_dst,
6723 wuffs_base__io_buffer* a_src,
6724 wuffs_base__pixel_blend a_blend,
6725 wuffs_base__slice_u8 a_workbuf,
6726 wuffs_base__decode_frame_options* a_opts) {
6727 return wuffs_bmp__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
6728 }
6729
6730 inline wuffs_base__rect_ie_u32
6731 frame_dirty_rect() const {
6732 return wuffs_bmp__decoder__frame_dirty_rect(this);
6733 }
6734
6735 inline uint32_t
6736 num_animation_loops() const {
6737 return wuffs_bmp__decoder__num_animation_loops(this);
6738 }
6739
6740 inline uint64_t
6741 num_decoded_frame_configs() const {
6742 return wuffs_bmp__decoder__num_decoded_frame_configs(this);
6743 }
6744
6745 inline uint64_t
6746 num_decoded_frames() const {
6747 return wuffs_bmp__decoder__num_decoded_frames(this);
6748 }
6749
6750 inline wuffs_base__status
6751 restart_frame(
6752 uint64_t a_index,
6753 uint64_t a_io_position) {
6754 return wuffs_bmp__decoder__restart_frame(this, a_index, a_io_position);
6755 }
6756
6757 inline wuffs_base__empty_struct
6758 set_report_metadata(
6759 uint32_t a_fourcc,
6760 bool a_report) {
6761 return wuffs_bmp__decoder__set_report_metadata(this, a_fourcc, a_report);
6762 }
6763
6764 inline wuffs_base__status
6765 tell_me_more(
6766 wuffs_base__io_buffer* a_dst,
6767 wuffs_base__more_information* a_minfo,
6768 wuffs_base__io_buffer* a_src) {
6769 return wuffs_bmp__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
6770 }
6771
6772 inline wuffs_base__range_ii_u64
6773 workbuf_len() const {
6774 return wuffs_bmp__decoder__workbuf_len(this);
6775 }
6776
6777#endif // __cplusplus
6778}; // struct wuffs_bmp__decoder__struct
6779
6780#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6781
6782// ---------------- Status Codes
6783
6784extern const char wuffs_cbor__error__bad_input[];
6785extern const char wuffs_cbor__error__unsupported_recursion_depth[];
6786
6787// ---------------- Public Consts
6788
6789#define WUFFS_CBOR__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
6790
6791#define WUFFS_CBOR__DECODER_DEPTH_MAX_INCL 1024
6792
6793#define WUFFS_CBOR__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 2
6794
6795#define WUFFS_CBOR__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 9
6796
6797#define WUFFS_CBOR__TOKEN_VALUE_MAJOR 787997
6798
6799#define WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK 262143
6800
6801#define WUFFS_CBOR__TOKEN_VALUE_MINOR__MINUS_1_MINUS_X 16777216
6802
6803#define WUFFS_CBOR__TOKEN_VALUE_MINOR__SIMPLE_VALUE 8388608
6804
6805#define WUFFS_CBOR__TOKEN_VALUE_MINOR__TAG 4194304
6806
6807// ---------------- Struct Declarations
6808
6809typedef struct wuffs_cbor__decoder__struct wuffs_cbor__decoder;
6810
6811#ifdef __cplusplus
6812extern "C" {
6813#endif
6814
6815// ---------------- Public Initializer Prototypes
6816
6817// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
6818// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
6819//
6820// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
6821// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
6822
6823wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6824wuffs_cbor__decoder__initialize(
6825 wuffs_cbor__decoder* self,
6826 size_t sizeof_star_self,
6827 uint64_t wuffs_version,
6828 uint32_t options);
6829
6830size_t
6831sizeof__wuffs_cbor__decoder();
6832
6833// ---------------- Allocs
6834
6835// These functions allocate and initialize Wuffs structs. They return NULL if
6836// memory allocation fails. If they return non-NULL, there is no need to call
6837// wuffs_foo__bar__initialize, but the caller is responsible for eventually
6838// calling free on the returned pointer. That pointer is effectively a C++
6839// std::unique_ptr<T, decltype(&free)>.
6840
6841wuffs_cbor__decoder*
6842wuffs_cbor__decoder__alloc();
6843
6844static inline wuffs_base__token_decoder*
6845wuffs_cbor__decoder__alloc_as__wuffs_base__token_decoder() {
6846 return (wuffs_base__token_decoder*)(wuffs_cbor__decoder__alloc());
6847}
6848
6849// ---------------- Upcasts
6850
6851static inline wuffs_base__token_decoder*
6852wuffs_cbor__decoder__upcast_as__wuffs_base__token_decoder(
6853 wuffs_cbor__decoder* p) {
6854 return (wuffs_base__token_decoder*)p;
6855}
6856
6857// ---------------- Public Function Prototypes
6858
6859WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6860wuffs_cbor__decoder__set_quirk_enabled(
6861 wuffs_cbor__decoder* self,
6862 uint32_t a_quirk,
6863 bool a_enabled);
6864
6865WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6866wuffs_cbor__decoder__workbuf_len(
6867 const wuffs_cbor__decoder* self);
6868
6869WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6870wuffs_cbor__decoder__decode_tokens(
6871 wuffs_cbor__decoder* self,
6872 wuffs_base__token_buffer* a_dst,
6873 wuffs_base__io_buffer* a_src,
6874 wuffs_base__slice_u8 a_workbuf);
6875
6876#ifdef __cplusplus
6877} // extern "C"
6878#endif
6879
6880// ---------------- Struct Definitions
6881
6882// These structs' fields, and the sizeof them, are private implementation
6883// details that aren't guaranteed to be stable across Wuffs versions.
6884//
6885// See https://en.wikipedia.org/wiki/Opaque_pointer#C
6886
6887#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6888
6889struct wuffs_cbor__decoder__struct {
6890 // Do not access the private_impl's or private_data's fields directly. There
6891 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
6892 // the wuffs_foo__bar__baz functions.
6893 //
6894 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
6895 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
6896
6897 struct {
6898 uint32_t magic;
6899 uint32_t active_coroutine;
6900 wuffs_base__vtable vtable_for__wuffs_base__token_decoder;
6901 wuffs_base__vtable null_vtable;
6902
6903 bool f_end_of_data;
6904
6905 uint32_t p_decode_tokens[1];
6906 } private_impl;
6907
6908 struct {
6909 uint32_t f_stack[64];
6910 uint64_t f_container_num_remaining[1024];
6911
6912 struct {
6913 uint64_t v_string_length;
6914 uint32_t v_depth;
6915 uint32_t v_token_length;
6916 bool v_tagged;
6917 uint8_t v_indefinite_string_major_type;
6918 } s_decode_tokens[1];
6919 } private_data;
6920
6921#ifdef __cplusplus
6922#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6923 using unique_ptr = std::unique_ptr<wuffs_cbor__decoder, decltype(&free)>;
6924
6925 // On failure, the alloc_etc functions return nullptr. They don't throw.
6926
6927 static inline unique_ptr
6928 alloc() {
6929 return unique_ptr(wuffs_cbor__decoder__alloc(), &free);
6930 }
6931
6932 static inline wuffs_base__token_decoder::unique_ptr
6933 alloc_as__wuffs_base__token_decoder() {
6934 return wuffs_base__token_decoder::unique_ptr(
6935 wuffs_cbor__decoder__alloc_as__wuffs_base__token_decoder(), &free);
6936 }
6937#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6938
6939#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6940 // Disallow constructing or copying an object via standard C++ mechanisms,
6941 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
6942 // size and field layout is not part of the public, stable, memory-safe API.
6943 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
6944 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
6945 // their first argument) rather than tweaking bar.private_impl.qux fields.
6946 //
6947 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
6948 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
6949 // order to provide convenience methods. These forward on "this", so that you
6950 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
6951 wuffs_cbor__decoder__struct() = delete;
6952 wuffs_cbor__decoder__struct(const wuffs_cbor__decoder__struct&) = delete;
6953 wuffs_cbor__decoder__struct& operator=(
6954 const wuffs_cbor__decoder__struct&) = delete;
6955#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6956
6957#if !defined(WUFFS_IMPLEMENTATION)
6958 // As above, the size of the struct is not part of the public API, and unless
6959 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
6960 // allocated, not stack allocated. Its size is not intended to be known at
6961 // compile time, but it is unfortunately divulged as a side effect of
6962 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
6963 // instead of "sizeof T", invoking the operator. To make the two values
6964 // different, so that passing the latter will be rejected by the initialize
6965 // function, we add an arbitrary amount of dead weight.
6966 uint8_t dead_weight[123000000]; // 123 MB.
6967#endif // !defined(WUFFS_IMPLEMENTATION)
6968
6969 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6970 initialize(
6971 size_t sizeof_star_self,
6972 uint64_t wuffs_version,
6973 uint32_t options) {
6974 return wuffs_cbor__decoder__initialize(
6975 this, sizeof_star_self, wuffs_version, options);
6976 }
6977
6978 inline wuffs_base__token_decoder*
6979 upcast_as__wuffs_base__token_decoder() {
6980 return (wuffs_base__token_decoder*)this;
6981 }
6982
6983 inline wuffs_base__empty_struct
6984 set_quirk_enabled(
6985 uint32_t a_quirk,
6986 bool a_enabled) {
6987 return wuffs_cbor__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
6988 }
6989
6990 inline wuffs_base__range_ii_u64
6991 workbuf_len() const {
6992 return wuffs_cbor__decoder__workbuf_len(this);
6993 }
6994
6995 inline wuffs_base__status
6996 decode_tokens(
6997 wuffs_base__token_buffer* a_dst,
6998 wuffs_base__io_buffer* a_src,
6999 wuffs_base__slice_u8 a_workbuf) {
7000 return wuffs_cbor__decoder__decode_tokens(this, a_dst, a_src, a_workbuf);
7001 }
7002
7003#endif // __cplusplus
7004}; // struct wuffs_cbor__decoder__struct
7005
7006#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7007
7008// ---------------- Status Codes
7009
7010// ---------------- Public Consts
7011
7012// ---------------- Struct Declarations
7013
7014typedef struct wuffs_crc32__ieee_hasher__struct wuffs_crc32__ieee_hasher;
7015
7016#ifdef __cplusplus
7017extern "C" {
7018#endif
7019
7020// ---------------- Public Initializer Prototypes
7021
7022// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
7023// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
7024//
7025// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
7026// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
7027
7028wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7029wuffs_crc32__ieee_hasher__initialize(
7030 wuffs_crc32__ieee_hasher* self,
7031 size_t sizeof_star_self,
7032 uint64_t wuffs_version,
7033 uint32_t options);
7034
7035size_t
7036sizeof__wuffs_crc32__ieee_hasher();
7037
7038// ---------------- Allocs
7039
7040// These functions allocate and initialize Wuffs structs. They return NULL if
7041// memory allocation fails. If they return non-NULL, there is no need to call
7042// wuffs_foo__bar__initialize, but the caller is responsible for eventually
7043// calling free on the returned pointer. That pointer is effectively a C++
7044// std::unique_ptr<T, decltype(&free)>.
7045
7046wuffs_crc32__ieee_hasher*
7047wuffs_crc32__ieee_hasher__alloc();
7048
7049static inline wuffs_base__hasher_u32*
7050wuffs_crc32__ieee_hasher__alloc_as__wuffs_base__hasher_u32() {
7051 return (wuffs_base__hasher_u32*)(wuffs_crc32__ieee_hasher__alloc());
7052}
7053
7054// ---------------- Upcasts
7055
7056static inline wuffs_base__hasher_u32*
7057wuffs_crc32__ieee_hasher__upcast_as__wuffs_base__hasher_u32(
7058 wuffs_crc32__ieee_hasher* p) {
7059 return (wuffs_base__hasher_u32*)p;
7060}
7061
7062// ---------------- Public Function Prototypes
7063
7064WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7065wuffs_crc32__ieee_hasher__set_quirk_enabled(
7066 wuffs_crc32__ieee_hasher* self,
7067 uint32_t a_quirk,
7068 bool a_enabled);
7069
7070WUFFS_BASE__MAYBE_STATIC uint32_t
7071wuffs_crc32__ieee_hasher__update_u32(
7072 wuffs_crc32__ieee_hasher* self,
7073 wuffs_base__slice_u8 a_x);
7074
7075#ifdef __cplusplus
7076} // extern "C"
7077#endif
7078
7079// ---------------- Struct Definitions
7080
7081// These structs' fields, and the sizeof them, are private implementation
7082// details that aren't guaranteed to be stable across Wuffs versions.
7083//
7084// See https://en.wikipedia.org/wiki/Opaque_pointer#C
7085
7086#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7087
7088struct wuffs_crc32__ieee_hasher__struct {
7089 // Do not access the private_impl's or private_data's fields directly. There
7090 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
7091 // the wuffs_foo__bar__baz functions.
7092 //
7093 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
7094 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
7095
7096 struct {
7097 uint32_t magic;
7098 uint32_t active_coroutine;
7099 wuffs_base__vtable vtable_for__wuffs_base__hasher_u32;
7100 wuffs_base__vtable null_vtable;
7101
7102 uint32_t f_state;
7103
7104 wuffs_base__empty_struct (*choosy_up)(
7105 wuffs_crc32__ieee_hasher* self,
7106 wuffs_base__slice_u8 a_x);
7107 } private_impl;
7108
7109#ifdef __cplusplus
7110#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7111 using unique_ptr = std::unique_ptr<wuffs_crc32__ieee_hasher, decltype(&free)>;
7112
7113 // On failure, the alloc_etc functions return nullptr. They don't throw.
7114
7115 static inline unique_ptr
7116 alloc() {
7117 return unique_ptr(wuffs_crc32__ieee_hasher__alloc(), &free);
7118 }
7119
7120 static inline wuffs_base__hasher_u32::unique_ptr
7121 alloc_as__wuffs_base__hasher_u32() {
7122 return wuffs_base__hasher_u32::unique_ptr(
7123 wuffs_crc32__ieee_hasher__alloc_as__wuffs_base__hasher_u32(), &free);
7124 }
7125#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7126
7127#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7128 // Disallow constructing or copying an object via standard C++ mechanisms,
7129 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
7130 // size and field layout is not part of the public, stable, memory-safe API.
7131 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
7132 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
7133 // their first argument) rather than tweaking bar.private_impl.qux fields.
7134 //
7135 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
7136 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
7137 // order to provide convenience methods. These forward on "this", so that you
7138 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
7139 wuffs_crc32__ieee_hasher__struct() = delete;
7140 wuffs_crc32__ieee_hasher__struct(const wuffs_crc32__ieee_hasher__struct&) = delete;
7141 wuffs_crc32__ieee_hasher__struct& operator=(
7142 const wuffs_crc32__ieee_hasher__struct&) = delete;
7143#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7144
7145#if !defined(WUFFS_IMPLEMENTATION)
7146 // As above, the size of the struct is not part of the public API, and unless
7147 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
7148 // allocated, not stack allocated. Its size is not intended to be known at
7149 // compile time, but it is unfortunately divulged as a side effect of
7150 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
7151 // instead of "sizeof T", invoking the operator. To make the two values
7152 // different, so that passing the latter will be rejected by the initialize
7153 // function, we add an arbitrary amount of dead weight.
7154 uint8_t dead_weight[123000000]; // 123 MB.
7155#endif // !defined(WUFFS_IMPLEMENTATION)
7156
7157 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7158 initialize(
7159 size_t sizeof_star_self,
7160 uint64_t wuffs_version,
7161 uint32_t options) {
7162 return wuffs_crc32__ieee_hasher__initialize(
7163 this, sizeof_star_self, wuffs_version, options);
7164 }
7165
7166 inline wuffs_base__hasher_u32*
7167 upcast_as__wuffs_base__hasher_u32() {
7168 return (wuffs_base__hasher_u32*)this;
7169 }
7170
7171 inline wuffs_base__empty_struct
7172 set_quirk_enabled(
7173 uint32_t a_quirk,
7174 bool a_enabled) {
7175 return wuffs_crc32__ieee_hasher__set_quirk_enabled(this, a_quirk, a_enabled);
7176 }
7177
7178 inline uint32_t
7179 update_u32(
7180 wuffs_base__slice_u8 a_x) {
7181 return wuffs_crc32__ieee_hasher__update_u32(this, a_x);
7182 }
7183
7184#endif // __cplusplus
7185}; // struct wuffs_crc32__ieee_hasher__struct
7186
7187#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7188
7189// ---------------- Status Codes
7190
7191extern const char wuffs_deflate__error__bad_huffman_code_over_subscribed[];
7192extern const char wuffs_deflate__error__bad_huffman_code_under_subscribed[];
7193extern const char wuffs_deflate__error__bad_huffman_code_length_count[];
7194extern const char wuffs_deflate__error__bad_huffman_code_length_repetition[];
7195extern const char wuffs_deflate__error__bad_huffman_code[];
7196extern const char wuffs_deflate__error__bad_huffman_minimum_code_length[];
7197extern const char wuffs_deflate__error__bad_block[];
7198extern const char wuffs_deflate__error__bad_distance[];
7199extern const char wuffs_deflate__error__bad_distance_code_count[];
7200extern const char wuffs_deflate__error__bad_literal_length_code_count[];
7201extern const char wuffs_deflate__error__inconsistent_stored_block_length[];
7202extern const char wuffs_deflate__error__missing_end_of_block_code[];
7203extern const char wuffs_deflate__error__no_huffman_codes[];
7204
7205// ---------------- Public Consts
7206
7207#define WUFFS_DEFLATE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1
7208
7209// ---------------- Struct Declarations
7210
7211typedef struct wuffs_deflate__decoder__struct wuffs_deflate__decoder;
7212
7213#ifdef __cplusplus
7214extern "C" {
7215#endif
7216
7217// ---------------- Public Initializer Prototypes
7218
7219// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
7220// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
7221//
7222// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
7223// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
7224
7225wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7226wuffs_deflate__decoder__initialize(
7227 wuffs_deflate__decoder* self,
7228 size_t sizeof_star_self,
7229 uint64_t wuffs_version,
7230 uint32_t options);
7231
7232size_t
7233sizeof__wuffs_deflate__decoder();
7234
7235// ---------------- Allocs
7236
7237// These functions allocate and initialize Wuffs structs. They return NULL if
7238// memory allocation fails. If they return non-NULL, there is no need to call
7239// wuffs_foo__bar__initialize, but the caller is responsible for eventually
7240// calling free on the returned pointer. That pointer is effectively a C++
7241// std::unique_ptr<T, decltype(&free)>.
7242
7243wuffs_deflate__decoder*
7244wuffs_deflate__decoder__alloc();
7245
7246static inline wuffs_base__io_transformer*
7247wuffs_deflate__decoder__alloc_as__wuffs_base__io_transformer() {
7248 return (wuffs_base__io_transformer*)(wuffs_deflate__decoder__alloc());
7249}
7250
7251// ---------------- Upcasts
7252
7253static inline wuffs_base__io_transformer*
7254wuffs_deflate__decoder__upcast_as__wuffs_base__io_transformer(
7255 wuffs_deflate__decoder* p) {
7256 return (wuffs_base__io_transformer*)p;
7257}
7258
7259// ---------------- Public Function Prototypes
7260
7261WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7262wuffs_deflate__decoder__add_history(
7263 wuffs_deflate__decoder* self,
7264 wuffs_base__slice_u8 a_hist);
7265
7266WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7267wuffs_deflate__decoder__set_quirk_enabled(
7268 wuffs_deflate__decoder* self,
7269 uint32_t a_quirk,
7270 bool a_enabled);
7271
7272WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
7273wuffs_deflate__decoder__workbuf_len(
7274 const wuffs_deflate__decoder* self);
7275
7276WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7277wuffs_deflate__decoder__transform_io(
7278 wuffs_deflate__decoder* self,
7279 wuffs_base__io_buffer* a_dst,
7280 wuffs_base__io_buffer* a_src,
7281 wuffs_base__slice_u8 a_workbuf);
7282
7283#ifdef __cplusplus
7284} // extern "C"
7285#endif
7286
7287// ---------------- Struct Definitions
7288
7289// These structs' fields, and the sizeof them, are private implementation
7290// details that aren't guaranteed to be stable across Wuffs versions.
7291//
7292// See https://en.wikipedia.org/wiki/Opaque_pointer#C
7293
7294#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7295
7296struct wuffs_deflate__decoder__struct {
7297 // Do not access the private_impl's or private_data's fields directly. There
7298 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
7299 // the wuffs_foo__bar__baz functions.
7300 //
7301 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
7302 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
7303
7304 struct {
7305 uint32_t magic;
7306 uint32_t active_coroutine;
7307 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
7308 wuffs_base__vtable null_vtable;
7309
7310 uint32_t f_bits;
7311 uint32_t f_n_bits;
Nigel Taoc9d2ed72021-08-15 13:50:22 +10007312 uint64_t f_transformed_history_count;
Nigel Taoe360a532021-04-05 22:47:03 +10007313 uint32_t f_history_index;
7314 uint32_t f_n_huffs_bits[2];
7315 bool f_end_of_block;
7316
7317 uint32_t p_transform_io[1];
7318 uint32_t p_decode_blocks[1];
7319 uint32_t p_decode_uncompressed[1];
7320 uint32_t p_init_dynamic_huffman[1];
Nigel Tao5571bfe2021-06-24 22:44:29 +10007321 wuffs_base__status (*choosy_decode_huffman_fast64)(
7322 wuffs_deflate__decoder* self,
7323 wuffs_base__io_buffer* a_dst,
7324 wuffs_base__io_buffer* a_src);
Nigel Taoe360a532021-04-05 22:47:03 +10007325 uint32_t p_decode_huffman_slow[1];
7326 } private_impl;
7327
7328 struct {
7329 uint32_t f_huffs[2][1024];
7330 uint8_t f_history[33025];
7331 uint8_t f_code_lengths[320];
7332
7333 struct {
7334 uint32_t v_final;
7335 } s_decode_blocks[1];
7336 struct {
7337 uint32_t v_length;
7338 uint64_t scratch;
7339 } s_decode_uncompressed[1];
7340 struct {
7341 uint32_t v_bits;
7342 uint32_t v_n_bits;
7343 uint32_t v_n_lit;
7344 uint32_t v_n_dist;
7345 uint32_t v_n_clen;
7346 uint32_t v_i;
7347 uint32_t v_mask;
7348 uint32_t v_table_entry;
7349 uint32_t v_n_extra_bits;
7350 uint8_t v_rep_symbol;
7351 uint32_t v_rep_count;
7352 } s_init_dynamic_huffman[1];
7353 struct {
7354 uint32_t v_bits;
7355 uint32_t v_n_bits;
7356 uint32_t v_table_entry;
7357 uint32_t v_table_entry_n_bits;
7358 uint32_t v_lmask;
7359 uint32_t v_dmask;
7360 uint32_t v_redir_top;
7361 uint32_t v_redir_mask;
7362 uint32_t v_length;
7363 uint32_t v_dist_minus_1;
7364 uint32_t v_hlen;
7365 uint32_t v_hdist;
7366 uint64_t scratch;
7367 } s_decode_huffman_slow[1];
7368 } private_data;
7369
7370#ifdef __cplusplus
7371#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7372 using unique_ptr = std::unique_ptr<wuffs_deflate__decoder, decltype(&free)>;
7373
7374 // On failure, the alloc_etc functions return nullptr. They don't throw.
7375
7376 static inline unique_ptr
7377 alloc() {
7378 return unique_ptr(wuffs_deflate__decoder__alloc(), &free);
7379 }
7380
7381 static inline wuffs_base__io_transformer::unique_ptr
7382 alloc_as__wuffs_base__io_transformer() {
7383 return wuffs_base__io_transformer::unique_ptr(
7384 wuffs_deflate__decoder__alloc_as__wuffs_base__io_transformer(), &free);
7385 }
7386#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7387
7388#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7389 // Disallow constructing or copying an object via standard C++ mechanisms,
7390 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
7391 // size and field layout is not part of the public, stable, memory-safe API.
7392 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
7393 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
7394 // their first argument) rather than tweaking bar.private_impl.qux fields.
7395 //
7396 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
7397 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
7398 // order to provide convenience methods. These forward on "this", so that you
7399 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
7400 wuffs_deflate__decoder__struct() = delete;
7401 wuffs_deflate__decoder__struct(const wuffs_deflate__decoder__struct&) = delete;
7402 wuffs_deflate__decoder__struct& operator=(
7403 const wuffs_deflate__decoder__struct&) = delete;
7404#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7405
7406#if !defined(WUFFS_IMPLEMENTATION)
7407 // As above, the size of the struct is not part of the public API, and unless
7408 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
7409 // allocated, not stack allocated. Its size is not intended to be known at
7410 // compile time, but it is unfortunately divulged as a side effect of
7411 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
7412 // instead of "sizeof T", invoking the operator. To make the two values
7413 // different, so that passing the latter will be rejected by the initialize
7414 // function, we add an arbitrary amount of dead weight.
7415 uint8_t dead_weight[123000000]; // 123 MB.
7416#endif // !defined(WUFFS_IMPLEMENTATION)
7417
7418 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7419 initialize(
7420 size_t sizeof_star_self,
7421 uint64_t wuffs_version,
7422 uint32_t options) {
7423 return wuffs_deflate__decoder__initialize(
7424 this, sizeof_star_self, wuffs_version, options);
7425 }
7426
7427 inline wuffs_base__io_transformer*
7428 upcast_as__wuffs_base__io_transformer() {
7429 return (wuffs_base__io_transformer*)this;
7430 }
7431
7432 inline wuffs_base__empty_struct
7433 add_history(
7434 wuffs_base__slice_u8 a_hist) {
7435 return wuffs_deflate__decoder__add_history(this, a_hist);
7436 }
7437
7438 inline wuffs_base__empty_struct
7439 set_quirk_enabled(
7440 uint32_t a_quirk,
7441 bool a_enabled) {
7442 return wuffs_deflate__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
7443 }
7444
7445 inline wuffs_base__range_ii_u64
7446 workbuf_len() const {
7447 return wuffs_deflate__decoder__workbuf_len(this);
7448 }
7449
7450 inline wuffs_base__status
7451 transform_io(
7452 wuffs_base__io_buffer* a_dst,
7453 wuffs_base__io_buffer* a_src,
7454 wuffs_base__slice_u8 a_workbuf) {
7455 return wuffs_deflate__decoder__transform_io(this, a_dst, a_src, a_workbuf);
7456 }
7457
7458#endif // __cplusplus
7459}; // struct wuffs_deflate__decoder__struct
7460
7461#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7462
7463// ---------------- Status Codes
7464
7465extern const char wuffs_lzw__error__bad_code[];
7466
7467// ---------------- Public Consts
7468
7469#define WUFFS_LZW__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
7470
7471// ---------------- Struct Declarations
7472
7473typedef struct wuffs_lzw__decoder__struct wuffs_lzw__decoder;
7474
7475#ifdef __cplusplus
7476extern "C" {
7477#endif
7478
7479// ---------------- Public Initializer Prototypes
7480
7481// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
7482// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
7483//
7484// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
7485// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
7486
7487wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7488wuffs_lzw__decoder__initialize(
7489 wuffs_lzw__decoder* self,
7490 size_t sizeof_star_self,
7491 uint64_t wuffs_version,
7492 uint32_t options);
7493
7494size_t
7495sizeof__wuffs_lzw__decoder();
7496
7497// ---------------- Allocs
7498
7499// These functions allocate and initialize Wuffs structs. They return NULL if
7500// memory allocation fails. If they return non-NULL, there is no need to call
7501// wuffs_foo__bar__initialize, but the caller is responsible for eventually
7502// calling free on the returned pointer. That pointer is effectively a C++
7503// std::unique_ptr<T, decltype(&free)>.
7504
7505wuffs_lzw__decoder*
7506wuffs_lzw__decoder__alloc();
7507
7508static inline wuffs_base__io_transformer*
7509wuffs_lzw__decoder__alloc_as__wuffs_base__io_transformer() {
7510 return (wuffs_base__io_transformer*)(wuffs_lzw__decoder__alloc());
7511}
7512
7513// ---------------- Upcasts
7514
7515static inline wuffs_base__io_transformer*
7516wuffs_lzw__decoder__upcast_as__wuffs_base__io_transformer(
7517 wuffs_lzw__decoder* p) {
7518 return (wuffs_base__io_transformer*)p;
7519}
7520
7521// ---------------- Public Function Prototypes
7522
7523WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7524wuffs_lzw__decoder__set_quirk_enabled(
7525 wuffs_lzw__decoder* self,
7526 uint32_t a_quirk,
7527 bool a_enabled);
7528
7529WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7530wuffs_lzw__decoder__set_literal_width(
7531 wuffs_lzw__decoder* self,
7532 uint32_t a_lw);
7533
7534WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
7535wuffs_lzw__decoder__workbuf_len(
7536 const wuffs_lzw__decoder* self);
7537
7538WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7539wuffs_lzw__decoder__transform_io(
7540 wuffs_lzw__decoder* self,
7541 wuffs_base__io_buffer* a_dst,
7542 wuffs_base__io_buffer* a_src,
7543 wuffs_base__slice_u8 a_workbuf);
7544
7545WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8
7546wuffs_lzw__decoder__flush(
7547 wuffs_lzw__decoder* self);
7548
7549#ifdef __cplusplus
7550} // extern "C"
7551#endif
7552
7553// ---------------- Struct Definitions
7554
7555// These structs' fields, and the sizeof them, are private implementation
7556// details that aren't guaranteed to be stable across Wuffs versions.
7557//
7558// See https://en.wikipedia.org/wiki/Opaque_pointer#C
7559
7560#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7561
7562struct wuffs_lzw__decoder__struct {
7563 // Do not access the private_impl's or private_data's fields directly. There
7564 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
7565 // the wuffs_foo__bar__baz functions.
7566 //
7567 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
7568 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
7569
7570 struct {
7571 uint32_t magic;
7572 uint32_t active_coroutine;
7573 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
7574 wuffs_base__vtable null_vtable;
7575
7576 uint32_t f_set_literal_width_arg;
7577 uint32_t f_literal_width;
7578 uint32_t f_clear_code;
7579 uint32_t f_end_code;
7580 uint32_t f_save_code;
7581 uint32_t f_prev_code;
7582 uint32_t f_width;
7583 uint32_t f_bits;
7584 uint32_t f_n_bits;
7585 uint32_t f_output_ri;
7586 uint32_t f_output_wi;
7587 uint32_t f_read_from_return_value;
7588 uint16_t f_prefixes[4096];
7589
7590 uint32_t p_transform_io[1];
7591 uint32_t p_write_to[1];
7592 } private_impl;
7593
7594 struct {
7595 uint8_t f_suffixes[4096][8];
7596 uint16_t f_lm1s[4096];
7597 uint8_t f_output[8199];
7598 } private_data;
7599
7600#ifdef __cplusplus
7601#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7602 using unique_ptr = std::unique_ptr<wuffs_lzw__decoder, decltype(&free)>;
7603
7604 // On failure, the alloc_etc functions return nullptr. They don't throw.
7605
7606 static inline unique_ptr
7607 alloc() {
7608 return unique_ptr(wuffs_lzw__decoder__alloc(), &free);
7609 }
7610
7611 static inline wuffs_base__io_transformer::unique_ptr
7612 alloc_as__wuffs_base__io_transformer() {
7613 return wuffs_base__io_transformer::unique_ptr(
7614 wuffs_lzw__decoder__alloc_as__wuffs_base__io_transformer(), &free);
7615 }
7616#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7617
7618#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7619 // Disallow constructing or copying an object via standard C++ mechanisms,
7620 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
7621 // size and field layout is not part of the public, stable, memory-safe API.
7622 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
7623 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
7624 // their first argument) rather than tweaking bar.private_impl.qux fields.
7625 //
7626 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
7627 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
7628 // order to provide convenience methods. These forward on "this", so that you
7629 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
7630 wuffs_lzw__decoder__struct() = delete;
7631 wuffs_lzw__decoder__struct(const wuffs_lzw__decoder__struct&) = delete;
7632 wuffs_lzw__decoder__struct& operator=(
7633 const wuffs_lzw__decoder__struct&) = delete;
7634#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7635
7636#if !defined(WUFFS_IMPLEMENTATION)
7637 // As above, the size of the struct is not part of the public API, and unless
7638 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
7639 // allocated, not stack allocated. Its size is not intended to be known at
7640 // compile time, but it is unfortunately divulged as a side effect of
7641 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
7642 // instead of "sizeof T", invoking the operator. To make the two values
7643 // different, so that passing the latter will be rejected by the initialize
7644 // function, we add an arbitrary amount of dead weight.
7645 uint8_t dead_weight[123000000]; // 123 MB.
7646#endif // !defined(WUFFS_IMPLEMENTATION)
7647
7648 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7649 initialize(
7650 size_t sizeof_star_self,
7651 uint64_t wuffs_version,
7652 uint32_t options) {
7653 return wuffs_lzw__decoder__initialize(
7654 this, sizeof_star_self, wuffs_version, options);
7655 }
7656
7657 inline wuffs_base__io_transformer*
7658 upcast_as__wuffs_base__io_transformer() {
7659 return (wuffs_base__io_transformer*)this;
7660 }
7661
7662 inline wuffs_base__empty_struct
7663 set_quirk_enabled(
7664 uint32_t a_quirk,
7665 bool a_enabled) {
7666 return wuffs_lzw__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
7667 }
7668
7669 inline wuffs_base__empty_struct
7670 set_literal_width(
7671 uint32_t a_lw) {
7672 return wuffs_lzw__decoder__set_literal_width(this, a_lw);
7673 }
7674
7675 inline wuffs_base__range_ii_u64
7676 workbuf_len() const {
7677 return wuffs_lzw__decoder__workbuf_len(this);
7678 }
7679
7680 inline wuffs_base__status
7681 transform_io(
7682 wuffs_base__io_buffer* a_dst,
7683 wuffs_base__io_buffer* a_src,
7684 wuffs_base__slice_u8 a_workbuf) {
7685 return wuffs_lzw__decoder__transform_io(this, a_dst, a_src, a_workbuf);
7686 }
7687
7688 inline wuffs_base__slice_u8
7689 flush() {
7690 return wuffs_lzw__decoder__flush(this);
7691 }
7692
7693#endif // __cplusplus
7694}; // struct wuffs_lzw__decoder__struct
7695
7696#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7697
7698// ---------------- Status Codes
7699
7700extern const char wuffs_gif__error__bad_extension_label[];
7701extern const char wuffs_gif__error__bad_frame_size[];
7702extern const char wuffs_gif__error__bad_graphic_control[];
7703extern const char wuffs_gif__error__bad_header[];
7704extern const char wuffs_gif__error__bad_literal_width[];
7705extern const char wuffs_gif__error__bad_palette[];
7706
7707// ---------------- Public Consts
7708
7709#define WUFFS_GIF__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
7710
7711#define WUFFS_GIF__QUIRK_DELAY_NUM_DECODED_FRAMES 1041635328
7712
7713#define WUFFS_GIF__QUIRK_FIRST_FRAME_LOCAL_PALETTE_MEANS_BLACK_BACKGROUND 1041635329
7714
7715#define WUFFS_GIF__QUIRK_HONOR_BACKGROUND_COLOR 1041635330
7716
7717#define WUFFS_GIF__QUIRK_IGNORE_TOO_MUCH_PIXEL_DATA 1041635331
7718
7719#define WUFFS_GIF__QUIRK_IMAGE_BOUNDS_ARE_STRICT 1041635332
7720
7721#define WUFFS_GIF__QUIRK_REJECT_EMPTY_FRAME 1041635333
7722
7723#define WUFFS_GIF__QUIRK_REJECT_EMPTY_PALETTE 1041635334
7724
7725// ---------------- Struct Declarations
7726
7727typedef struct wuffs_gif__decoder__struct wuffs_gif__decoder;
7728
7729#ifdef __cplusplus
7730extern "C" {
7731#endif
7732
7733// ---------------- Public Initializer Prototypes
7734
7735// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
7736// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
7737//
7738// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
7739// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
7740
7741wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7742wuffs_gif__decoder__initialize(
7743 wuffs_gif__decoder* self,
7744 size_t sizeof_star_self,
7745 uint64_t wuffs_version,
7746 uint32_t options);
7747
7748size_t
7749sizeof__wuffs_gif__decoder();
7750
7751// ---------------- Allocs
7752
7753// These functions allocate and initialize Wuffs structs. They return NULL if
7754// memory allocation fails. If they return non-NULL, there is no need to call
7755// wuffs_foo__bar__initialize, but the caller is responsible for eventually
7756// calling free on the returned pointer. That pointer is effectively a C++
7757// std::unique_ptr<T, decltype(&free)>.
7758
7759wuffs_gif__decoder*
7760wuffs_gif__decoder__alloc();
7761
7762static inline wuffs_base__image_decoder*
7763wuffs_gif__decoder__alloc_as__wuffs_base__image_decoder() {
7764 return (wuffs_base__image_decoder*)(wuffs_gif__decoder__alloc());
7765}
7766
7767// ---------------- Upcasts
7768
7769static inline wuffs_base__image_decoder*
7770wuffs_gif__decoder__upcast_as__wuffs_base__image_decoder(
7771 wuffs_gif__decoder* p) {
7772 return (wuffs_base__image_decoder*)p;
7773}
7774
7775// ---------------- Public Function Prototypes
7776
7777WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7778wuffs_gif__decoder__set_quirk_enabled(
7779 wuffs_gif__decoder* self,
7780 uint32_t a_quirk,
7781 bool a_enabled);
7782
7783WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7784wuffs_gif__decoder__decode_image_config(
7785 wuffs_gif__decoder* self,
7786 wuffs_base__image_config* a_dst,
7787 wuffs_base__io_buffer* a_src);
7788
7789WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7790wuffs_gif__decoder__set_report_metadata(
7791 wuffs_gif__decoder* self,
7792 uint32_t a_fourcc,
7793 bool a_report);
7794
7795WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7796wuffs_gif__decoder__tell_me_more(
7797 wuffs_gif__decoder* self,
7798 wuffs_base__io_buffer* a_dst,
7799 wuffs_base__more_information* a_minfo,
7800 wuffs_base__io_buffer* a_src);
7801
7802WUFFS_BASE__MAYBE_STATIC uint32_t
7803wuffs_gif__decoder__num_animation_loops(
7804 const wuffs_gif__decoder* self);
7805
7806WUFFS_BASE__MAYBE_STATIC uint64_t
7807wuffs_gif__decoder__num_decoded_frame_configs(
7808 const wuffs_gif__decoder* self);
7809
7810WUFFS_BASE__MAYBE_STATIC uint64_t
7811wuffs_gif__decoder__num_decoded_frames(
7812 const wuffs_gif__decoder* self);
7813
7814WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
7815wuffs_gif__decoder__frame_dirty_rect(
7816 const wuffs_gif__decoder* self);
7817
7818WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
7819wuffs_gif__decoder__workbuf_len(
7820 const wuffs_gif__decoder* self);
7821
7822WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7823wuffs_gif__decoder__restart_frame(
7824 wuffs_gif__decoder* self,
7825 uint64_t a_index,
7826 uint64_t a_io_position);
7827
7828WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7829wuffs_gif__decoder__decode_frame_config(
7830 wuffs_gif__decoder* self,
7831 wuffs_base__frame_config* a_dst,
7832 wuffs_base__io_buffer* a_src);
7833
7834WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7835wuffs_gif__decoder__decode_frame(
7836 wuffs_gif__decoder* self,
7837 wuffs_base__pixel_buffer* a_dst,
7838 wuffs_base__io_buffer* a_src,
7839 wuffs_base__pixel_blend a_blend,
7840 wuffs_base__slice_u8 a_workbuf,
7841 wuffs_base__decode_frame_options* a_opts);
7842
7843#ifdef __cplusplus
7844} // extern "C"
7845#endif
7846
7847// ---------------- Struct Definitions
7848
7849// These structs' fields, and the sizeof them, are private implementation
7850// details that aren't guaranteed to be stable across Wuffs versions.
7851//
7852// See https://en.wikipedia.org/wiki/Opaque_pointer#C
7853
7854#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7855
7856struct wuffs_gif__decoder__struct {
7857 // Do not access the private_impl's or private_data's fields directly. There
7858 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
7859 // the wuffs_foo__bar__baz functions.
7860 //
7861 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
7862 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
7863
7864 struct {
7865 uint32_t magic;
7866 uint32_t active_coroutine;
7867 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
7868 wuffs_base__vtable null_vtable;
7869
7870 uint32_t f_width;
7871 uint32_t f_height;
7872 uint8_t f_call_sequence;
7873 bool f_ignore_metadata;
7874 bool f_report_metadata_iccp;
7875 bool f_report_metadata_xmp;
7876 uint32_t f_metadata_fourcc;
7877 uint64_t f_metadata_io_position;
7878 bool f_quirks[7];
7879 bool f_delayed_num_decoded_frames;
7880 bool f_end_of_data;
7881 bool f_restarted;
7882 bool f_previous_lzw_decode_ended_abruptly;
7883 bool f_has_global_palette;
7884 uint8_t f_interlace;
Nigel Taobf9dab32021-11-18 19:19:55 +11007885 bool f_seen_num_animation_loops_value;
7886 uint32_t f_num_animation_loops_value;
Nigel Taoe360a532021-04-05 22:47:03 +10007887 uint32_t f_background_color_u32_argb_premul;
7888 uint32_t f_black_color_u32_argb_premul;
7889 bool f_gc_has_transparent_index;
7890 uint8_t f_gc_transparent_index;
7891 uint8_t f_gc_disposal;
7892 uint64_t f_gc_duration;
7893 uint64_t f_frame_config_io_position;
7894 uint64_t f_num_decoded_frame_configs_value;
7895 uint64_t f_num_decoded_frames_value;
7896 uint32_t f_frame_rect_x0;
7897 uint32_t f_frame_rect_y0;
7898 uint32_t f_frame_rect_x1;
7899 uint32_t f_frame_rect_y1;
7900 uint32_t f_dst_x;
7901 uint32_t f_dst_y;
7902 uint32_t f_dirty_max_excl_y;
7903 uint64_t f_compressed_ri;
7904 uint64_t f_compressed_wi;
7905 wuffs_base__pixel_swizzler f_swizzler;
7906
7907 uint32_t p_decode_image_config[1];
7908 uint32_t p_tell_me_more[1];
7909 uint32_t p_decode_frame_config[1];
7910 uint32_t p_skip_frame[1];
7911 uint32_t p_decode_frame[1];
7912 uint32_t p_decode_up_to_id_part1[1];
7913 uint32_t p_decode_header[1];
7914 uint32_t p_decode_lsd[1];
7915 uint32_t p_decode_extension[1];
7916 uint32_t p_skip_blocks[1];
7917 uint32_t p_decode_ae[1];
7918 uint32_t p_decode_gc[1];
7919 uint32_t p_decode_id_part0[1];
7920 uint32_t p_decode_id_part1[1];
7921 uint32_t p_decode_id_part2[1];
7922 } private_impl;
7923
7924 struct {
7925 uint8_t f_compressed[4096];
7926 uint8_t f_palettes[2][1024];
7927 uint8_t f_dst_palette[1024];
7928 wuffs_lzw__decoder f_lzw;
7929
7930 struct {
7931 uint32_t v_background_color;
7932 } s_decode_frame_config[1];
7933 struct {
7934 uint64_t scratch;
7935 } s_skip_frame[1];
7936 struct {
7937 uint8_t v_c[6];
7938 uint32_t v_i;
7939 } s_decode_header[1];
7940 struct {
7941 uint8_t v_flags;
7942 uint8_t v_background_color_index;
7943 uint32_t v_num_palette_entries;
7944 uint32_t v_i;
7945 uint64_t scratch;
7946 } s_decode_lsd[1];
7947 struct {
7948 uint64_t scratch;
7949 } s_skip_blocks[1];
7950 struct {
7951 uint8_t v_block_size;
7952 bool v_is_animexts;
7953 bool v_is_netscape;
7954 bool v_is_iccp;
7955 bool v_is_xmp;
7956 uint64_t scratch;
7957 } s_decode_ae[1];
7958 struct {
7959 uint64_t scratch;
7960 } s_decode_gc[1];
7961 struct {
7962 uint64_t scratch;
7963 } s_decode_id_part0[1];
7964 struct {
7965 uint8_t v_which_palette;
7966 uint32_t v_num_palette_entries;
7967 uint32_t v_i;
7968 uint64_t scratch;
7969 } s_decode_id_part1[1];
7970 struct {
7971 uint64_t v_block_size;
7972 bool v_need_block_size;
7973 wuffs_base__status v_lzw_status;
7974 uint64_t scratch;
7975 } s_decode_id_part2[1];
7976 } private_data;
7977
7978#ifdef __cplusplus
7979#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7980 using unique_ptr = std::unique_ptr<wuffs_gif__decoder, decltype(&free)>;
7981
7982 // On failure, the alloc_etc functions return nullptr. They don't throw.
7983
7984 static inline unique_ptr
7985 alloc() {
7986 return unique_ptr(wuffs_gif__decoder__alloc(), &free);
7987 }
7988
7989 static inline wuffs_base__image_decoder::unique_ptr
7990 alloc_as__wuffs_base__image_decoder() {
7991 return wuffs_base__image_decoder::unique_ptr(
7992 wuffs_gif__decoder__alloc_as__wuffs_base__image_decoder(), &free);
7993 }
7994#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7995
7996#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7997 // Disallow constructing or copying an object via standard C++ mechanisms,
7998 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
7999 // size and field layout is not part of the public, stable, memory-safe API.
8000 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
8001 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
8002 // their first argument) rather than tweaking bar.private_impl.qux fields.
8003 //
8004 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
8005 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
8006 // order to provide convenience methods. These forward on "this", so that you
8007 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
8008 wuffs_gif__decoder__struct() = delete;
8009 wuffs_gif__decoder__struct(const wuffs_gif__decoder__struct&) = delete;
8010 wuffs_gif__decoder__struct& operator=(
8011 const wuffs_gif__decoder__struct&) = delete;
8012#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8013
8014#if !defined(WUFFS_IMPLEMENTATION)
8015 // As above, the size of the struct is not part of the public API, and unless
8016 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
8017 // allocated, not stack allocated. Its size is not intended to be known at
8018 // compile time, but it is unfortunately divulged as a side effect of
8019 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
8020 // instead of "sizeof T", invoking the operator. To make the two values
8021 // different, so that passing the latter will be rejected by the initialize
8022 // function, we add an arbitrary amount of dead weight.
8023 uint8_t dead_weight[123000000]; // 123 MB.
8024#endif // !defined(WUFFS_IMPLEMENTATION)
8025
8026 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8027 initialize(
8028 size_t sizeof_star_self,
8029 uint64_t wuffs_version,
8030 uint32_t options) {
8031 return wuffs_gif__decoder__initialize(
8032 this, sizeof_star_self, wuffs_version, options);
8033 }
8034
8035 inline wuffs_base__image_decoder*
8036 upcast_as__wuffs_base__image_decoder() {
8037 return (wuffs_base__image_decoder*)this;
8038 }
8039
8040 inline wuffs_base__empty_struct
8041 set_quirk_enabled(
8042 uint32_t a_quirk,
8043 bool a_enabled) {
8044 return wuffs_gif__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
8045 }
8046
8047 inline wuffs_base__status
8048 decode_image_config(
8049 wuffs_base__image_config* a_dst,
8050 wuffs_base__io_buffer* a_src) {
8051 return wuffs_gif__decoder__decode_image_config(this, a_dst, a_src);
8052 }
8053
8054 inline wuffs_base__empty_struct
8055 set_report_metadata(
8056 uint32_t a_fourcc,
8057 bool a_report) {
8058 return wuffs_gif__decoder__set_report_metadata(this, a_fourcc, a_report);
8059 }
8060
8061 inline wuffs_base__status
8062 tell_me_more(
8063 wuffs_base__io_buffer* a_dst,
8064 wuffs_base__more_information* a_minfo,
8065 wuffs_base__io_buffer* a_src) {
8066 return wuffs_gif__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
8067 }
8068
8069 inline uint32_t
8070 num_animation_loops() const {
8071 return wuffs_gif__decoder__num_animation_loops(this);
8072 }
8073
8074 inline uint64_t
8075 num_decoded_frame_configs() const {
8076 return wuffs_gif__decoder__num_decoded_frame_configs(this);
8077 }
8078
8079 inline uint64_t
8080 num_decoded_frames() const {
8081 return wuffs_gif__decoder__num_decoded_frames(this);
8082 }
8083
8084 inline wuffs_base__rect_ie_u32
8085 frame_dirty_rect() const {
8086 return wuffs_gif__decoder__frame_dirty_rect(this);
8087 }
8088
8089 inline wuffs_base__range_ii_u64
8090 workbuf_len() const {
8091 return wuffs_gif__decoder__workbuf_len(this);
8092 }
8093
8094 inline wuffs_base__status
8095 restart_frame(
8096 uint64_t a_index,
8097 uint64_t a_io_position) {
8098 return wuffs_gif__decoder__restart_frame(this, a_index, a_io_position);
8099 }
8100
8101 inline wuffs_base__status
8102 decode_frame_config(
8103 wuffs_base__frame_config* a_dst,
8104 wuffs_base__io_buffer* a_src) {
8105 return wuffs_gif__decoder__decode_frame_config(this, a_dst, a_src);
8106 }
8107
8108 inline wuffs_base__status
8109 decode_frame(
8110 wuffs_base__pixel_buffer* a_dst,
8111 wuffs_base__io_buffer* a_src,
8112 wuffs_base__pixel_blend a_blend,
8113 wuffs_base__slice_u8 a_workbuf,
8114 wuffs_base__decode_frame_options* a_opts) {
8115 return wuffs_gif__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
8116 }
8117
8118#endif // __cplusplus
8119}; // struct wuffs_gif__decoder__struct
8120
8121#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8122
8123// ---------------- Status Codes
8124
8125extern const char wuffs_gzip__error__bad_checksum[];
8126extern const char wuffs_gzip__error__bad_compression_method[];
8127extern const char wuffs_gzip__error__bad_encoding_flags[];
8128extern const char wuffs_gzip__error__bad_header[];
8129
8130// ---------------- Public Consts
8131
8132#define WUFFS_GZIP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1
8133
8134// ---------------- Struct Declarations
8135
8136typedef struct wuffs_gzip__decoder__struct wuffs_gzip__decoder;
8137
8138#ifdef __cplusplus
8139extern "C" {
8140#endif
8141
8142// ---------------- Public Initializer Prototypes
8143
8144// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
8145// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
8146//
8147// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
8148// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
8149
8150wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8151wuffs_gzip__decoder__initialize(
8152 wuffs_gzip__decoder* self,
8153 size_t sizeof_star_self,
8154 uint64_t wuffs_version,
8155 uint32_t options);
8156
8157size_t
8158sizeof__wuffs_gzip__decoder();
8159
8160// ---------------- Allocs
8161
8162// These functions allocate and initialize Wuffs structs. They return NULL if
8163// memory allocation fails. If they return non-NULL, there is no need to call
8164// wuffs_foo__bar__initialize, but the caller is responsible for eventually
8165// calling free on the returned pointer. That pointer is effectively a C++
8166// std::unique_ptr<T, decltype(&free)>.
8167
8168wuffs_gzip__decoder*
8169wuffs_gzip__decoder__alloc();
8170
8171static inline wuffs_base__io_transformer*
8172wuffs_gzip__decoder__alloc_as__wuffs_base__io_transformer() {
8173 return (wuffs_base__io_transformer*)(wuffs_gzip__decoder__alloc());
8174}
8175
8176// ---------------- Upcasts
8177
8178static inline wuffs_base__io_transformer*
8179wuffs_gzip__decoder__upcast_as__wuffs_base__io_transformer(
8180 wuffs_gzip__decoder* p) {
8181 return (wuffs_base__io_transformer*)p;
8182}
8183
8184// ---------------- Public Function Prototypes
8185
8186WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8187wuffs_gzip__decoder__set_quirk_enabled(
8188 wuffs_gzip__decoder* self,
8189 uint32_t a_quirk,
8190 bool a_enabled);
8191
8192WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
8193wuffs_gzip__decoder__workbuf_len(
8194 const wuffs_gzip__decoder* self);
8195
8196WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8197wuffs_gzip__decoder__transform_io(
8198 wuffs_gzip__decoder* self,
8199 wuffs_base__io_buffer* a_dst,
8200 wuffs_base__io_buffer* a_src,
8201 wuffs_base__slice_u8 a_workbuf);
8202
8203#ifdef __cplusplus
8204} // extern "C"
8205#endif
8206
8207// ---------------- Struct Definitions
8208
8209// These structs' fields, and the sizeof them, are private implementation
8210// details that aren't guaranteed to be stable across Wuffs versions.
8211//
8212// See https://en.wikipedia.org/wiki/Opaque_pointer#C
8213
8214#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8215
8216struct wuffs_gzip__decoder__struct {
8217 // Do not access the private_impl's or private_data's fields directly. There
8218 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
8219 // the wuffs_foo__bar__baz functions.
8220 //
8221 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
8222 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
8223
8224 struct {
8225 uint32_t magic;
8226 uint32_t active_coroutine;
8227 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
8228 wuffs_base__vtable null_vtable;
8229
8230 bool f_ignore_checksum;
8231
8232 uint32_t p_transform_io[1];
8233 } private_impl;
8234
8235 struct {
8236 wuffs_crc32__ieee_hasher f_checksum;
8237 wuffs_deflate__decoder f_flate;
8238
8239 struct {
8240 uint8_t v_flags;
8241 uint32_t v_checksum_got;
8242 uint32_t v_decoded_length_got;
8243 uint32_t v_checksum_want;
8244 uint64_t scratch;
8245 } s_transform_io[1];
8246 } private_data;
8247
8248#ifdef __cplusplus
8249#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8250 using unique_ptr = std::unique_ptr<wuffs_gzip__decoder, decltype(&free)>;
8251
8252 // On failure, the alloc_etc functions return nullptr. They don't throw.
8253
8254 static inline unique_ptr
8255 alloc() {
8256 return unique_ptr(wuffs_gzip__decoder__alloc(), &free);
8257 }
8258
8259 static inline wuffs_base__io_transformer::unique_ptr
8260 alloc_as__wuffs_base__io_transformer() {
8261 return wuffs_base__io_transformer::unique_ptr(
8262 wuffs_gzip__decoder__alloc_as__wuffs_base__io_transformer(), &free);
8263 }
8264#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8265
8266#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8267 // Disallow constructing or copying an object via standard C++ mechanisms,
8268 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
8269 // size and field layout is not part of the public, stable, memory-safe API.
8270 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
8271 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
8272 // their first argument) rather than tweaking bar.private_impl.qux fields.
8273 //
8274 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
8275 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
8276 // order to provide convenience methods. These forward on "this", so that you
8277 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
8278 wuffs_gzip__decoder__struct() = delete;
8279 wuffs_gzip__decoder__struct(const wuffs_gzip__decoder__struct&) = delete;
8280 wuffs_gzip__decoder__struct& operator=(
8281 const wuffs_gzip__decoder__struct&) = delete;
8282#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8283
8284#if !defined(WUFFS_IMPLEMENTATION)
8285 // As above, the size of the struct is not part of the public API, and unless
8286 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
8287 // allocated, not stack allocated. Its size is not intended to be known at
8288 // compile time, but it is unfortunately divulged as a side effect of
8289 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
8290 // instead of "sizeof T", invoking the operator. To make the two values
8291 // different, so that passing the latter will be rejected by the initialize
8292 // function, we add an arbitrary amount of dead weight.
8293 uint8_t dead_weight[123000000]; // 123 MB.
8294#endif // !defined(WUFFS_IMPLEMENTATION)
8295
8296 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8297 initialize(
8298 size_t sizeof_star_self,
8299 uint64_t wuffs_version,
8300 uint32_t options) {
8301 return wuffs_gzip__decoder__initialize(
8302 this, sizeof_star_self, wuffs_version, options);
8303 }
8304
8305 inline wuffs_base__io_transformer*
8306 upcast_as__wuffs_base__io_transformer() {
8307 return (wuffs_base__io_transformer*)this;
8308 }
8309
8310 inline wuffs_base__empty_struct
8311 set_quirk_enabled(
8312 uint32_t a_quirk,
8313 bool a_enabled) {
8314 return wuffs_gzip__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
8315 }
8316
8317 inline wuffs_base__range_ii_u64
8318 workbuf_len() const {
8319 return wuffs_gzip__decoder__workbuf_len(this);
8320 }
8321
8322 inline wuffs_base__status
8323 transform_io(
8324 wuffs_base__io_buffer* a_dst,
8325 wuffs_base__io_buffer* a_src,
8326 wuffs_base__slice_u8 a_workbuf) {
8327 return wuffs_gzip__decoder__transform_io(this, a_dst, a_src, a_workbuf);
8328 }
8329
8330#endif // __cplusplus
8331}; // struct wuffs_gzip__decoder__struct
8332
8333#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8334
8335// ---------------- Status Codes
8336
8337extern const char wuffs_json__error__bad_c0_control_code[];
8338extern const char wuffs_json__error__bad_utf_8[];
8339extern const char wuffs_json__error__bad_backslash_escape[];
8340extern const char wuffs_json__error__bad_input[];
8341extern const char wuffs_json__error__bad_new_line_in_a_string[];
8342extern const char wuffs_json__error__bad_quirk_combination[];
8343extern const char wuffs_json__error__unsupported_number_length[];
8344extern const char wuffs_json__error__unsupported_recursion_depth[];
8345
8346// ---------------- Public Consts
8347
8348#define WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
8349
8350#define WUFFS_JSON__DECODER_DEPTH_MAX_INCL 1024
8351
8352#define WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 1
8353
8354#define WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 100
8355
8356#define WUFFS_JSON__QUIRK_ALLOW_ASCII_CONTROL_CODES 1225364480
8357
8358#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A 1225364481
8359
8360#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U 1225364482
8361
8362#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_E 1225364483
8363
8364#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_NEW_LINE 1225364484
8365
8366#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_QUESTION_MARK 1225364485
8367
8368#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_SINGLE_QUOTE 1225364486
8369
8370#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V 1225364487
8371
8372#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X_AS_CODE_POINTS 1225364489
8373
8374#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO 1225364490
8375
8376#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK 1225364491
8377
8378#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE 1225364492
8379
8380#define WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA 1225364493
8381
8382#define WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS 1225364494
8383
8384#define WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR 1225364495
8385
8386#define WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK 1225364496
8387
8388#define WUFFS_JSON__QUIRK_ALLOW_TRAILING_FILLER 1225364497
8389
8390#define WUFFS_JSON__QUIRK_EXPECT_TRAILING_NEW_LINE_OR_EOF 1225364498
8391
8392#define WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_N_TILDE_R_TILDE_T 1225364499
8393
8394#define WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE 1225364500
8395
8396// ---------------- Struct Declarations
8397
8398typedef struct wuffs_json__decoder__struct wuffs_json__decoder;
8399
8400#ifdef __cplusplus
8401extern "C" {
8402#endif
8403
8404// ---------------- Public Initializer Prototypes
8405
8406// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
8407// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
8408//
8409// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
8410// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
8411
8412wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8413wuffs_json__decoder__initialize(
8414 wuffs_json__decoder* self,
8415 size_t sizeof_star_self,
8416 uint64_t wuffs_version,
8417 uint32_t options);
8418
8419size_t
8420sizeof__wuffs_json__decoder();
8421
8422// ---------------- Allocs
8423
8424// These functions allocate and initialize Wuffs structs. They return NULL if
8425// memory allocation fails. If they return non-NULL, there is no need to call
8426// wuffs_foo__bar__initialize, but the caller is responsible for eventually
8427// calling free on the returned pointer. That pointer is effectively a C++
8428// std::unique_ptr<T, decltype(&free)>.
8429
8430wuffs_json__decoder*
8431wuffs_json__decoder__alloc();
8432
8433static inline wuffs_base__token_decoder*
8434wuffs_json__decoder__alloc_as__wuffs_base__token_decoder() {
8435 return (wuffs_base__token_decoder*)(wuffs_json__decoder__alloc());
8436}
8437
8438// ---------------- Upcasts
8439
8440static inline wuffs_base__token_decoder*
8441wuffs_json__decoder__upcast_as__wuffs_base__token_decoder(
8442 wuffs_json__decoder* p) {
8443 return (wuffs_base__token_decoder*)p;
8444}
8445
8446// ---------------- Public Function Prototypes
8447
8448WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8449wuffs_json__decoder__set_quirk_enabled(
8450 wuffs_json__decoder* self,
8451 uint32_t a_quirk,
8452 bool a_enabled);
8453
8454WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
8455wuffs_json__decoder__workbuf_len(
8456 const wuffs_json__decoder* self);
8457
8458WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8459wuffs_json__decoder__decode_tokens(
8460 wuffs_json__decoder* self,
8461 wuffs_base__token_buffer* a_dst,
8462 wuffs_base__io_buffer* a_src,
8463 wuffs_base__slice_u8 a_workbuf);
8464
8465#ifdef __cplusplus
8466} // extern "C"
8467#endif
8468
8469// ---------------- Struct Definitions
8470
8471// These structs' fields, and the sizeof them, are private implementation
8472// details that aren't guaranteed to be stable across Wuffs versions.
8473//
8474// See https://en.wikipedia.org/wiki/Opaque_pointer#C
8475
8476#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8477
8478struct wuffs_json__decoder__struct {
8479 // Do not access the private_impl's or private_data's fields directly. There
8480 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
8481 // the wuffs_foo__bar__baz functions.
8482 //
8483 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
8484 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
8485
8486 struct {
8487 uint32_t magic;
8488 uint32_t active_coroutine;
8489 wuffs_base__vtable vtable_for__wuffs_base__token_decoder;
8490 wuffs_base__vtable null_vtable;
8491
8492 bool f_quirks[21];
8493 bool f_allow_leading_ars;
8494 bool f_allow_leading_ubom;
8495 bool f_end_of_data;
8496 uint8_t f_trailer_stop;
8497 uint8_t f_comment_type;
8498
8499 uint32_t p_decode_tokens[1];
8500 uint32_t p_decode_leading[1];
8501 uint32_t p_decode_comment[1];
8502 uint32_t p_decode_inf_nan[1];
8503 uint32_t p_decode_trailer[1];
8504 } private_impl;
8505
8506 struct {
8507 uint32_t f_stack[32];
8508
8509 struct {
8510 uint32_t v_depth;
8511 uint32_t v_expect;
8512 uint32_t v_expect_after_value;
8513 } s_decode_tokens[1];
8514 struct {
8515 uint32_t v_neg;
8516 } s_decode_inf_nan[1];
8517 } private_data;
8518
8519#ifdef __cplusplus
8520#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8521 using unique_ptr = std::unique_ptr<wuffs_json__decoder, decltype(&free)>;
8522
8523 // On failure, the alloc_etc functions return nullptr. They don't throw.
8524
8525 static inline unique_ptr
8526 alloc() {
8527 return unique_ptr(wuffs_json__decoder__alloc(), &free);
8528 }
8529
8530 static inline wuffs_base__token_decoder::unique_ptr
8531 alloc_as__wuffs_base__token_decoder() {
8532 return wuffs_base__token_decoder::unique_ptr(
8533 wuffs_json__decoder__alloc_as__wuffs_base__token_decoder(), &free);
8534 }
8535#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8536
8537#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8538 // Disallow constructing or copying an object via standard C++ mechanisms,
8539 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
8540 // size and field layout is not part of the public, stable, memory-safe API.
8541 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
8542 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
8543 // their first argument) rather than tweaking bar.private_impl.qux fields.
8544 //
8545 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
8546 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
8547 // order to provide convenience methods. These forward on "this", so that you
8548 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
8549 wuffs_json__decoder__struct() = delete;
8550 wuffs_json__decoder__struct(const wuffs_json__decoder__struct&) = delete;
8551 wuffs_json__decoder__struct& operator=(
8552 const wuffs_json__decoder__struct&) = delete;
8553#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8554
8555#if !defined(WUFFS_IMPLEMENTATION)
8556 // As above, the size of the struct is not part of the public API, and unless
8557 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
8558 // allocated, not stack allocated. Its size is not intended to be known at
8559 // compile time, but it is unfortunately divulged as a side effect of
8560 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
8561 // instead of "sizeof T", invoking the operator. To make the two values
8562 // different, so that passing the latter will be rejected by the initialize
8563 // function, we add an arbitrary amount of dead weight.
8564 uint8_t dead_weight[123000000]; // 123 MB.
8565#endif // !defined(WUFFS_IMPLEMENTATION)
8566
8567 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8568 initialize(
8569 size_t sizeof_star_self,
8570 uint64_t wuffs_version,
8571 uint32_t options) {
8572 return wuffs_json__decoder__initialize(
8573 this, sizeof_star_self, wuffs_version, options);
8574 }
8575
8576 inline wuffs_base__token_decoder*
8577 upcast_as__wuffs_base__token_decoder() {
8578 return (wuffs_base__token_decoder*)this;
8579 }
8580
8581 inline wuffs_base__empty_struct
8582 set_quirk_enabled(
8583 uint32_t a_quirk,
8584 bool a_enabled) {
8585 return wuffs_json__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
8586 }
8587
8588 inline wuffs_base__range_ii_u64
8589 workbuf_len() const {
8590 return wuffs_json__decoder__workbuf_len(this);
8591 }
8592
8593 inline wuffs_base__status
8594 decode_tokens(
8595 wuffs_base__token_buffer* a_dst,
8596 wuffs_base__io_buffer* a_src,
8597 wuffs_base__slice_u8 a_workbuf) {
8598 return wuffs_json__decoder__decode_tokens(this, a_dst, a_src, a_workbuf);
8599 }
8600
8601#endif // __cplusplus
8602}; // struct wuffs_json__decoder__struct
8603
8604#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8605
8606// ---------------- Status Codes
8607
8608extern const char wuffs_nie__error__bad_header[];
8609extern const char wuffs_nie__error__unsupported_nie_file[];
8610
8611// ---------------- Public Consts
8612
8613#define WUFFS_NIE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
8614
8615// ---------------- Struct Declarations
8616
8617typedef struct wuffs_nie__decoder__struct wuffs_nie__decoder;
8618
8619#ifdef __cplusplus
8620extern "C" {
8621#endif
8622
8623// ---------------- Public Initializer Prototypes
8624
8625// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
8626// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
8627//
8628// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
8629// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
8630
8631wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8632wuffs_nie__decoder__initialize(
8633 wuffs_nie__decoder* self,
8634 size_t sizeof_star_self,
8635 uint64_t wuffs_version,
8636 uint32_t options);
8637
8638size_t
8639sizeof__wuffs_nie__decoder();
8640
8641// ---------------- Allocs
8642
8643// These functions allocate and initialize Wuffs structs. They return NULL if
8644// memory allocation fails. If they return non-NULL, there is no need to call
8645// wuffs_foo__bar__initialize, but the caller is responsible for eventually
8646// calling free on the returned pointer. That pointer is effectively a C++
8647// std::unique_ptr<T, decltype(&free)>.
8648
8649wuffs_nie__decoder*
8650wuffs_nie__decoder__alloc();
8651
8652static inline wuffs_base__image_decoder*
8653wuffs_nie__decoder__alloc_as__wuffs_base__image_decoder() {
8654 return (wuffs_base__image_decoder*)(wuffs_nie__decoder__alloc());
8655}
8656
8657// ---------------- Upcasts
8658
8659static inline wuffs_base__image_decoder*
8660wuffs_nie__decoder__upcast_as__wuffs_base__image_decoder(
8661 wuffs_nie__decoder* p) {
8662 return (wuffs_base__image_decoder*)p;
8663}
8664
8665// ---------------- Public Function Prototypes
8666
8667WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8668wuffs_nie__decoder__set_quirk_enabled(
8669 wuffs_nie__decoder* self,
8670 uint32_t a_quirk,
8671 bool a_enabled);
8672
8673WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8674wuffs_nie__decoder__decode_image_config(
8675 wuffs_nie__decoder* self,
8676 wuffs_base__image_config* a_dst,
8677 wuffs_base__io_buffer* a_src);
8678
8679WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8680wuffs_nie__decoder__decode_frame_config(
8681 wuffs_nie__decoder* self,
8682 wuffs_base__frame_config* a_dst,
8683 wuffs_base__io_buffer* a_src);
8684
8685WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8686wuffs_nie__decoder__decode_frame(
8687 wuffs_nie__decoder* self,
8688 wuffs_base__pixel_buffer* a_dst,
8689 wuffs_base__io_buffer* a_src,
8690 wuffs_base__pixel_blend a_blend,
8691 wuffs_base__slice_u8 a_workbuf,
8692 wuffs_base__decode_frame_options* a_opts);
8693
8694WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
8695wuffs_nie__decoder__frame_dirty_rect(
8696 const wuffs_nie__decoder* self);
8697
8698WUFFS_BASE__MAYBE_STATIC uint32_t
8699wuffs_nie__decoder__num_animation_loops(
8700 const wuffs_nie__decoder* self);
8701
8702WUFFS_BASE__MAYBE_STATIC uint64_t
8703wuffs_nie__decoder__num_decoded_frame_configs(
8704 const wuffs_nie__decoder* self);
8705
8706WUFFS_BASE__MAYBE_STATIC uint64_t
8707wuffs_nie__decoder__num_decoded_frames(
8708 const wuffs_nie__decoder* self);
8709
8710WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8711wuffs_nie__decoder__restart_frame(
8712 wuffs_nie__decoder* self,
8713 uint64_t a_index,
8714 uint64_t a_io_position);
8715
8716WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8717wuffs_nie__decoder__set_report_metadata(
8718 wuffs_nie__decoder* self,
8719 uint32_t a_fourcc,
8720 bool a_report);
8721
8722WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8723wuffs_nie__decoder__tell_me_more(
8724 wuffs_nie__decoder* self,
8725 wuffs_base__io_buffer* a_dst,
8726 wuffs_base__more_information* a_minfo,
8727 wuffs_base__io_buffer* a_src);
8728
8729WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
8730wuffs_nie__decoder__workbuf_len(
8731 const wuffs_nie__decoder* self);
8732
8733#ifdef __cplusplus
8734} // extern "C"
8735#endif
8736
8737// ---------------- Struct Definitions
8738
8739// These structs' fields, and the sizeof them, are private implementation
8740// details that aren't guaranteed to be stable across Wuffs versions.
8741//
8742// See https://en.wikipedia.org/wiki/Opaque_pointer#C
8743
8744#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8745
8746struct wuffs_nie__decoder__struct {
8747 // Do not access the private_impl's or private_data's fields directly. There
8748 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
8749 // the wuffs_foo__bar__baz functions.
8750 //
8751 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
8752 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
8753
8754 struct {
8755 uint32_t magic;
8756 uint32_t active_coroutine;
8757 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
8758 wuffs_base__vtable null_vtable;
8759
8760 uint32_t f_pixfmt;
8761 uint32_t f_width;
8762 uint32_t f_height;
8763 uint8_t f_call_sequence;
8764 uint32_t f_dst_x;
8765 uint32_t f_dst_y;
8766 wuffs_base__pixel_swizzler f_swizzler;
8767
8768 uint32_t p_decode_image_config[1];
8769 uint32_t p_decode_frame_config[1];
8770 uint32_t p_decode_frame[1];
8771 } private_impl;
8772
8773 struct {
8774 struct {
8775 uint64_t scratch;
8776 } s_decode_image_config[1];
8777 } private_data;
8778
8779#ifdef __cplusplus
8780#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8781 using unique_ptr = std::unique_ptr<wuffs_nie__decoder, decltype(&free)>;
8782
8783 // On failure, the alloc_etc functions return nullptr. They don't throw.
8784
8785 static inline unique_ptr
8786 alloc() {
8787 return unique_ptr(wuffs_nie__decoder__alloc(), &free);
8788 }
8789
8790 static inline wuffs_base__image_decoder::unique_ptr
8791 alloc_as__wuffs_base__image_decoder() {
8792 return wuffs_base__image_decoder::unique_ptr(
8793 wuffs_nie__decoder__alloc_as__wuffs_base__image_decoder(), &free);
8794 }
8795#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8796
8797#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8798 // Disallow constructing or copying an object via standard C++ mechanisms,
8799 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
8800 // size and field layout is not part of the public, stable, memory-safe API.
8801 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
8802 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
8803 // their first argument) rather than tweaking bar.private_impl.qux fields.
8804 //
8805 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
8806 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
8807 // order to provide convenience methods. These forward on "this", so that you
8808 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
8809 wuffs_nie__decoder__struct() = delete;
8810 wuffs_nie__decoder__struct(const wuffs_nie__decoder__struct&) = delete;
8811 wuffs_nie__decoder__struct& operator=(
8812 const wuffs_nie__decoder__struct&) = delete;
8813#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8814
8815#if !defined(WUFFS_IMPLEMENTATION)
8816 // As above, the size of the struct is not part of the public API, and unless
8817 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
8818 // allocated, not stack allocated. Its size is not intended to be known at
8819 // compile time, but it is unfortunately divulged as a side effect of
8820 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
8821 // instead of "sizeof T", invoking the operator. To make the two values
8822 // different, so that passing the latter will be rejected by the initialize
8823 // function, we add an arbitrary amount of dead weight.
8824 uint8_t dead_weight[123000000]; // 123 MB.
8825#endif // !defined(WUFFS_IMPLEMENTATION)
8826
8827 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8828 initialize(
8829 size_t sizeof_star_self,
8830 uint64_t wuffs_version,
8831 uint32_t options) {
8832 return wuffs_nie__decoder__initialize(
8833 this, sizeof_star_self, wuffs_version, options);
8834 }
8835
8836 inline wuffs_base__image_decoder*
8837 upcast_as__wuffs_base__image_decoder() {
8838 return (wuffs_base__image_decoder*)this;
8839 }
8840
8841 inline wuffs_base__empty_struct
8842 set_quirk_enabled(
8843 uint32_t a_quirk,
8844 bool a_enabled) {
8845 return wuffs_nie__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
8846 }
8847
8848 inline wuffs_base__status
8849 decode_image_config(
8850 wuffs_base__image_config* a_dst,
8851 wuffs_base__io_buffer* a_src) {
8852 return wuffs_nie__decoder__decode_image_config(this, a_dst, a_src);
8853 }
8854
8855 inline wuffs_base__status
8856 decode_frame_config(
8857 wuffs_base__frame_config* a_dst,
8858 wuffs_base__io_buffer* a_src) {
8859 return wuffs_nie__decoder__decode_frame_config(this, a_dst, a_src);
8860 }
8861
8862 inline wuffs_base__status
8863 decode_frame(
8864 wuffs_base__pixel_buffer* a_dst,
8865 wuffs_base__io_buffer* a_src,
8866 wuffs_base__pixel_blend a_blend,
8867 wuffs_base__slice_u8 a_workbuf,
8868 wuffs_base__decode_frame_options* a_opts) {
8869 return wuffs_nie__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
8870 }
8871
8872 inline wuffs_base__rect_ie_u32
8873 frame_dirty_rect() const {
8874 return wuffs_nie__decoder__frame_dirty_rect(this);
8875 }
8876
8877 inline uint32_t
8878 num_animation_loops() const {
8879 return wuffs_nie__decoder__num_animation_loops(this);
8880 }
8881
8882 inline uint64_t
8883 num_decoded_frame_configs() const {
8884 return wuffs_nie__decoder__num_decoded_frame_configs(this);
8885 }
8886
8887 inline uint64_t
8888 num_decoded_frames() const {
8889 return wuffs_nie__decoder__num_decoded_frames(this);
8890 }
8891
8892 inline wuffs_base__status
8893 restart_frame(
8894 uint64_t a_index,
8895 uint64_t a_io_position) {
8896 return wuffs_nie__decoder__restart_frame(this, a_index, a_io_position);
8897 }
8898
8899 inline wuffs_base__empty_struct
8900 set_report_metadata(
8901 uint32_t a_fourcc,
8902 bool a_report) {
8903 return wuffs_nie__decoder__set_report_metadata(this, a_fourcc, a_report);
8904 }
8905
8906 inline wuffs_base__status
8907 tell_me_more(
8908 wuffs_base__io_buffer* a_dst,
8909 wuffs_base__more_information* a_minfo,
8910 wuffs_base__io_buffer* a_src) {
8911 return wuffs_nie__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
8912 }
8913
8914 inline wuffs_base__range_ii_u64
8915 workbuf_len() const {
8916 return wuffs_nie__decoder__workbuf_len(this);
8917 }
8918
8919#endif // __cplusplus
8920}; // struct wuffs_nie__decoder__struct
8921
8922#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8923
8924// ---------------- Status Codes
8925
8926extern const char wuffs_zlib__note__dictionary_required[];
8927extern const char wuffs_zlib__error__bad_checksum[];
8928extern const char wuffs_zlib__error__bad_compression_method[];
8929extern const char wuffs_zlib__error__bad_compression_window_size[];
8930extern const char wuffs_zlib__error__bad_parity_check[];
8931extern const char wuffs_zlib__error__incorrect_dictionary[];
8932
8933// ---------------- Public Consts
8934
8935#define WUFFS_ZLIB__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1
8936
8937// ---------------- Struct Declarations
8938
8939typedef struct wuffs_zlib__decoder__struct wuffs_zlib__decoder;
8940
8941#ifdef __cplusplus
8942extern "C" {
8943#endif
8944
8945// ---------------- Public Initializer Prototypes
8946
8947// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
8948// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
8949//
8950// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
8951// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
8952
8953wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8954wuffs_zlib__decoder__initialize(
8955 wuffs_zlib__decoder* self,
8956 size_t sizeof_star_self,
8957 uint64_t wuffs_version,
8958 uint32_t options);
8959
8960size_t
8961sizeof__wuffs_zlib__decoder();
8962
8963// ---------------- Allocs
8964
8965// These functions allocate and initialize Wuffs structs. They return NULL if
8966// memory allocation fails. If they return non-NULL, there is no need to call
8967// wuffs_foo__bar__initialize, but the caller is responsible for eventually
8968// calling free on the returned pointer. That pointer is effectively a C++
8969// std::unique_ptr<T, decltype(&free)>.
8970
8971wuffs_zlib__decoder*
8972wuffs_zlib__decoder__alloc();
8973
8974static inline wuffs_base__io_transformer*
8975wuffs_zlib__decoder__alloc_as__wuffs_base__io_transformer() {
8976 return (wuffs_base__io_transformer*)(wuffs_zlib__decoder__alloc());
8977}
8978
8979// ---------------- Upcasts
8980
8981static inline wuffs_base__io_transformer*
8982wuffs_zlib__decoder__upcast_as__wuffs_base__io_transformer(
8983 wuffs_zlib__decoder* p) {
8984 return (wuffs_base__io_transformer*)p;
8985}
8986
8987// ---------------- Public Function Prototypes
8988
8989WUFFS_BASE__MAYBE_STATIC uint32_t
8990wuffs_zlib__decoder__dictionary_id(
8991 const wuffs_zlib__decoder* self);
8992
8993WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8994wuffs_zlib__decoder__add_dictionary(
8995 wuffs_zlib__decoder* self,
8996 wuffs_base__slice_u8 a_dict);
8997
8998WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8999wuffs_zlib__decoder__set_quirk_enabled(
9000 wuffs_zlib__decoder* self,
9001 uint32_t a_quirk,
9002 bool a_enabled);
9003
9004WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
9005wuffs_zlib__decoder__workbuf_len(
9006 const wuffs_zlib__decoder* self);
9007
9008WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9009wuffs_zlib__decoder__transform_io(
9010 wuffs_zlib__decoder* self,
9011 wuffs_base__io_buffer* a_dst,
9012 wuffs_base__io_buffer* a_src,
9013 wuffs_base__slice_u8 a_workbuf);
9014
9015#ifdef __cplusplus
9016} // extern "C"
9017#endif
9018
9019// ---------------- Struct Definitions
9020
9021// These structs' fields, and the sizeof them, are private implementation
9022// details that aren't guaranteed to be stable across Wuffs versions.
9023//
9024// See https://en.wikipedia.org/wiki/Opaque_pointer#C
9025
9026#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9027
9028struct wuffs_zlib__decoder__struct {
9029 // Do not access the private_impl's or private_data's fields directly. There
9030 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
9031 // the wuffs_foo__bar__baz functions.
9032 //
9033 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
9034 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
9035
9036 struct {
9037 uint32_t magic;
9038 uint32_t active_coroutine;
9039 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
9040 wuffs_base__vtable null_vtable;
9041
9042 bool f_bad_call_sequence;
9043 bool f_header_complete;
9044 bool f_got_dictionary;
9045 bool f_want_dictionary;
9046 bool f_ignore_checksum;
9047 uint32_t f_dict_id_got;
9048 uint32_t f_dict_id_want;
9049
9050 uint32_t p_transform_io[1];
9051 } private_impl;
9052
9053 struct {
9054 wuffs_adler32__hasher f_checksum;
9055 wuffs_adler32__hasher f_dict_id_hasher;
9056 wuffs_deflate__decoder f_flate;
9057
9058 struct {
9059 uint32_t v_checksum_got;
9060 uint64_t scratch;
9061 } s_transform_io[1];
9062 } private_data;
9063
9064#ifdef __cplusplus
9065#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9066 using unique_ptr = std::unique_ptr<wuffs_zlib__decoder, decltype(&free)>;
9067
9068 // On failure, the alloc_etc functions return nullptr. They don't throw.
9069
9070 static inline unique_ptr
9071 alloc() {
9072 return unique_ptr(wuffs_zlib__decoder__alloc(), &free);
9073 }
9074
9075 static inline wuffs_base__io_transformer::unique_ptr
9076 alloc_as__wuffs_base__io_transformer() {
9077 return wuffs_base__io_transformer::unique_ptr(
9078 wuffs_zlib__decoder__alloc_as__wuffs_base__io_transformer(), &free);
9079 }
9080#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9081
9082#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9083 // Disallow constructing or copying an object via standard C++ mechanisms,
9084 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
9085 // size and field layout is not part of the public, stable, memory-safe API.
9086 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
9087 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
9088 // their first argument) rather than tweaking bar.private_impl.qux fields.
9089 //
9090 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
9091 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
9092 // order to provide convenience methods. These forward on "this", so that you
9093 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
9094 wuffs_zlib__decoder__struct() = delete;
9095 wuffs_zlib__decoder__struct(const wuffs_zlib__decoder__struct&) = delete;
9096 wuffs_zlib__decoder__struct& operator=(
9097 const wuffs_zlib__decoder__struct&) = delete;
9098#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9099
9100#if !defined(WUFFS_IMPLEMENTATION)
9101 // As above, the size of the struct is not part of the public API, and unless
9102 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
9103 // allocated, not stack allocated. Its size is not intended to be known at
9104 // compile time, but it is unfortunately divulged as a side effect of
9105 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
9106 // instead of "sizeof T", invoking the operator. To make the two values
9107 // different, so that passing the latter will be rejected by the initialize
9108 // function, we add an arbitrary amount of dead weight.
9109 uint8_t dead_weight[123000000]; // 123 MB.
9110#endif // !defined(WUFFS_IMPLEMENTATION)
9111
9112 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9113 initialize(
9114 size_t sizeof_star_self,
9115 uint64_t wuffs_version,
9116 uint32_t options) {
9117 return wuffs_zlib__decoder__initialize(
9118 this, sizeof_star_self, wuffs_version, options);
9119 }
9120
9121 inline wuffs_base__io_transformer*
9122 upcast_as__wuffs_base__io_transformer() {
9123 return (wuffs_base__io_transformer*)this;
9124 }
9125
9126 inline uint32_t
9127 dictionary_id() const {
9128 return wuffs_zlib__decoder__dictionary_id(this);
9129 }
9130
9131 inline wuffs_base__empty_struct
9132 add_dictionary(
9133 wuffs_base__slice_u8 a_dict) {
9134 return wuffs_zlib__decoder__add_dictionary(this, a_dict);
9135 }
9136
9137 inline wuffs_base__empty_struct
9138 set_quirk_enabled(
9139 uint32_t a_quirk,
9140 bool a_enabled) {
9141 return wuffs_zlib__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
9142 }
9143
9144 inline wuffs_base__range_ii_u64
9145 workbuf_len() const {
9146 return wuffs_zlib__decoder__workbuf_len(this);
9147 }
9148
9149 inline wuffs_base__status
9150 transform_io(
9151 wuffs_base__io_buffer* a_dst,
9152 wuffs_base__io_buffer* a_src,
9153 wuffs_base__slice_u8 a_workbuf) {
9154 return wuffs_zlib__decoder__transform_io(this, a_dst, a_src, a_workbuf);
9155 }
9156
9157#endif // __cplusplus
9158}; // struct wuffs_zlib__decoder__struct
9159
9160#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9161
9162// ---------------- Status Codes
9163
Nigel Taobf9dab32021-11-18 19:19:55 +11009164extern const char wuffs_png__error__bad_animation_sequence_number[];
Nigel Taoe360a532021-04-05 22:47:03 +10009165extern const char wuffs_png__error__bad_checksum[];
9166extern const char wuffs_png__error__bad_chunk[];
9167extern const char wuffs_png__error__bad_filter[];
9168extern const char wuffs_png__error__bad_header[];
Nigel Taobf9dab32021-11-18 19:19:55 +11009169extern const char wuffs_png__error__bad_text_chunk_not_latin_1[];
Nigel Taoe360a532021-04-05 22:47:03 +10009170extern const char wuffs_png__error__missing_palette[];
Nigel Taobf9dab32021-11-18 19:19:55 +11009171extern const char wuffs_png__error__unsupported_png_compression_method[];
Nigel Taoe360a532021-04-05 22:47:03 +10009172extern const char wuffs_png__error__unsupported_png_file[];
9173
9174// ---------------- Public Consts
9175
9176#define WUFFS_PNG__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
9177
Nigel Taobf9dab32021-11-18 19:19:55 +11009178#define WUFFS_PNG__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 8
9179
Nigel Taoe360a532021-04-05 22:47:03 +10009180// ---------------- Struct Declarations
9181
9182typedef struct wuffs_png__decoder__struct wuffs_png__decoder;
9183
9184#ifdef __cplusplus
9185extern "C" {
9186#endif
9187
9188// ---------------- Public Initializer Prototypes
9189
9190// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
9191// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
9192//
9193// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
9194// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
9195
9196wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9197wuffs_png__decoder__initialize(
9198 wuffs_png__decoder* self,
9199 size_t sizeof_star_self,
9200 uint64_t wuffs_version,
9201 uint32_t options);
9202
9203size_t
9204sizeof__wuffs_png__decoder();
9205
9206// ---------------- Allocs
9207
9208// These functions allocate and initialize Wuffs structs. They return NULL if
9209// memory allocation fails. If they return non-NULL, there is no need to call
9210// wuffs_foo__bar__initialize, but the caller is responsible for eventually
9211// calling free on the returned pointer. That pointer is effectively a C++
9212// std::unique_ptr<T, decltype(&free)>.
9213
9214wuffs_png__decoder*
9215wuffs_png__decoder__alloc();
9216
9217static inline wuffs_base__image_decoder*
9218wuffs_png__decoder__alloc_as__wuffs_base__image_decoder() {
9219 return (wuffs_base__image_decoder*)(wuffs_png__decoder__alloc());
9220}
9221
9222// ---------------- Upcasts
9223
9224static inline wuffs_base__image_decoder*
9225wuffs_png__decoder__upcast_as__wuffs_base__image_decoder(
9226 wuffs_png__decoder* p) {
9227 return (wuffs_base__image_decoder*)p;
9228}
9229
9230// ---------------- Public Function Prototypes
9231
9232WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9233wuffs_png__decoder__set_quirk_enabled(
9234 wuffs_png__decoder* self,
9235 uint32_t a_quirk,
9236 bool a_enabled);
9237
9238WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9239wuffs_png__decoder__decode_image_config(
9240 wuffs_png__decoder* self,
9241 wuffs_base__image_config* a_dst,
9242 wuffs_base__io_buffer* a_src);
9243
9244WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9245wuffs_png__decoder__decode_frame_config(
9246 wuffs_png__decoder* self,
9247 wuffs_base__frame_config* a_dst,
9248 wuffs_base__io_buffer* a_src);
9249
9250WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9251wuffs_png__decoder__decode_frame(
9252 wuffs_png__decoder* self,
9253 wuffs_base__pixel_buffer* a_dst,
9254 wuffs_base__io_buffer* a_src,
9255 wuffs_base__pixel_blend a_blend,
9256 wuffs_base__slice_u8 a_workbuf,
9257 wuffs_base__decode_frame_options* a_opts);
9258
9259WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
9260wuffs_png__decoder__frame_dirty_rect(
9261 const wuffs_png__decoder* self);
9262
9263WUFFS_BASE__MAYBE_STATIC uint32_t
9264wuffs_png__decoder__num_animation_loops(
9265 const wuffs_png__decoder* self);
9266
9267WUFFS_BASE__MAYBE_STATIC uint64_t
9268wuffs_png__decoder__num_decoded_frame_configs(
9269 const wuffs_png__decoder* self);
9270
9271WUFFS_BASE__MAYBE_STATIC uint64_t
9272wuffs_png__decoder__num_decoded_frames(
9273 const wuffs_png__decoder* self);
9274
9275WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9276wuffs_png__decoder__restart_frame(
9277 wuffs_png__decoder* self,
9278 uint64_t a_index,
9279 uint64_t a_io_position);
9280
9281WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9282wuffs_png__decoder__set_report_metadata(
9283 wuffs_png__decoder* self,
9284 uint32_t a_fourcc,
9285 bool a_report);
9286
9287WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9288wuffs_png__decoder__tell_me_more(
9289 wuffs_png__decoder* self,
9290 wuffs_base__io_buffer* a_dst,
9291 wuffs_base__more_information* a_minfo,
9292 wuffs_base__io_buffer* a_src);
9293
9294WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
9295wuffs_png__decoder__workbuf_len(
9296 const wuffs_png__decoder* self);
9297
9298#ifdef __cplusplus
9299} // extern "C"
9300#endif
9301
9302// ---------------- Struct Definitions
9303
9304// These structs' fields, and the sizeof them, are private implementation
9305// details that aren't guaranteed to be stable across Wuffs versions.
9306//
9307// See https://en.wikipedia.org/wiki/Opaque_pointer#C
9308
9309#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9310
9311struct wuffs_png__decoder__struct {
9312 // Do not access the private_impl's or private_data's fields directly. There
9313 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
9314 // the wuffs_foo__bar__baz functions.
9315 //
9316 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
9317 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
9318
9319 struct {
9320 uint32_t magic;
9321 uint32_t active_coroutine;
9322 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
9323 wuffs_base__vtable null_vtable;
9324
9325 uint32_t f_width;
9326 uint32_t f_height;
9327 uint64_t f_pass_bytes_per_row;
9328 uint64_t f_workbuf_wi;
Nigel Tao7804ffe2021-10-07 21:58:26 +11009329 uint64_t f_workbuf_hist_pos_base;
Nigel Taoe360a532021-04-05 22:47:03 +10009330 uint64_t f_overall_workbuf_length;
9331 uint64_t f_pass_workbuf_length;
9332 uint8_t f_call_sequence;
Nigel Taobf9dab32021-11-18 19:19:55 +11009333 bool f_report_metadata_chrm;
9334 bool f_report_metadata_gama;
9335 bool f_report_metadata_iccp;
9336 bool f_report_metadata_kvp;
9337 bool f_report_metadata_srgb;
Nigel Taoe360a532021-04-05 22:47:03 +10009338 bool f_ignore_checksum;
9339 uint8_t f_depth;
9340 uint8_t f_color_type;
9341 uint8_t f_filter_distance;
9342 uint8_t f_interlace_pass;
Nigel Taobf9dab32021-11-18 19:19:55 +11009343 bool f_seen_actl;
9344 bool f_seen_chrm;
9345 bool f_seen_fctl;
9346 bool f_seen_gama;
9347 bool f_seen_iccp;
9348 bool f_seen_idat;
Nigel Taoe360a532021-04-05 22:47:03 +10009349 bool f_seen_plte;
Nigel Taobf9dab32021-11-18 19:19:55 +11009350 bool f_seen_srgb;
Nigel Taoe360a532021-04-05 22:47:03 +10009351 bool f_seen_trns;
Nigel Taobf9dab32021-11-18 19:19:55 +11009352 bool f_metadata_is_zlib_compressed;
9353 bool f_zlib_is_dirty;
Nigel Taoe360a532021-04-05 22:47:03 +10009354 uint32_t f_chunk_type;
9355 uint8_t f_chunk_type_array[4];
Nigel Taobf9dab32021-11-18 19:19:55 +11009356 uint32_t f_chunk_length;
9357 uint64_t f_remap_transparency;
9358 uint32_t f_dst_pixfmt;
9359 uint32_t f_src_pixfmt;
9360 uint32_t f_num_animation_frames_value;
9361 uint32_t f_num_animation_loops_value;
9362 uint32_t f_num_decoded_frame_configs_value;
9363 uint32_t f_num_decoded_frames_value;
9364 uint32_t f_frame_rect_x0;
9365 uint32_t f_frame_rect_y0;
9366 uint32_t f_frame_rect_x1;
9367 uint32_t f_frame_rect_y1;
9368 uint32_t f_first_rect_x0;
9369 uint32_t f_first_rect_y0;
9370 uint32_t f_first_rect_x1;
9371 uint32_t f_first_rect_y1;
Nigel Taoe360a532021-04-05 22:47:03 +10009372 uint64_t f_frame_config_io_position;
Nigel Taobf9dab32021-11-18 19:19:55 +11009373 uint64_t f_first_config_io_position;
9374 uint64_t f_frame_duration;
9375 uint64_t f_first_duration;
9376 uint8_t f_frame_disposal;
9377 uint8_t f_first_disposal;
9378 bool f_frame_overwrite_instead_of_blend;
9379 bool f_first_overwrite_instead_of_blend;
9380 uint32_t f_next_animation_seq_num;
9381 uint32_t f_metadata_flavor;
9382 uint32_t f_metadata_fourcc;
9383 uint64_t f_metadata_x;
9384 uint64_t f_metadata_y;
9385 uint64_t f_metadata_z;
9386 uint32_t f_ztxt_ri;
9387 uint32_t f_ztxt_wi;
9388 uint64_t f_ztxt_hist_pos;
Nigel Taoe360a532021-04-05 22:47:03 +10009389 wuffs_base__pixel_swizzler f_swizzler;
9390
9391 wuffs_base__empty_struct (*choosy_filter_1)(
9392 wuffs_png__decoder* self,
9393 wuffs_base__slice_u8 a_curr);
9394 wuffs_base__empty_struct (*choosy_filter_3)(
9395 wuffs_png__decoder* self,
9396 wuffs_base__slice_u8 a_curr,
9397 wuffs_base__slice_u8 a_prev);
9398 wuffs_base__empty_struct (*choosy_filter_4)(
9399 wuffs_png__decoder* self,
9400 wuffs_base__slice_u8 a_curr,
9401 wuffs_base__slice_u8 a_prev);
9402 uint32_t p_decode_image_config[1];
9403 uint32_t p_decode_ihdr[1];
9404 uint32_t p_decode_other_chunk[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009405 uint32_t p_decode_actl[1];
9406 uint32_t p_decode_chrm[1];
9407 uint32_t p_decode_fctl[1];
9408 uint32_t p_decode_gama[1];
9409 uint32_t p_decode_iccp[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009410 uint32_t p_decode_plte[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009411 uint32_t p_decode_srgb[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009412 uint32_t p_decode_trns[1];
9413 uint32_t p_decode_frame_config[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009414 uint32_t p_skip_frame[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009415 uint32_t p_decode_frame[1];
9416 uint32_t p_decode_pass[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009417 uint32_t p_tell_me_more[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009418 wuffs_base__status (*choosy_filter_and_swizzle)(
9419 wuffs_png__decoder* self,
9420 wuffs_base__pixel_buffer* a_dst,
9421 wuffs_base__slice_u8 a_workbuf);
9422 } private_impl;
9423
9424 struct {
9425 wuffs_crc32__ieee_hasher f_crc32;
9426 wuffs_zlib__decoder f_zlib;
9427 uint8_t f_dst_palette[1024];
9428 uint8_t f_src_palette[1024];
9429
9430 struct {
9431 uint32_t v_checksum_have;
9432 uint64_t scratch;
9433 } s_decode_image_config[1];
9434 struct {
9435 uint64_t scratch;
9436 } s_decode_ihdr[1];
9437 struct {
9438 uint64_t scratch;
9439 } s_decode_other_chunk[1];
9440 struct {
Nigel Taobf9dab32021-11-18 19:19:55 +11009441 uint64_t scratch;
9442 } s_decode_actl[1];
9443 struct {
9444 uint64_t scratch;
9445 } s_decode_chrm[1];
9446 struct {
9447 uint32_t v_x0;
9448 uint32_t v_x1;
9449 uint32_t v_y1;
9450 uint64_t scratch;
9451 } s_decode_fctl[1];
9452 struct {
9453 uint64_t scratch;
9454 } s_decode_gama[1];
9455 struct {
Nigel Taoe360a532021-04-05 22:47:03 +10009456 uint32_t v_num_entries;
9457 uint32_t v_i;
9458 uint64_t scratch;
9459 } s_decode_plte[1];
9460 struct {
Nigel Taoe360a532021-04-05 22:47:03 +10009461 uint32_t v_i;
Nigel Taobf9dab32021-11-18 19:19:55 +11009462 uint32_t v_n;
9463 uint64_t scratch;
Nigel Taoe360a532021-04-05 22:47:03 +10009464 } s_decode_trns[1];
9465 struct {
Nigel Taobf9dab32021-11-18 19:19:55 +11009466 uint64_t scratch;
9467 } s_decode_frame_config[1];
9468 struct {
9469 uint64_t scratch;
9470 } s_skip_frame[1];
9471 struct {
9472 uint64_t scratch;
9473 } s_decode_frame[1];
9474 struct {
Nigel Taoe360a532021-04-05 22:47:03 +10009475 uint64_t scratch;
9476 } s_decode_pass[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009477 struct {
9478 wuffs_base__status v_zlib_status;
9479 uint64_t scratch;
9480 } s_tell_me_more[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009481 } private_data;
9482
9483#ifdef __cplusplus
9484#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9485 using unique_ptr = std::unique_ptr<wuffs_png__decoder, decltype(&free)>;
9486
9487 // On failure, the alloc_etc functions return nullptr. They don't throw.
9488
9489 static inline unique_ptr
9490 alloc() {
9491 return unique_ptr(wuffs_png__decoder__alloc(), &free);
9492 }
9493
9494 static inline wuffs_base__image_decoder::unique_ptr
9495 alloc_as__wuffs_base__image_decoder() {
9496 return wuffs_base__image_decoder::unique_ptr(
9497 wuffs_png__decoder__alloc_as__wuffs_base__image_decoder(), &free);
9498 }
9499#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9500
9501#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9502 // Disallow constructing or copying an object via standard C++ mechanisms,
9503 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
9504 // size and field layout is not part of the public, stable, memory-safe API.
9505 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
9506 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
9507 // their first argument) rather than tweaking bar.private_impl.qux fields.
9508 //
9509 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
9510 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
9511 // order to provide convenience methods. These forward on "this", so that you
9512 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
9513 wuffs_png__decoder__struct() = delete;
9514 wuffs_png__decoder__struct(const wuffs_png__decoder__struct&) = delete;
9515 wuffs_png__decoder__struct& operator=(
9516 const wuffs_png__decoder__struct&) = delete;
9517#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9518
9519#if !defined(WUFFS_IMPLEMENTATION)
9520 // As above, the size of the struct is not part of the public API, and unless
9521 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
9522 // allocated, not stack allocated. Its size is not intended to be known at
9523 // compile time, but it is unfortunately divulged as a side effect of
9524 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
9525 // instead of "sizeof T", invoking the operator. To make the two values
9526 // different, so that passing the latter will be rejected by the initialize
9527 // function, we add an arbitrary amount of dead weight.
9528 uint8_t dead_weight[123000000]; // 123 MB.
9529#endif // !defined(WUFFS_IMPLEMENTATION)
9530
9531 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9532 initialize(
9533 size_t sizeof_star_self,
9534 uint64_t wuffs_version,
9535 uint32_t options) {
9536 return wuffs_png__decoder__initialize(
9537 this, sizeof_star_self, wuffs_version, options);
9538 }
9539
9540 inline wuffs_base__image_decoder*
9541 upcast_as__wuffs_base__image_decoder() {
9542 return (wuffs_base__image_decoder*)this;
9543 }
9544
9545 inline wuffs_base__empty_struct
9546 set_quirk_enabled(
9547 uint32_t a_quirk,
9548 bool a_enabled) {
9549 return wuffs_png__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
9550 }
9551
9552 inline wuffs_base__status
9553 decode_image_config(
9554 wuffs_base__image_config* a_dst,
9555 wuffs_base__io_buffer* a_src) {
9556 return wuffs_png__decoder__decode_image_config(this, a_dst, a_src);
9557 }
9558
9559 inline wuffs_base__status
9560 decode_frame_config(
9561 wuffs_base__frame_config* a_dst,
9562 wuffs_base__io_buffer* a_src) {
9563 return wuffs_png__decoder__decode_frame_config(this, a_dst, a_src);
9564 }
9565
9566 inline wuffs_base__status
9567 decode_frame(
9568 wuffs_base__pixel_buffer* a_dst,
9569 wuffs_base__io_buffer* a_src,
9570 wuffs_base__pixel_blend a_blend,
9571 wuffs_base__slice_u8 a_workbuf,
9572 wuffs_base__decode_frame_options* a_opts) {
9573 return wuffs_png__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
9574 }
9575
9576 inline wuffs_base__rect_ie_u32
9577 frame_dirty_rect() const {
9578 return wuffs_png__decoder__frame_dirty_rect(this);
9579 }
9580
9581 inline uint32_t
9582 num_animation_loops() const {
9583 return wuffs_png__decoder__num_animation_loops(this);
9584 }
9585
9586 inline uint64_t
9587 num_decoded_frame_configs() const {
9588 return wuffs_png__decoder__num_decoded_frame_configs(this);
9589 }
9590
9591 inline uint64_t
9592 num_decoded_frames() const {
9593 return wuffs_png__decoder__num_decoded_frames(this);
9594 }
9595
9596 inline wuffs_base__status
9597 restart_frame(
9598 uint64_t a_index,
9599 uint64_t a_io_position) {
9600 return wuffs_png__decoder__restart_frame(this, a_index, a_io_position);
9601 }
9602
9603 inline wuffs_base__empty_struct
9604 set_report_metadata(
9605 uint32_t a_fourcc,
9606 bool a_report) {
9607 return wuffs_png__decoder__set_report_metadata(this, a_fourcc, a_report);
9608 }
9609
9610 inline wuffs_base__status
9611 tell_me_more(
9612 wuffs_base__io_buffer* a_dst,
9613 wuffs_base__more_information* a_minfo,
9614 wuffs_base__io_buffer* a_src) {
9615 return wuffs_png__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
9616 }
9617
9618 inline wuffs_base__range_ii_u64
9619 workbuf_len() const {
9620 return wuffs_png__decoder__workbuf_len(this);
9621 }
9622
9623#endif // __cplusplus
9624}; // struct wuffs_png__decoder__struct
9625
9626#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9627
9628// ---------------- Status Codes
9629
9630extern const char wuffs_wbmp__error__bad_header[];
9631
9632// ---------------- Public Consts
9633
9634#define WUFFS_WBMP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
9635
9636// ---------------- Struct Declarations
9637
9638typedef struct wuffs_wbmp__decoder__struct wuffs_wbmp__decoder;
9639
9640#ifdef __cplusplus
9641extern "C" {
9642#endif
9643
9644// ---------------- Public Initializer Prototypes
9645
9646// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
9647// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
9648//
9649// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
9650// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
9651
9652wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9653wuffs_wbmp__decoder__initialize(
9654 wuffs_wbmp__decoder* self,
9655 size_t sizeof_star_self,
9656 uint64_t wuffs_version,
9657 uint32_t options);
9658
9659size_t
9660sizeof__wuffs_wbmp__decoder();
9661
9662// ---------------- Allocs
9663
9664// These functions allocate and initialize Wuffs structs. They return NULL if
9665// memory allocation fails. If they return non-NULL, there is no need to call
9666// wuffs_foo__bar__initialize, but the caller is responsible for eventually
9667// calling free on the returned pointer. That pointer is effectively a C++
9668// std::unique_ptr<T, decltype(&free)>.
9669
9670wuffs_wbmp__decoder*
9671wuffs_wbmp__decoder__alloc();
9672
9673static inline wuffs_base__image_decoder*
9674wuffs_wbmp__decoder__alloc_as__wuffs_base__image_decoder() {
9675 return (wuffs_base__image_decoder*)(wuffs_wbmp__decoder__alloc());
9676}
9677
9678// ---------------- Upcasts
9679
9680static inline wuffs_base__image_decoder*
9681wuffs_wbmp__decoder__upcast_as__wuffs_base__image_decoder(
9682 wuffs_wbmp__decoder* p) {
9683 return (wuffs_base__image_decoder*)p;
9684}
9685
9686// ---------------- Public Function Prototypes
9687
9688WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9689wuffs_wbmp__decoder__set_quirk_enabled(
9690 wuffs_wbmp__decoder* self,
9691 uint32_t a_quirk,
9692 bool a_enabled);
9693
9694WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9695wuffs_wbmp__decoder__decode_image_config(
9696 wuffs_wbmp__decoder* self,
9697 wuffs_base__image_config* a_dst,
9698 wuffs_base__io_buffer* a_src);
9699
9700WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9701wuffs_wbmp__decoder__decode_frame_config(
9702 wuffs_wbmp__decoder* self,
9703 wuffs_base__frame_config* a_dst,
9704 wuffs_base__io_buffer* a_src);
9705
9706WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9707wuffs_wbmp__decoder__decode_frame(
9708 wuffs_wbmp__decoder* self,
9709 wuffs_base__pixel_buffer* a_dst,
9710 wuffs_base__io_buffer* a_src,
9711 wuffs_base__pixel_blend a_blend,
9712 wuffs_base__slice_u8 a_workbuf,
9713 wuffs_base__decode_frame_options* a_opts);
9714
9715WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
9716wuffs_wbmp__decoder__frame_dirty_rect(
9717 const wuffs_wbmp__decoder* self);
9718
9719WUFFS_BASE__MAYBE_STATIC uint32_t
9720wuffs_wbmp__decoder__num_animation_loops(
9721 const wuffs_wbmp__decoder* self);
9722
9723WUFFS_BASE__MAYBE_STATIC uint64_t
9724wuffs_wbmp__decoder__num_decoded_frame_configs(
9725 const wuffs_wbmp__decoder* self);
9726
9727WUFFS_BASE__MAYBE_STATIC uint64_t
9728wuffs_wbmp__decoder__num_decoded_frames(
9729 const wuffs_wbmp__decoder* self);
9730
9731WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9732wuffs_wbmp__decoder__restart_frame(
9733 wuffs_wbmp__decoder* self,
9734 uint64_t a_index,
9735 uint64_t a_io_position);
9736
9737WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9738wuffs_wbmp__decoder__set_report_metadata(
9739 wuffs_wbmp__decoder* self,
9740 uint32_t a_fourcc,
9741 bool a_report);
9742
9743WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9744wuffs_wbmp__decoder__tell_me_more(
9745 wuffs_wbmp__decoder* self,
9746 wuffs_base__io_buffer* a_dst,
9747 wuffs_base__more_information* a_minfo,
9748 wuffs_base__io_buffer* a_src);
9749
9750WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
9751wuffs_wbmp__decoder__workbuf_len(
9752 const wuffs_wbmp__decoder* self);
9753
9754#ifdef __cplusplus
9755} // extern "C"
9756#endif
9757
9758// ---------------- Struct Definitions
9759
9760// These structs' fields, and the sizeof them, are private implementation
9761// details that aren't guaranteed to be stable across Wuffs versions.
9762//
9763// See https://en.wikipedia.org/wiki/Opaque_pointer#C
9764
9765#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9766
9767struct wuffs_wbmp__decoder__struct {
9768 // Do not access the private_impl's or private_data's fields directly. There
9769 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
9770 // the wuffs_foo__bar__baz functions.
9771 //
9772 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
9773 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
9774
9775 struct {
9776 uint32_t magic;
9777 uint32_t active_coroutine;
9778 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
9779 wuffs_base__vtable null_vtable;
9780
9781 uint32_t f_width;
9782 uint32_t f_height;
9783 uint8_t f_call_sequence;
9784 uint64_t f_frame_config_io_position;
9785 wuffs_base__pixel_swizzler f_swizzler;
9786
9787 uint32_t p_decode_image_config[1];
9788 uint32_t p_decode_frame_config[1];
9789 uint32_t p_decode_frame[1];
9790 } private_impl;
9791
9792 struct {
9793 struct {
9794 uint32_t v_i;
9795 uint32_t v_x32;
9796 } s_decode_image_config[1];
9797 struct {
9798 uint64_t v_dst_bytes_per_pixel;
9799 uint32_t v_dst_x;
9800 uint32_t v_dst_y;
9801 uint8_t v_src[1];
9802 uint8_t v_c;
9803 } s_decode_frame[1];
9804 } private_data;
9805
9806#ifdef __cplusplus
9807#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9808 using unique_ptr = std::unique_ptr<wuffs_wbmp__decoder, decltype(&free)>;
9809
9810 // On failure, the alloc_etc functions return nullptr. They don't throw.
9811
9812 static inline unique_ptr
9813 alloc() {
9814 return unique_ptr(wuffs_wbmp__decoder__alloc(), &free);
9815 }
9816
9817 static inline wuffs_base__image_decoder::unique_ptr
9818 alloc_as__wuffs_base__image_decoder() {
9819 return wuffs_base__image_decoder::unique_ptr(
9820 wuffs_wbmp__decoder__alloc_as__wuffs_base__image_decoder(), &free);
9821 }
9822#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9823
9824#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9825 // Disallow constructing or copying an object via standard C++ mechanisms,
9826 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
9827 // size and field layout is not part of the public, stable, memory-safe API.
9828 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
9829 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
9830 // their first argument) rather than tweaking bar.private_impl.qux fields.
9831 //
9832 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
9833 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
9834 // order to provide convenience methods. These forward on "this", so that you
9835 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
9836 wuffs_wbmp__decoder__struct() = delete;
9837 wuffs_wbmp__decoder__struct(const wuffs_wbmp__decoder__struct&) = delete;
9838 wuffs_wbmp__decoder__struct& operator=(
9839 const wuffs_wbmp__decoder__struct&) = delete;
9840#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9841
9842#if !defined(WUFFS_IMPLEMENTATION)
9843 // As above, the size of the struct is not part of the public API, and unless
9844 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
9845 // allocated, not stack allocated. Its size is not intended to be known at
9846 // compile time, but it is unfortunately divulged as a side effect of
9847 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
9848 // instead of "sizeof T", invoking the operator. To make the two values
9849 // different, so that passing the latter will be rejected by the initialize
9850 // function, we add an arbitrary amount of dead weight.
9851 uint8_t dead_weight[123000000]; // 123 MB.
9852#endif // !defined(WUFFS_IMPLEMENTATION)
9853
9854 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9855 initialize(
9856 size_t sizeof_star_self,
9857 uint64_t wuffs_version,
9858 uint32_t options) {
9859 return wuffs_wbmp__decoder__initialize(
9860 this, sizeof_star_self, wuffs_version, options);
9861 }
9862
9863 inline wuffs_base__image_decoder*
9864 upcast_as__wuffs_base__image_decoder() {
9865 return (wuffs_base__image_decoder*)this;
9866 }
9867
9868 inline wuffs_base__empty_struct
9869 set_quirk_enabled(
9870 uint32_t a_quirk,
9871 bool a_enabled) {
9872 return wuffs_wbmp__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
9873 }
9874
9875 inline wuffs_base__status
9876 decode_image_config(
9877 wuffs_base__image_config* a_dst,
9878 wuffs_base__io_buffer* a_src) {
9879 return wuffs_wbmp__decoder__decode_image_config(this, a_dst, a_src);
9880 }
9881
9882 inline wuffs_base__status
9883 decode_frame_config(
9884 wuffs_base__frame_config* a_dst,
9885 wuffs_base__io_buffer* a_src) {
9886 return wuffs_wbmp__decoder__decode_frame_config(this, a_dst, a_src);
9887 }
9888
9889 inline wuffs_base__status
9890 decode_frame(
9891 wuffs_base__pixel_buffer* a_dst,
9892 wuffs_base__io_buffer* a_src,
9893 wuffs_base__pixel_blend a_blend,
9894 wuffs_base__slice_u8 a_workbuf,
9895 wuffs_base__decode_frame_options* a_opts) {
9896 return wuffs_wbmp__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
9897 }
9898
9899 inline wuffs_base__rect_ie_u32
9900 frame_dirty_rect() const {
9901 return wuffs_wbmp__decoder__frame_dirty_rect(this);
9902 }
9903
9904 inline uint32_t
9905 num_animation_loops() const {
9906 return wuffs_wbmp__decoder__num_animation_loops(this);
9907 }
9908
9909 inline uint64_t
9910 num_decoded_frame_configs() const {
9911 return wuffs_wbmp__decoder__num_decoded_frame_configs(this);
9912 }
9913
9914 inline uint64_t
9915 num_decoded_frames() const {
9916 return wuffs_wbmp__decoder__num_decoded_frames(this);
9917 }
9918
9919 inline wuffs_base__status
9920 restart_frame(
9921 uint64_t a_index,
9922 uint64_t a_io_position) {
9923 return wuffs_wbmp__decoder__restart_frame(this, a_index, a_io_position);
9924 }
9925
9926 inline wuffs_base__empty_struct
9927 set_report_metadata(
9928 uint32_t a_fourcc,
9929 bool a_report) {
9930 return wuffs_wbmp__decoder__set_report_metadata(this, a_fourcc, a_report);
9931 }
9932
9933 inline wuffs_base__status
9934 tell_me_more(
9935 wuffs_base__io_buffer* a_dst,
9936 wuffs_base__more_information* a_minfo,
9937 wuffs_base__io_buffer* a_src) {
9938 return wuffs_wbmp__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
9939 }
9940
9941 inline wuffs_base__range_ii_u64
9942 workbuf_len() const {
9943 return wuffs_wbmp__decoder__workbuf_len(this);
9944 }
9945
9946#endif // __cplusplus
9947}; // struct wuffs_wbmp__decoder__struct
9948
9949#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9950
9951#if defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9952
9953// ---------------- Auxiliary - Base
9954
9955// Auxiliary code is discussed at
9956// https://github.com/google/wuffs/blob/main/doc/note/auxiliary-code.md
9957
9958#include <stdio.h>
9959
9960#include <string>
9961
9962namespace wuffs_aux {
9963
9964using IOBuffer = wuffs_base__io_buffer;
9965
9966// MemOwner represents ownership of some memory. Dynamically allocated memory
9967// (e.g. from malloc or new) is typically paired with free or delete, invoked
9968// when the std::unique_ptr is destroyed. Statically allocated memory might use
9969// MemOwner(nullptr, &free), even if that statically allocated memory is not
9970// nullptr, since calling free(nullptr) is a no-op.
9971using MemOwner = std::unique_ptr<void, decltype(&free)>;
9972
9973namespace sync_io {
9974
9975// --------
9976
Nigel Taobf9dab32021-11-18 19:19:55 +11009977// DynIOBuffer is an IOBuffer that is backed by a dynamically sized byte array.
9978// It owns that backing array and will free it in its destructor.
9979//
9980// The array size can be explicitly extended (by calling the grow method) but,
9981// unlike a C++ std::vector, there is no implicit extension (e.g. by calling
9982// std::vector::insert) and its maximum size is capped by the max_incl
9983// constructor argument.
9984//
9985// It contains an IOBuffer-typed field whose reader side provides access to
9986// previously written bytes and whose writer side provides access to the
9987// allocated but not-yet-written-to slack space. For Go programmers, this slack
9988// space is roughly analogous to the s[len(s):cap(s)] space of a slice s.
9989class DynIOBuffer {
9990 public:
9991 enum GrowResult {
9992 OK = 0,
9993 FailedMaxInclExceeded = 1,
9994 FailedOutOfMemory = 2,
9995 };
9996
9997 // m_buf holds the dynamically sized byte array and its read/write indexes:
9998 // - m_buf.meta.wi is roughly analogous to a Go slice's length.
9999 // - m_buf.data.len is roughly analogous to a Go slice's capacity. It is
10000 // also equal to the m_buf.data.ptr malloc/realloc size.
10001 //
10002 // Users should not modify the m_buf.data.ptr or m_buf.data.len fields (as
10003 // they are conceptually private to this class), but they can modify the
10004 // bytes referenced by that pointer-length pair (e.g. compactions).
10005 IOBuffer m_buf;
10006
10007 // m_max_incl is an inclusive upper bound on the backing array size.
10008 const uint64_t m_max_incl;
10009
10010 // Constructor and destructor.
10011 explicit DynIOBuffer(uint64_t max_incl);
10012 ~DynIOBuffer();
10013
10014 // Drop frees the byte array and resets m_buf. The DynIOBuffer can still be
10015 // used after a drop call. It just restarts from zero.
10016 void drop();
10017
10018 // grow ensures that the byte array size is at least min_incl and at most
10019 // max_incl. It returns FailedMaxInclExceeded if that would require
10020 // allocating more than max_incl bytes, including the case where (min_incl >
10021 // max_incl). It returns FailedOutOfMemory if memory allocation failed.
10022 GrowResult grow(uint64_t min_incl);
10023
10024 private:
10025 // Delete the copy and assign constructors.
10026 DynIOBuffer(const DynIOBuffer&) = delete;
10027 DynIOBuffer& operator=(const DynIOBuffer&) = delete;
10028
10029 static uint64_t round_up(uint64_t min_incl, uint64_t max_incl);
10030};
10031
10032// --------
10033
Nigel Taoe360a532021-04-05 22:47:03 +100010034class Input {
10035 public:
10036 virtual ~Input();
10037
10038 virtual IOBuffer* BringsItsOwnIOBuffer();
10039 virtual std::string CopyIn(IOBuffer* dst) = 0;
10040};
10041
10042// --------
10043
10044// FileInput is an Input that reads from a file source.
10045//
10046// It does not take responsibility for closing the file when done.
10047class FileInput : public Input {
10048 public:
10049 FileInput(FILE* f);
10050
10051 virtual std::string CopyIn(IOBuffer* dst);
10052
10053 private:
10054 FILE* m_f;
10055
10056 // Delete the copy and assign constructors.
10057 FileInput(const FileInput&) = delete;
10058 FileInput& operator=(const FileInput&) = delete;
10059};
10060
10061// --------
10062
10063// MemoryInput is an Input that reads from an in-memory source.
10064//
10065// It does not take responsibility for freeing the memory when done.
10066class MemoryInput : public Input {
10067 public:
10068 MemoryInput(const char* ptr, size_t len);
10069 MemoryInput(const uint8_t* ptr, size_t len);
10070
10071 virtual IOBuffer* BringsItsOwnIOBuffer();
10072 virtual std::string CopyIn(IOBuffer* dst);
10073
10074 private:
10075 IOBuffer m_io;
10076
10077 // Delete the copy and assign constructors.
10078 MemoryInput(const MemoryInput&) = delete;
10079 MemoryInput& operator=(const MemoryInput&) = delete;
10080};
10081
10082// --------
10083
10084} // namespace sync_io
10085
10086} // namespace wuffs_aux
10087
10088// ---------------- Auxiliary - CBOR
10089
10090namespace wuffs_aux {
10091
10092struct DecodeCborResult {
10093 DecodeCborResult(std::string&& error_message0, uint64_t cursor_position0);
10094
10095 std::string error_message;
10096 uint64_t cursor_position;
10097};
10098
10099class DecodeCborCallbacks {
10100 public:
10101 virtual ~DecodeCborCallbacks();
10102
10103 // AppendXxx are called for leaf nodes: literals, numbers, strings, etc.
10104
10105 virtual std::string AppendNull() = 0;
10106 virtual std::string AppendUndefined() = 0;
10107 virtual std::string AppendBool(bool val) = 0;
10108 virtual std::string AppendF64(double val) = 0;
10109 virtual std::string AppendI64(int64_t val) = 0;
10110 virtual std::string AppendU64(uint64_t val) = 0;
10111 virtual std::string AppendByteString(std::string&& val) = 0;
10112 virtual std::string AppendTextString(std::string&& val) = 0;
10113 virtual std::string AppendMinus1MinusX(uint64_t val) = 0;
10114 virtual std::string AppendCborSimpleValue(uint8_t val) = 0;
10115 virtual std::string AppendCborTag(uint64_t val) = 0;
10116
10117 // Push and Pop are called for container nodes: CBOR arrays (lists) and CBOR
10118 // maps (dictionaries).
10119 //
10120 // The flags bits combine exactly one of:
10121 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE
10122 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST
10123 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT
10124 // and exactly one of:
10125 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE
10126 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST
10127 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT
10128
10129 virtual std::string Push(uint32_t flags) = 0;
10130 virtual std::string Pop(uint32_t flags) = 0;
10131
10132 // Done is always the last Callback method called by DecodeCbor, whether or
10133 // not parsing the input as CBOR encountered an error. Even when successful,
10134 // trailing data may remain in input and buffer.
10135 //
10136 // Do not keep a reference to buffer or buffer.data.ptr after Done returns,
10137 // as DecodeCbor may then de-allocate the backing array.
10138 //
10139 // The default Done implementation is a no-op.
10140 virtual void //
10141 Done(DecodeCborResult& result, sync_io::Input& input, IOBuffer& buffer);
10142};
10143
Nigel Taobf9dab32021-11-18 19:19:55 +110010144// The FooArgBar types add structure to Foo's optional arguments. They wrap
10145// inner representations for several reasons:
10146// - It provides a home for the DefaultValue static method, for Foo callers
10147// that want to override some but not all optional arguments.
10148// - It provides the "Bar" name at Foo call sites, which can help self-
10149// document Foo calls with many arguemnts.
10150// - It provides some type safety against accidentally transposing or omitting
10151// adjacent fundamentally-numeric-typed optional arguments.
10152
10153// DecodeCborArgQuirks wraps an optional argument to DecodeCbor.
10154struct DecodeCborArgQuirks {
10155 explicit DecodeCborArgQuirks(wuffs_base__slice_u32 repr0);
10156 explicit DecodeCborArgQuirks(uint32_t* ptr, size_t len);
10157
10158 // DefaultValue returns an empty slice.
10159 static DecodeCborArgQuirks DefaultValue();
10160
10161 wuffs_base__slice_u32 repr;
10162};
10163
Nigel Taoe360a532021-04-05 22:47:03 +100010164// DecodeCbor calls callbacks based on the CBOR-formatted data in input.
10165//
10166// On success, the returned error_message is empty and cursor_position counts
10167// the number of bytes consumed. On failure, error_message is non-empty and
10168// cursor_position is the location of the error. That error may be a content
10169// error (invalid CBOR) or an input error (e.g. network failure).
10170DecodeCborResult //
10171DecodeCbor(DecodeCborCallbacks& callbacks,
10172 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110010173 DecodeCborArgQuirks quirks = DecodeCborArgQuirks::DefaultValue());
Nigel Taoe360a532021-04-05 22:47:03 +100010174
10175} // namespace wuffs_aux
10176
10177// ---------------- Auxiliary - Image
10178
10179namespace wuffs_aux {
10180
10181struct DecodeImageResult {
10182 DecodeImageResult(MemOwner&& pixbuf_mem_owner0,
10183 wuffs_base__pixel_buffer pixbuf0,
10184 std::string&& error_message0);
10185 DecodeImageResult(std::string&& error_message0);
10186
10187 MemOwner pixbuf_mem_owner;
10188 wuffs_base__pixel_buffer pixbuf;
10189 std::string error_message;
10190};
10191
10192// DecodeImageCallbacks are the callbacks given to DecodeImage. They are always
10193// called in this order:
10194// 1. SelectDecoder
Nigel Taobf9dab32021-11-18 19:19:55 +110010195// 2. HandleMetadata
10196// 3. SelectPixfmt
10197// 4. AllocPixbuf
10198// 5. AllocWorkbuf
10199// 6. Done
Nigel Taoe360a532021-04-05 22:47:03 +100010200//
10201// It may return early - the third callback might not be invoked if the second
10202// one fails - but the final callback (Done) is always invoked.
10203class DecodeImageCallbacks {
10204 public:
10205 // AllocPixbufResult holds a memory allocation (the result of malloc or new,
10206 // a statically allocated pointer, etc), or an error message. The memory is
10207 // de-allocated when mem_owner goes out of scope and is destroyed.
10208 struct AllocPixbufResult {
10209 AllocPixbufResult(MemOwner&& mem_owner0, wuffs_base__pixel_buffer pixbuf0);
10210 AllocPixbufResult(std::string&& error_message0);
10211
10212 MemOwner mem_owner;
10213 wuffs_base__pixel_buffer pixbuf;
10214 std::string error_message;
10215 };
10216
10217 // AllocWorkbufResult holds a memory allocation (the result of malloc or new,
10218 // a statically allocated pointer, etc), or an error message. The memory is
10219 // de-allocated when mem_owner goes out of scope and is destroyed.
10220 struct AllocWorkbufResult {
10221 AllocWorkbufResult(MemOwner&& mem_owner0, wuffs_base__slice_u8 workbuf0);
10222 AllocWorkbufResult(std::string&& error_message0);
10223
10224 MemOwner mem_owner;
10225 wuffs_base__slice_u8 workbuf;
10226 std::string error_message;
10227 };
10228
10229 virtual ~DecodeImageCallbacks();
10230
10231 // SelectDecoder returns the image decoder for the input data's file format.
10232 // Returning a nullptr means failure (DecodeImage_UnsupportedImageFormat).
10233 //
10234 // Common formats will have a FourCC value in the range [1 ..= 0x7FFF_FFFF],
10235 // such as WUFFS_BASE__FOURCC__JPEG. A zero FourCC value means that the
10236 // caller is responsible for examining the opening bytes (a prefix) of the
10237 // input data. SelectDecoder implementations should not modify those bytes.
10238 //
10239 // SelectDecoder might be called more than once, since some image file
10240 // formats can wrap others. For example, a nominal BMP file can actually
10241 // contain a JPEG or a PNG.
10242 //
10243 // The default SelectDecoder accepts the FOURCC codes listed below. For
10244 // modular builds (i.e. when #define'ing WUFFS_CONFIG__MODULES), acceptance
10245 // of the ETC file format is optional (for each value of ETC) and depends on
10246 // the corresponding module to be enabled at compile time (i.e. #define'ing
10247 // WUFFS_CONFIG__MODULE__ETC).
10248 // - WUFFS_BASE__FOURCC__BMP
10249 // - WUFFS_BASE__FOURCC__GIF
10250 // - WUFFS_BASE__FOURCC__NIE
10251 // - WUFFS_BASE__FOURCC__PNG
10252 // - WUFFS_BASE__FOURCC__WBMP
10253 virtual wuffs_base__image_decoder::unique_ptr //
10254 SelectDecoder(uint32_t fourcc, wuffs_base__slice_u8 prefix);
10255
Nigel Taobf9dab32021-11-18 19:19:55 +110010256 // HandleMetadata acknowledges image metadata. minfo.flavor will be one of:
10257 // - WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH
10258 // - WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED
10259 // If it is ETC__METADATA_RAW_ETC then raw contains the metadata bytes. Those
10260 // bytes should not be retained beyond the the HandleMetadata call.
10261 //
10262 // minfo.metadata__fourcc() will typically match one of the
10263 // DecodeImageArgFlags bits. For example, if (REPORT_METADATA_CHRM |
10264 // REPORT_METADATA_GAMA) was passed to DecodeImage then the metadata FourCC
10265 // will be either WUFFS_BASE__FOURCC__CHRM or WUFFS_BASE__FOURCC__GAMA.
10266 //
10267 // It returns an error message, or an empty string on success.
10268 virtual std::string //
10269 HandleMetadata(const wuffs_base__more_information& minfo,
10270 wuffs_base__slice_u8 raw);
10271
Nigel Taoe360a532021-04-05 22:47:03 +100010272 // SelectPixfmt returns the destination pixel format for AllocPixbuf. It
10273 // should return wuffs_base__make_pixel_format(etc) called with one of:
10274 // - WUFFS_BASE__PIXEL_FORMAT__BGR_565
10275 // - WUFFS_BASE__PIXEL_FORMAT__BGR
10276 // - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL
10277 // - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE
10278 // - WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL
10279 // - WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL
10280 // - WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL
10281 // or return image_config.pixcfg.pixel_format(). The latter means to use the
10282 // image file's natural pixel format. For example, GIF images' natural pixel
10283 // format is an indexed one.
10284 //
10285 // Returning otherwise means failure (DecodeImage_UnsupportedPixelFormat).
10286 //
10287 // The default SelectPixfmt implementation returns
10288 // wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL) which
10289 // is 4 bytes per pixel (8 bits per channel × 4 channels).
10290 virtual wuffs_base__pixel_format //
10291 SelectPixfmt(const wuffs_base__image_config& image_config);
10292
10293 // AllocPixbuf allocates the pixel buffer.
10294 //
10295 // allow_uninitialized_memory will be true if a valid background_color was
10296 // passed to DecodeImage, since the pixel buffer's contents will be
10297 // overwritten with that color after AllocPixbuf returns.
10298 //
10299 // The default AllocPixbuf implementation allocates either uninitialized or
10300 // zeroed memory. Zeroed memory typically corresponds to filling with opaque
10301 // black or transparent black, depending on the pixel format.
10302 virtual AllocPixbufResult //
10303 AllocPixbuf(const wuffs_base__image_config& image_config,
10304 bool allow_uninitialized_memory);
10305
10306 // AllocWorkbuf allocates the work buffer. The allocated buffer's length
10307 // should be at least len_range.min_incl, but larger allocations (up to
10308 // len_range.max_incl) may have better performance (by using more memory).
10309 //
10310 // The default AllocWorkbuf implementation allocates len_range.max_incl bytes
10311 // of either uninitialized or zeroed memory.
10312 virtual AllocWorkbufResult //
10313 AllocWorkbuf(wuffs_base__range_ii_u64 len_range,
10314 bool allow_uninitialized_memory);
10315
10316 // Done is always the last Callback method called by DecodeImage, whether or
10317 // not parsing the input encountered an error. Even when successful, trailing
10318 // data may remain in input and buffer.
10319 //
10320 // The image_decoder is the one returned by SelectDecoder (if SelectDecoder
10321 // was successful), or a no-op unique_ptr otherwise. Like any unique_ptr,
10322 // ownership moves to the Done implementation.
10323 //
10324 // Do not keep a reference to buffer or buffer.data.ptr after Done returns,
10325 // as DecodeImage may then de-allocate the backing array.
10326 //
10327 // The default Done implementation is a no-op, other than running the
10328 // image_decoder unique_ptr destructor.
10329 virtual void //
10330 Done(DecodeImageResult& result,
10331 sync_io::Input& input,
10332 IOBuffer& buffer,
10333 wuffs_base__image_decoder::unique_ptr image_decoder);
10334};
10335
10336extern const char DecodeImage_BufferIsTooShort[];
10337extern const char DecodeImage_MaxInclDimensionExceeded[];
Nigel Taobf9dab32021-11-18 19:19:55 +110010338extern const char DecodeImage_MaxInclMetadataLengthExceeded[];
Nigel Taoe360a532021-04-05 22:47:03 +100010339extern const char DecodeImage_OutOfMemory[];
10340extern const char DecodeImage_UnexpectedEndOfFile[];
10341extern const char DecodeImage_UnsupportedImageFormat[];
Nigel Taobf9dab32021-11-18 19:19:55 +110010342extern const char DecodeImage_UnsupportedMetadata[];
Nigel Taoe360a532021-04-05 22:47:03 +100010343extern const char DecodeImage_UnsupportedPixelBlend[];
10344extern const char DecodeImage_UnsupportedPixelConfiguration[];
10345extern const char DecodeImage_UnsupportedPixelFormat[];
10346
Nigel Taobf9dab32021-11-18 19:19:55 +110010347// The FooArgBar types add structure to Foo's optional arguments. They wrap
10348// inner representations for several reasons:
10349// - It provides a home for the DefaultValue static method, for Foo callers
10350// that want to override some but not all optional arguments.
10351// - It provides the "Bar" name at Foo call sites, which can help self-
10352// document Foo calls with many arguemnts.
10353// - It provides some type safety against accidentally transposing or omitting
10354// adjacent fundamentally-numeric-typed optional arguments.
10355
10356// DecodeImageArgQuirks wraps an optional argument to DecodeImage.
10357struct DecodeImageArgQuirks {
10358 explicit DecodeImageArgQuirks(wuffs_base__slice_u32 repr0);
10359 explicit DecodeImageArgQuirks(uint32_t* ptr, size_t len);
10360
10361 // DefaultValue returns an empty slice.
10362 static DecodeImageArgQuirks DefaultValue();
10363
10364 wuffs_base__slice_u32 repr;
10365};
10366
10367// DecodeImageArgFlags wraps an optional argument to DecodeImage.
10368struct DecodeImageArgFlags {
10369 explicit DecodeImageArgFlags(uint64_t repr0);
10370
10371 // DefaultValue returns 0.
10372 static DecodeImageArgFlags DefaultValue();
10373
10374 // TODO: support all of the REPORT_METADATA_ETC flags, not just CHRM, GAMA,
10375 // ICCP, KVP, SRGB and XMP.
10376
10377 // Background Color.
10378 static constexpr uint64_t REPORT_METADATA_BGCL = 0x0001;
10379 // Primary Chromaticities and White Point.
10380 static constexpr uint64_t REPORT_METADATA_CHRM = 0x0002;
10381 // Exchangeable Image File Format.
10382 static constexpr uint64_t REPORT_METADATA_EXIF = 0x0004;
10383 // Gamma Correction.
10384 static constexpr uint64_t REPORT_METADATA_GAMA = 0x0008;
10385 // International Color Consortium Profile.
10386 static constexpr uint64_t REPORT_METADATA_ICCP = 0x0010;
10387 // Key-Value Pair.
10388 //
10389 // For PNG files, this includes iTXt, tEXt and zTXt chunks. In the
10390 // HandleMetadata callback, the raw argument contains UTF-8 strings.
10391 static constexpr uint64_t REPORT_METADATA_KVP = 0x0020;
10392 // Modification Time.
10393 static constexpr uint64_t REPORT_METADATA_MTIM = 0x0040;
10394 // Offset (2-Dimensional).
10395 static constexpr uint64_t REPORT_METADATA_OFS2 = 0x0080;
10396 // Physical Dimensions.
10397 static constexpr uint64_t REPORT_METADATA_PHYD = 0x0100;
10398 // Standard Red Green Blue (Rendering Intent).
10399 static constexpr uint64_t REPORT_METADATA_SRGB = 0x0200;
10400 // Extensible Metadata Platform.
10401 static constexpr uint64_t REPORT_METADATA_XMP = 0x0400;
10402
10403 uint64_t repr;
10404};
10405
10406// DecodeImageArgPixelBlend wraps an optional argument to DecodeImage.
10407struct DecodeImageArgPixelBlend {
10408 explicit DecodeImageArgPixelBlend(wuffs_base__pixel_blend repr0);
10409
10410 // DefaultValue returns WUFFS_BASE__PIXEL_BLEND__SRC.
10411 static DecodeImageArgPixelBlend DefaultValue();
10412
10413 wuffs_base__pixel_blend repr;
10414};
10415
10416// DecodeImageArgBackgroundColor wraps an optional argument to DecodeImage.
10417struct DecodeImageArgBackgroundColor {
10418 explicit DecodeImageArgBackgroundColor(
10419 wuffs_base__color_u32_argb_premul repr0);
10420
10421 // DefaultValue returns 1, an invalid wuffs_base__color_u32_argb_premul.
10422 static DecodeImageArgBackgroundColor DefaultValue();
10423
10424 wuffs_base__color_u32_argb_premul repr;
10425};
10426
10427// DecodeImageArgMaxInclDimension wraps an optional argument to DecodeImage.
10428struct DecodeImageArgMaxInclDimension {
10429 explicit DecodeImageArgMaxInclDimension(uint32_t repr0);
10430
10431 // DefaultValue returns 1048575 = 0x000F_FFFF, more than 1 million pixels.
10432 static DecodeImageArgMaxInclDimension DefaultValue();
10433
10434 uint32_t repr;
10435};
10436
10437// DecodeImageArgMaxInclMetadataLength wraps an optional argument to
10438// DecodeImage.
10439struct DecodeImageArgMaxInclMetadataLength {
10440 explicit DecodeImageArgMaxInclMetadataLength(uint64_t repr0);
10441
10442 // DefaultValue returns 16777215 = 0x00FF_FFFF, one less than 16 MiB.
10443 static DecodeImageArgMaxInclMetadataLength DefaultValue();
10444
10445 uint64_t repr;
10446};
10447
Nigel Taoe360a532021-04-05 22:47:03 +100010448// DecodeImage decodes the image data in input. A variety of image file formats
10449// can be decoded, depending on what callbacks.SelectDecoder returns.
10450//
10451// For animated formats, only the first frame is returned, since the API is
10452// simpler for synchronous I/O and having DecodeImage only return when
10453// completely done, but rendering animation often involves handling other
10454// events in between animation frames. To decode multiple frames of animated
10455// images, or for asynchronous I/O (e.g. when decoding an image streamed over
10456// the network), use Wuffs' lower level C API instead of its higher level,
10457// simplified C++ API (the wuffs_aux API).
10458//
10459// The DecodeImageResult's fields depend on whether decoding succeeded:
10460// - On total success, the error_message is empty and pixbuf.pixcfg.is_valid()
10461// is true.
10462// - On partial success (e.g. the input file was truncated but we are still
10463// able to decode some of the pixels), error_message is non-empty but
10464// pixbuf.pixcfg.is_valid() is still true. It is up to the caller whether to
10465// accept or reject partial success.
10466// - On failure, the error_message is non_empty and pixbuf.pixcfg.is_valid()
10467// is false.
10468//
10469// The callbacks allocate the pixel buffer memory and work buffer memory. On
10470// success, pixel buffer memory ownership is passed to the DecodeImage caller
10471// as the returned pixbuf_mem_owner. Regardless of success or failure, the work
10472// buffer memory is deleted.
10473//
10474// The pixel_blend (one of the constants listed below) determines how to
10475// composite the decoded image over the pixel buffer's original pixels (as
10476// returned by callbacks.AllocPixbuf):
10477// - WUFFS_BASE__PIXEL_BLEND__SRC
10478// - WUFFS_BASE__PIXEL_BLEND__SRC_OVER
10479//
10480// The background_color is used to fill the pixel buffer after
10481// callbacks.AllocPixbuf returns, if it is valid in the
10482// wuffs_base__color_u32_argb_premul__is_valid sense. The default value,
10483// 0x0000_0001, is not valid since its Blue channel value (0x01) is greater
10484// than its Alpha channel value (0x00). A valid background_color will typically
10485// be overwritten when pixel_blend is WUFFS_BASE__PIXEL_BLEND__SRC, but might
10486// still be visible on partial (not total) success or when pixel_blend is
10487// WUFFS_BASE__PIXEL_BLEND__SRC_OVER and the decoded image is not fully opaque.
10488//
10489// Decoding fails (with DecodeImage_MaxInclDimensionExceeded) if the image's
Nigel Taobf9dab32021-11-18 19:19:55 +110010490// width or height is greater than max_incl_dimension or if any opted-in (via
10491// flags bits) metadata is longer than max_incl_metadata_length.
Nigel Taoe360a532021-04-05 22:47:03 +100010492DecodeImageResult //
10493DecodeImage(DecodeImageCallbacks& callbacks,
10494 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110010495 DecodeImageArgQuirks quirks = DecodeImageArgQuirks::DefaultValue(),
10496 DecodeImageArgFlags flags = DecodeImageArgFlags::DefaultValue(),
10497 DecodeImageArgPixelBlend pixel_blend =
10498 DecodeImageArgPixelBlend::DefaultValue(),
10499 DecodeImageArgBackgroundColor background_color =
10500 DecodeImageArgBackgroundColor::DefaultValue(),
10501 DecodeImageArgMaxInclDimension max_incl_dimension =
10502 DecodeImageArgMaxInclDimension::DefaultValue(),
10503 DecodeImageArgMaxInclMetadataLength max_incl_metadata_length =
10504 DecodeImageArgMaxInclMetadataLength::DefaultValue());
Nigel Taoe360a532021-04-05 22:47:03 +100010505
10506} // namespace wuffs_aux
10507
10508// ---------------- Auxiliary - JSON
10509
10510namespace wuffs_aux {
10511
10512struct DecodeJsonResult {
10513 DecodeJsonResult(std::string&& error_message0, uint64_t cursor_position0);
10514
10515 std::string error_message;
10516 uint64_t cursor_position;
10517};
10518
10519class DecodeJsonCallbacks {
10520 public:
10521 virtual ~DecodeJsonCallbacks();
10522
10523 // AppendXxx are called for leaf nodes: literals, numbers and strings. For
10524 // strings, the Callbacks implementation is responsible for tracking map keys
10525 // versus other values.
10526
10527 virtual std::string AppendNull() = 0;
10528 virtual std::string AppendBool(bool val) = 0;
10529 virtual std::string AppendF64(double val) = 0;
10530 virtual std::string AppendI64(int64_t val) = 0;
10531 virtual std::string AppendTextString(std::string&& val) = 0;
10532
10533 // Push and Pop are called for container nodes: JSON arrays (lists) and JSON
10534 // objects (dictionaries).
10535 //
10536 // The flags bits combine exactly one of:
10537 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE
10538 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST
10539 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT
10540 // and exactly one of:
10541 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE
10542 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST
10543 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT
10544
10545 virtual std::string Push(uint32_t flags) = 0;
10546 virtual std::string Pop(uint32_t flags) = 0;
10547
10548 // Done is always the last Callback method called by DecodeJson, whether or
10549 // not parsing the input as JSON encountered an error. Even when successful,
10550 // trailing data may remain in input and buffer. See "Unintuitive JSON
10551 // Parsing" (https://nullprogram.com/blog/2019/12/28/) which discusses JSON
10552 // parsing and when it stops.
10553 //
10554 // Do not keep a reference to buffer or buffer.data.ptr after Done returns,
10555 // as DecodeJson may then de-allocate the backing array.
10556 //
10557 // The default Done implementation is a no-op.
10558 virtual void //
10559 Done(DecodeJsonResult& result, sync_io::Input& input, IOBuffer& buffer);
10560};
10561
10562extern const char DecodeJson_BadJsonPointer[];
10563extern const char DecodeJson_NoMatch[];
10564
Nigel Taobf9dab32021-11-18 19:19:55 +110010565// The FooArgBar types add structure to Foo's optional arguments. They wrap
10566// inner representations for several reasons:
10567// - It provides a home for the DefaultValue static method, for Foo callers
10568// that want to override some but not all optional arguments.
10569// - It provides the "Bar" name at Foo call sites, which can help self-
10570// document Foo calls with many arguemnts.
10571// - It provides some type safety against accidentally transposing or omitting
10572// adjacent fundamentally-numeric-typed optional arguments.
10573
10574// DecodeJsonArgQuirks wraps an optional argument to DecodeJson.
10575struct DecodeJsonArgQuirks {
10576 explicit DecodeJsonArgQuirks(wuffs_base__slice_u32 repr0);
10577 explicit DecodeJsonArgQuirks(uint32_t* ptr, size_t len);
10578
10579 // DefaultValue returns an empty slice.
10580 static DecodeJsonArgQuirks DefaultValue();
10581
10582 wuffs_base__slice_u32 repr;
10583};
10584
10585// DecodeJsonArgJsonPointer wraps an optional argument to DecodeJson.
10586struct DecodeJsonArgJsonPointer {
10587 explicit DecodeJsonArgJsonPointer(std::string repr0);
10588
10589 // DefaultValue returns an empty string.
10590 static DecodeJsonArgJsonPointer DefaultValue();
10591
10592 std::string repr;
10593};
10594
Nigel Taoe360a532021-04-05 22:47:03 +100010595// DecodeJson calls callbacks based on the JSON-formatted data in input.
10596//
10597// On success, the returned error_message is empty and cursor_position counts
10598// the number of bytes consumed. On failure, error_message is non-empty and
10599// cursor_position is the location of the error. That error may be a content
10600// error (invalid JSON) or an input error (e.g. network failure).
10601//
10602// json_pointer is a query in the JSON Pointer (RFC 6901) syntax. The callbacks
10603// run for the input's sub-node that matches the query. DecodeJson_NoMatch is
10604// returned if no matching sub-node was found. The empty query matches the
10605// input's root node, consistent with JSON Pointer semantics.
10606//
10607// The JSON Pointer implementation is greedy: duplicate keys are not rejected
10608// but only the first match for each '/'-separated fragment is followed.
10609DecodeJsonResult //
10610DecodeJson(DecodeJsonCallbacks& callbacks,
10611 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110010612 DecodeJsonArgQuirks quirks = DecodeJsonArgQuirks::DefaultValue(),
10613 DecodeJsonArgJsonPointer json_pointer =
10614 DecodeJsonArgJsonPointer::DefaultValue());
Nigel Taoe360a532021-04-05 22:47:03 +100010615
10616} // namespace wuffs_aux
10617
10618#endif // defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
10619
10620// ‼ WUFFS C HEADER ENDS HERE.
10621#ifdef WUFFS_IMPLEMENTATION
10622
10623#ifdef __cplusplus
10624extern "C" {
10625#endif
10626
10627// ---------------- Fundamentals
10628
10629// WUFFS_BASE__MAGIC is a magic number to check that initializers are called.
10630// It's not foolproof, given C doesn't automatically zero memory before use,
10631// but it should catch 99.99% of cases.
10632//
10633// Its (non-zero) value is arbitrary, based on md5sum("wuffs").
10634#define WUFFS_BASE__MAGIC ((uint32_t)0x3CCB6C71)
10635
10636// WUFFS_BASE__DISABLED is a magic number to indicate that a non-recoverable
10637// error was previously encountered.
10638//
10639// Its (non-zero) value is arbitrary, based on md5sum("disabled").
10640#define WUFFS_BASE__DISABLED ((uint32_t)0x075AE3D2)
10641
Nigel Taoe360a532021-04-05 22:47:03 +100010642// Use switch cases for coroutine suspension points, similar to the technique
10643// in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
10644//
Nigel Tao5aae6d12021-07-05 21:53:02 +100010645// The implicit fallthrough is intentional.
10646//
Nigel Taoe360a532021-04-05 22:47:03 +100010647// We use trivial macros instead of an explicit assignment and case statement
10648// so that clang-format doesn't get confused by the unusual "case"s.
10649#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0 case 0:;
10650#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT(n) \
10651 coro_susp_point = n; \
Nigel Taoe360a532021-04-05 22:47:03 +100010652 case n:;
10653
10654#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \
10655 if (!status.repr) { \
10656 goto ok; \
10657 } else if (*status.repr != '$') { \
10658 goto exit; \
10659 } \
10660 coro_susp_point = n; \
10661 goto suspend; \
10662 case n:;
10663
Nigel Taobf9dab32021-11-18 19:19:55 +110010664// The "defined(__clang__)" isn't redundant. While vanilla clang defines
10665// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not.
10666#if defined(__GNUC__) || defined(__clang__)
Nigel Taoe360a532021-04-05 22:47:03 +100010667#define WUFFS_BASE__LIKELY(expr) (__builtin_expect(!!(expr), 1))
10668#define WUFFS_BASE__UNLIKELY(expr) (__builtin_expect(!!(expr), 0))
10669#else
10670#define WUFFS_BASE__LIKELY(expr) (expr)
10671#define WUFFS_BASE__UNLIKELY(expr) (expr)
10672#endif
10673
10674// --------
10675
10676static inline wuffs_base__empty_struct //
10677wuffs_base__ignore_status(wuffs_base__status z) {
10678 return wuffs_base__make_empty_struct();
10679}
10680
10681static inline wuffs_base__status //
10682wuffs_base__status__ensure_not_a_suspension(wuffs_base__status z) {
10683 if (z.repr && (*z.repr == '$')) {
10684 z.repr = wuffs_base__error__cannot_return_a_suspension;
10685 }
10686 return z;
10687}
10688
10689// --------
10690
10691// wuffs_base__iterate_total_advance returns the exclusive pointer-offset at
10692// which iteration should stop. The overall slice has length total_len, each
10693// iteration's sub-slice has length iter_len and are placed iter_advance apart.
10694//
10695// The iter_advance may not be larger than iter_len. The iter_advance may be
10696// smaller than iter_len, in which case the sub-slices will overlap.
10697//
10698// The return value r satisfies ((0 <= r) && (r <= total_len)).
10699//
10700// For example, if total_len = 15, iter_len = 5 and iter_advance = 3, there are
10701// four iterations at offsets 0, 3, 6 and 9. This function returns 12.
10702//
10703// 0123456789012345
10704// [....]
10705// [....]
10706// [....]
10707// [....]
10708// $
10709// 0123456789012345
10710//
10711// For example, if total_len = 15, iter_len = 5 and iter_advance = 5, there are
10712// three iterations at offsets 0, 5 and 10. This function returns 15.
10713//
10714// 0123456789012345
10715// [....]
10716// [....]
10717// [....]
10718// $
10719// 0123456789012345
10720static inline size_t //
10721wuffs_base__iterate_total_advance(size_t total_len,
10722 size_t iter_len,
10723 size_t iter_advance) {
10724 if (total_len >= iter_len) {
10725 size_t n = total_len - iter_len;
10726 return ((n / iter_advance) * iter_advance) + iter_advance;
10727 }
10728 return 0;
10729}
10730
10731// ---------------- Numeric Types
10732
10733extern const uint8_t wuffs_base__low_bits_mask__u8[8];
10734extern const uint16_t wuffs_base__low_bits_mask__u16[16];
10735extern const uint32_t wuffs_base__low_bits_mask__u32[32];
10736extern const uint64_t wuffs_base__low_bits_mask__u64[64];
10737
10738#define WUFFS_BASE__LOW_BITS_MASK__U8(n) (wuffs_base__low_bits_mask__u8[n])
10739#define WUFFS_BASE__LOW_BITS_MASK__U16(n) (wuffs_base__low_bits_mask__u16[n])
10740#define WUFFS_BASE__LOW_BITS_MASK__U32(n) (wuffs_base__low_bits_mask__u32[n])
10741#define WUFFS_BASE__LOW_BITS_MASK__U64(n) (wuffs_base__low_bits_mask__u64[n])
10742
10743// --------
10744
10745static inline void //
10746wuffs_base__u8__sat_add_indirect(uint8_t* x, uint8_t y) {
10747 *x = wuffs_base__u8__sat_add(*x, y);
10748}
10749
10750static inline void //
10751wuffs_base__u8__sat_sub_indirect(uint8_t* x, uint8_t y) {
10752 *x = wuffs_base__u8__sat_sub(*x, y);
10753}
10754
10755static inline void //
10756wuffs_base__u16__sat_add_indirect(uint16_t* x, uint16_t y) {
10757 *x = wuffs_base__u16__sat_add(*x, y);
10758}
10759
10760static inline void //
10761wuffs_base__u16__sat_sub_indirect(uint16_t* x, uint16_t y) {
10762 *x = wuffs_base__u16__sat_sub(*x, y);
10763}
10764
10765static inline void //
10766wuffs_base__u32__sat_add_indirect(uint32_t* x, uint32_t y) {
10767 *x = wuffs_base__u32__sat_add(*x, y);
10768}
10769
10770static inline void //
10771wuffs_base__u32__sat_sub_indirect(uint32_t* x, uint32_t y) {
10772 *x = wuffs_base__u32__sat_sub(*x, y);
10773}
10774
10775static inline void //
10776wuffs_base__u64__sat_add_indirect(uint64_t* x, uint64_t y) {
10777 *x = wuffs_base__u64__sat_add(*x, y);
10778}
10779
10780static inline void //
10781wuffs_base__u64__sat_sub_indirect(uint64_t* x, uint64_t y) {
10782 *x = wuffs_base__u64__sat_sub(*x, y);
10783}
10784
10785// ---------------- Slices and Tables
10786
10787// wuffs_base__slice_u8__prefix returns up to the first up_to bytes of s.
10788static inline wuffs_base__slice_u8 //
10789wuffs_base__slice_u8__prefix(wuffs_base__slice_u8 s, uint64_t up_to) {
10790 if (((uint64_t)(s.len)) > up_to) {
10791 s.len = ((size_t)up_to);
10792 }
10793 return s;
10794}
10795
10796// wuffs_base__slice_u8__suffix returns up to the last up_to bytes of s.
10797static inline wuffs_base__slice_u8 //
10798wuffs_base__slice_u8__suffix(wuffs_base__slice_u8 s, uint64_t up_to) {
10799 if (((uint64_t)(s.len)) > up_to) {
10800 s.ptr += ((uint64_t)(s.len)) - up_to;
10801 s.len = ((size_t)up_to);
10802 }
10803 return s;
10804}
10805
10806// wuffs_base__slice_u8__copy_from_slice calls memmove(dst.ptr, src.ptr, len)
10807// where len is the minimum of dst.len and src.len.
10808//
10809// Passing a wuffs_base__slice_u8 with all fields NULL or zero (a valid, empty
10810// slice) is valid and results in a no-op.
10811static inline uint64_t //
10812wuffs_base__slice_u8__copy_from_slice(wuffs_base__slice_u8 dst,
10813 wuffs_base__slice_u8 src) {
10814 size_t len = dst.len < src.len ? dst.len : src.len;
10815 if (len > 0) {
10816 memmove(dst.ptr, src.ptr, len);
10817 }
10818 return len;
10819}
10820
10821// --------
10822
10823static inline wuffs_base__slice_u8 //
Nigel Taobf9dab32021-11-18 19:19:55 +110010824wuffs_base__table_u8__row_u32(wuffs_base__table_u8 t, uint32_t y) {
Nigel Taoe360a532021-04-05 22:47:03 +100010825 if (y < t.height) {
10826 return wuffs_base__make_slice_u8(t.ptr + (t.stride * y), t.width);
10827 }
10828 return wuffs_base__make_slice_u8(NULL, 0);
10829}
10830
10831// ---------------- Slices and Tables (Utility)
10832
10833#define wuffs_base__utility__empty_slice_u8 wuffs_base__empty_slice_u8
10834
10835// ---------------- Ranges and Rects
10836
10837static inline uint32_t //
10838wuffs_base__range_ii_u32__get_min_incl(const wuffs_base__range_ii_u32* r) {
10839 return r->min_incl;
10840}
10841
10842static inline uint32_t //
10843wuffs_base__range_ii_u32__get_max_incl(const wuffs_base__range_ii_u32* r) {
10844 return r->max_incl;
10845}
10846
10847static inline uint32_t //
10848wuffs_base__range_ie_u32__get_min_incl(const wuffs_base__range_ie_u32* r) {
10849 return r->min_incl;
10850}
10851
10852static inline uint32_t //
10853wuffs_base__range_ie_u32__get_max_excl(const wuffs_base__range_ie_u32* r) {
10854 return r->max_excl;
10855}
10856
10857static inline uint64_t //
10858wuffs_base__range_ii_u64__get_min_incl(const wuffs_base__range_ii_u64* r) {
10859 return r->min_incl;
10860}
10861
10862static inline uint64_t //
10863wuffs_base__range_ii_u64__get_max_incl(const wuffs_base__range_ii_u64* r) {
10864 return r->max_incl;
10865}
10866
10867static inline uint64_t //
10868wuffs_base__range_ie_u64__get_min_incl(const wuffs_base__range_ie_u64* r) {
10869 return r->min_incl;
10870}
10871
10872static inline uint64_t //
10873wuffs_base__range_ie_u64__get_max_excl(const wuffs_base__range_ie_u64* r) {
10874 return r->max_excl;
10875}
10876
10877// ---------------- Ranges and Rects (Utility)
10878
10879#define wuffs_base__utility__empty_range_ii_u32 wuffs_base__empty_range_ii_u32
10880#define wuffs_base__utility__empty_range_ie_u32 wuffs_base__empty_range_ie_u32
10881#define wuffs_base__utility__empty_range_ii_u64 wuffs_base__empty_range_ii_u64
10882#define wuffs_base__utility__empty_range_ie_u64 wuffs_base__empty_range_ie_u64
10883#define wuffs_base__utility__empty_rect_ii_u32 wuffs_base__empty_rect_ii_u32
10884#define wuffs_base__utility__empty_rect_ie_u32 wuffs_base__empty_rect_ie_u32
10885#define wuffs_base__utility__make_range_ii_u32 wuffs_base__make_range_ii_u32
10886#define wuffs_base__utility__make_range_ie_u32 wuffs_base__make_range_ie_u32
10887#define wuffs_base__utility__make_range_ii_u64 wuffs_base__make_range_ii_u64
10888#define wuffs_base__utility__make_range_ie_u64 wuffs_base__make_range_ie_u64
10889#define wuffs_base__utility__make_rect_ii_u32 wuffs_base__make_rect_ii_u32
10890#define wuffs_base__utility__make_rect_ie_u32 wuffs_base__make_rect_ie_u32
10891
10892// ---------------- I/O
10893
10894static inline uint64_t //
10895wuffs_base__io__count_since(uint64_t mark, uint64_t index) {
10896 if (index >= mark) {
10897 return index - mark;
10898 }
10899 return 0;
10900}
10901
10902// TODO: drop the "const" in "const uint8_t* ptr". Some though required about
10903// the base.io_reader.since method returning a mutable "slice base.u8".
10904#if defined(__GNUC__)
10905#pragma GCC diagnostic push
10906#pragma GCC diagnostic ignored "-Wcast-qual"
10907#endif
10908static inline wuffs_base__slice_u8 //
10909wuffs_base__io__since(uint64_t mark, uint64_t index, const uint8_t* ptr) {
10910 if (index >= mark) {
10911 return wuffs_base__make_slice_u8(((uint8_t*)ptr) + mark,
10912 ((size_t)(index - mark)));
10913 }
10914 return wuffs_base__make_slice_u8(NULL, 0);
10915}
10916#if defined(__GNUC__)
10917#pragma GCC diagnostic pop
10918#endif
10919
10920// --------
10921
10922static inline void //
10923wuffs_base__io_reader__limit(const uint8_t** ptr_io2_r,
10924 const uint8_t* iop_r,
10925 uint64_t limit) {
10926 if (((uint64_t)(*ptr_io2_r - iop_r)) > limit) {
10927 *ptr_io2_r = iop_r + limit;
10928 }
10929}
10930
10931static inline uint32_t //
10932wuffs_base__io_reader__limited_copy_u32_to_slice(const uint8_t** ptr_iop_r,
10933 const uint8_t* io2_r,
10934 uint32_t length,
10935 wuffs_base__slice_u8 dst) {
10936 const uint8_t* iop_r = *ptr_iop_r;
10937 size_t n = dst.len;
10938 if (n > length) {
10939 n = length;
10940 }
10941 if (n > ((size_t)(io2_r - iop_r))) {
10942 n = (size_t)(io2_r - iop_r);
10943 }
10944 if (n > 0) {
10945 memmove(dst.ptr, iop_r, n);
10946 *ptr_iop_r += n;
10947 }
10948 return (uint32_t)(n);
10949}
10950
10951// wuffs_base__io_reader__match7 returns whether the io_reader's upcoming bytes
10952// start with the given prefix (up to 7 bytes long). It is peek-like, not
10953// read-like, in that there are no side-effects.
10954//
10955// The low 3 bits of a hold the prefix length, n.
10956//
10957// The high 56 bits of a hold the prefix itself, in little-endian order. The
10958// first prefix byte is in bits 8..=15, the second prefix byte is in bits
10959// 16..=23, etc. The high (8 * (7 - n)) bits are ignored.
10960//
10961// There are three possible return values:
10962// - 0 means success.
10963// - 1 means inconclusive, equivalent to "$short read".
10964// - 2 means failure.
10965static inline uint32_t //
10966wuffs_base__io_reader__match7(const uint8_t* iop_r,
10967 const uint8_t* io2_r,
10968 wuffs_base__io_buffer* r,
10969 uint64_t a) {
10970 uint32_t n = a & 7;
10971 a >>= 8;
10972 if ((io2_r - iop_r) >= 8) {
10973 uint64_t x = wuffs_base__peek_u64le__no_bounds_check(iop_r);
10974 uint32_t shift = 8 * (8 - n);
10975 return ((a << shift) == (x << shift)) ? 0 : 2;
10976 }
10977 for (; n > 0; n--) {
10978 if (iop_r >= io2_r) {
10979 return (r && r->meta.closed) ? 2 : 1;
10980 } else if (*iop_r != ((uint8_t)(a))) {
10981 return 2;
10982 }
10983 iop_r++;
10984 a >>= 8;
10985 }
10986 return 0;
10987}
10988
10989static inline wuffs_base__io_buffer* //
10990wuffs_base__io_reader__set(wuffs_base__io_buffer* b,
10991 const uint8_t** ptr_iop_r,
10992 const uint8_t** ptr_io0_r,
10993 const uint8_t** ptr_io1_r,
10994 const uint8_t** ptr_io2_r,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100010995 wuffs_base__slice_u8 data,
10996 uint64_t history_position) {
Nigel Taoe360a532021-04-05 22:47:03 +100010997 b->data = data;
10998 b->meta.wi = data.len;
10999 b->meta.ri = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100011000 b->meta.pos = history_position;
Nigel Taoe360a532021-04-05 22:47:03 +100011001 b->meta.closed = false;
11002
11003 *ptr_iop_r = data.ptr;
11004 *ptr_io0_r = data.ptr;
11005 *ptr_io1_r = data.ptr;
11006 *ptr_io2_r = data.ptr + data.len;
11007
11008 return b;
11009}
11010
11011// --------
11012
11013static inline uint64_t //
11014wuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w,
11015 uint8_t* io2_w,
11016 wuffs_base__slice_u8 src) {
11017 uint8_t* iop_w = *ptr_iop_w;
11018 size_t n = src.len;
11019 if (n > ((size_t)(io2_w - iop_w))) {
11020 n = (size_t)(io2_w - iop_w);
11021 }
11022 if (n > 0) {
11023 memmove(iop_w, src.ptr, n);
11024 *ptr_iop_w += n;
11025 }
11026 return (uint64_t)(n);
11027}
11028
11029static inline void //
11030wuffs_base__io_writer__limit(uint8_t** ptr_io2_w,
11031 uint8_t* iop_w,
11032 uint64_t limit) {
11033 if (((uint64_t)(*ptr_io2_w - iop_w)) > limit) {
11034 *ptr_io2_w = iop_w + limit;
11035 }
11036}
11037
11038static inline uint32_t //
11039wuffs_base__io_writer__limited_copy_u32_from_history(uint8_t** ptr_iop_w,
11040 uint8_t* io1_w,
11041 uint8_t* io2_w,
11042 uint32_t length,
11043 uint32_t distance) {
11044 if (!distance) {
11045 return 0;
11046 }
11047 uint8_t* p = *ptr_iop_w;
11048 if ((size_t)(p - io1_w) < (size_t)(distance)) {
11049 return 0;
11050 }
11051 uint8_t* q = p - distance;
11052 size_t n = (size_t)(io2_w - p);
11053 if ((size_t)(length) > n) {
11054 length = (uint32_t)(n);
11055 } else {
11056 n = (size_t)(length);
11057 }
11058 // TODO: unrolling by 3 seems best for the std/deflate benchmarks, but that
11059 // is mostly because 3 is the minimum length for the deflate format. This
11060 // function implementation shouldn't overfit to that one format. Perhaps the
11061 // limited_copy_u32_from_history Wuffs method should also take an unroll hint
11062 // argument, and the cgen can look if that argument is the constant
11063 // expression '3'.
11064 //
11065 // See also wuffs_base__io_writer__limited_copy_u32_from_history_fast below.
11066 for (; n >= 3; n -= 3) {
11067 *p++ = *q++;
11068 *p++ = *q++;
11069 *p++ = *q++;
11070 }
11071 for (; n; n--) {
11072 *p++ = *q++;
11073 }
11074 *ptr_iop_w = p;
11075 return length;
11076}
11077
11078// wuffs_base__io_writer__limited_copy_u32_from_history_fast is like the
11079// wuffs_base__io_writer__limited_copy_u32_from_history function above, but has
11080// stronger pre-conditions.
11081//
11082// The caller needs to prove that:
11083// - length <= (io2_w - *ptr_iop_w)
11084// - distance >= 1
11085// - distance <= (*ptr_iop_w - io1_w)
11086static inline uint32_t //
11087wuffs_base__io_writer__limited_copy_u32_from_history_fast(uint8_t** ptr_iop_w,
11088 uint8_t* io1_w,
11089 uint8_t* io2_w,
11090 uint32_t length,
11091 uint32_t distance) {
11092 uint8_t* p = *ptr_iop_w;
11093 uint8_t* q = p - distance;
11094 uint32_t n = length;
11095 for (; n >= 3; n -= 3) {
11096 *p++ = *q++;
11097 *p++ = *q++;
11098 *p++ = *q++;
11099 }
11100 for (; n; n--) {
11101 *p++ = *q++;
11102 }
11103 *ptr_iop_w = p;
11104 return length;
11105}
11106
Nigel Tao5571bfe2021-06-24 22:44:29 +100011107// wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast
11108// copies the previous byte (the one immediately before *ptr_iop_w), copying 8
11109// byte chunks at a time. Each chunk contains 8 repetitions of the same byte.
11110//
11111// In terms of number of bytes copied, length is rounded up to a multiple of 8.
11112// As a special case, a zero length rounds up to 8 (even though 0 is already a
11113// multiple of 8), since there is always at least one 8 byte chunk copied.
11114//
11115// In terms of advancing *ptr_iop_w, length is not rounded up.
11116//
11117// The caller needs to prove that:
11118// - (length + 8) <= (io2_w - *ptr_iop_w)
11119// - distance == 1
11120// - distance <= (*ptr_iop_w - io1_w)
11121static inline uint32_t //
11122wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast(
11123 uint8_t** ptr_iop_w,
11124 uint8_t* io1_w,
11125 uint8_t* io2_w,
11126 uint32_t length,
11127 uint32_t distance) {
11128 uint8_t* p = *ptr_iop_w;
11129 uint64_t x = p[-1];
11130 x |= x << 8;
11131 x |= x << 16;
11132 x |= x << 32;
11133 uint32_t n = length;
11134 while (1) {
11135 wuffs_base__poke_u64le__no_bounds_check(p, x);
11136 if (n <= 8) {
11137 p += n;
11138 break;
11139 }
11140 p += 8;
11141 n -= 8;
11142 }
11143 *ptr_iop_w = p;
11144 return length;
11145}
11146
Nigel Taoe360a532021-04-05 22:47:03 +100011147// wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast is
11148// like the wuffs_base__io_writer__limited_copy_u32_from_history_fast function
11149// above, but copies 8 byte chunks at a time.
11150//
11151// In terms of number of bytes copied, length is rounded up to a multiple of 8.
11152// As a special case, a zero length rounds up to 8 (even though 0 is already a
11153// multiple of 8), since there is always at least one 8 byte chunk copied.
11154//
11155// In terms of advancing *ptr_iop_w, length is not rounded up.
11156//
11157// The caller needs to prove that:
11158// - (length + 8) <= (io2_w - *ptr_iop_w)
11159// - distance >= 8
11160// - distance <= (*ptr_iop_w - io1_w)
11161static inline uint32_t //
11162wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast(
11163 uint8_t** ptr_iop_w,
11164 uint8_t* io1_w,
11165 uint8_t* io2_w,
11166 uint32_t length,
11167 uint32_t distance) {
11168 uint8_t* p = *ptr_iop_w;
11169 uint8_t* q = p - distance;
11170 uint32_t n = length;
11171 while (1) {
11172 memcpy(p, q, 8);
11173 if (n <= 8) {
11174 p += n;
11175 break;
11176 }
11177 p += 8;
11178 q += 8;
11179 n -= 8;
11180 }
11181 *ptr_iop_w = p;
11182 return length;
11183}
11184
11185static inline uint32_t //
11186wuffs_base__io_writer__limited_copy_u32_from_reader(uint8_t** ptr_iop_w,
11187 uint8_t* io2_w,
11188 uint32_t length,
11189 const uint8_t** ptr_iop_r,
11190 const uint8_t* io2_r) {
11191 uint8_t* iop_w = *ptr_iop_w;
11192 size_t n = length;
11193 if (n > ((size_t)(io2_w - iop_w))) {
11194 n = (size_t)(io2_w - iop_w);
11195 }
11196 const uint8_t* iop_r = *ptr_iop_r;
11197 if (n > ((size_t)(io2_r - iop_r))) {
11198 n = (size_t)(io2_r - iop_r);
11199 }
11200 if (n > 0) {
11201 memmove(iop_w, iop_r, n);
11202 *ptr_iop_w += n;
11203 *ptr_iop_r += n;
11204 }
11205 return (uint32_t)(n);
11206}
11207
11208static inline uint32_t //
11209wuffs_base__io_writer__limited_copy_u32_from_slice(uint8_t** ptr_iop_w,
11210 uint8_t* io2_w,
11211 uint32_t length,
11212 wuffs_base__slice_u8 src) {
11213 uint8_t* iop_w = *ptr_iop_w;
11214 size_t n = src.len;
11215 if (n > length) {
11216 n = length;
11217 }
11218 if (n > ((size_t)(io2_w - iop_w))) {
11219 n = (size_t)(io2_w - iop_w);
11220 }
11221 if (n > 0) {
11222 memmove(iop_w, src.ptr, n);
11223 *ptr_iop_w += n;
11224 }
11225 return (uint32_t)(n);
11226}
11227
11228static inline wuffs_base__io_buffer* //
11229wuffs_base__io_writer__set(wuffs_base__io_buffer* b,
11230 uint8_t** ptr_iop_w,
11231 uint8_t** ptr_io0_w,
11232 uint8_t** ptr_io1_w,
11233 uint8_t** ptr_io2_w,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100011234 wuffs_base__slice_u8 data,
11235 uint64_t history_position) {
Nigel Taoe360a532021-04-05 22:47:03 +100011236 b->data = data;
11237 b->meta.wi = 0;
11238 b->meta.ri = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100011239 b->meta.pos = history_position;
Nigel Taoe360a532021-04-05 22:47:03 +100011240 b->meta.closed = false;
11241
11242 *ptr_iop_w = data.ptr;
11243 *ptr_io0_w = data.ptr;
11244 *ptr_io1_w = data.ptr;
11245 *ptr_io2_w = data.ptr + data.len;
11246
11247 return b;
11248}
11249
11250// ---------------- I/O (Utility)
11251
11252#define wuffs_base__utility__empty_io_reader wuffs_base__empty_io_reader
11253#define wuffs_base__utility__empty_io_writer wuffs_base__empty_io_writer
11254
11255// ---------------- Tokens
11256
11257// ---------------- Tokens (Utility)
11258
11259// ---------------- Memory Allocation
11260
11261// ---------------- Images
11262
11263WUFFS_BASE__MAYBE_STATIC uint64_t //
11264wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
11265 const wuffs_base__pixel_swizzler* p,
11266 uint32_t up_to_num_pixels,
11267 wuffs_base__slice_u8 dst,
11268 wuffs_base__slice_u8 dst_palette,
11269 const uint8_t** ptr_iop_r,
11270 const uint8_t* io2_r);
11271
11272WUFFS_BASE__MAYBE_STATIC uint64_t //
11273wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
11274 const wuffs_base__pixel_swizzler* p,
11275 wuffs_base__slice_u8 dst,
11276 wuffs_base__slice_u8 dst_palette,
11277 const uint8_t** ptr_iop_r,
11278 const uint8_t* io2_r);
11279
11280WUFFS_BASE__MAYBE_STATIC uint64_t //
11281wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(
11282 const wuffs_base__pixel_swizzler* p,
11283 wuffs_base__slice_u8 dst,
11284 wuffs_base__slice_u8 dst_palette,
11285 uint64_t num_pixels);
11286
11287// ---------------- Images (Utility)
11288
11289#define wuffs_base__utility__make_pixel_format wuffs_base__make_pixel_format
11290
11291// ---------------- String Conversions
11292
11293// ---------------- Unicode and UTF-8
11294
11295// ----------------
11296
11297#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
11298 defined(WUFFS_CONFIG__MODULE__BASE__CORE)
11299
11300const uint8_t wuffs_base__low_bits_mask__u8[8] = {
11301 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F,
11302};
11303
11304const uint16_t wuffs_base__low_bits_mask__u16[16] = {
11305 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F,
11306 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF,
11307};
11308
11309const uint32_t wuffs_base__low_bits_mask__u32[32] = {
11310 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F,
11311 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
11312 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF,
11313 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
11314 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF,
11315 0x3FFFFFFF, 0x7FFFFFFF,
11316};
11317
11318const uint64_t wuffs_base__low_bits_mask__u64[64] = {
11319 0x0000000000000000, 0x0000000000000001, 0x0000000000000003,
11320 0x0000000000000007, 0x000000000000000F, 0x000000000000001F,
11321 0x000000000000003F, 0x000000000000007F, 0x00000000000000FF,
11322 0x00000000000001FF, 0x00000000000003FF, 0x00000000000007FF,
11323 0x0000000000000FFF, 0x0000000000001FFF, 0x0000000000003FFF,
11324 0x0000000000007FFF, 0x000000000000FFFF, 0x000000000001FFFF,
11325 0x000000000003FFFF, 0x000000000007FFFF, 0x00000000000FFFFF,
11326 0x00000000001FFFFF, 0x00000000003FFFFF, 0x00000000007FFFFF,
11327 0x0000000000FFFFFF, 0x0000000001FFFFFF, 0x0000000003FFFFFF,
11328 0x0000000007FFFFFF, 0x000000000FFFFFFF, 0x000000001FFFFFFF,
11329 0x000000003FFFFFFF, 0x000000007FFFFFFF, 0x00000000FFFFFFFF,
11330 0x00000001FFFFFFFF, 0x00000003FFFFFFFF, 0x00000007FFFFFFFF,
11331 0x0000000FFFFFFFFF, 0x0000001FFFFFFFFF, 0x0000003FFFFFFFFF,
11332 0x0000007FFFFFFFFF, 0x000000FFFFFFFFFF, 0x000001FFFFFFFFFF,
11333 0x000003FFFFFFFFFF, 0x000007FFFFFFFFFF, 0x00000FFFFFFFFFFF,
11334 0x00001FFFFFFFFFFF, 0x00003FFFFFFFFFFF, 0x00007FFFFFFFFFFF,
11335 0x0000FFFFFFFFFFFF, 0x0001FFFFFFFFFFFF, 0x0003FFFFFFFFFFFF,
11336 0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x001FFFFFFFFFFFFF,
11337 0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF,
11338 0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF,
11339 0x0FFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF,
11340 0x7FFFFFFFFFFFFFFF,
11341};
11342
11343const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {
11344 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
11345 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,
11346};
11347
11348const char wuffs_base__note__i_o_redirect[] = "@base: I/O redirect";
11349const char wuffs_base__note__end_of_data[] = "@base: end of data";
11350const char wuffs_base__note__metadata_reported[] = "@base: metadata reported";
11351const char wuffs_base__suspension__even_more_information[] = "$base: even more information";
11352const char wuffs_base__suspension__mispositioned_read[] = "$base: mispositioned read";
11353const char wuffs_base__suspension__mispositioned_write[] = "$base: mispositioned write";
11354const char wuffs_base__suspension__short_read[] = "$base: short read";
11355const char wuffs_base__suspension__short_write[] = "$base: short write";
11356const char wuffs_base__error__bad_i_o_position[] = "#base: bad I/O position";
11357const char wuffs_base__error__bad_argument_length_too_short[] = "#base: bad argument (length too short)";
11358const char wuffs_base__error__bad_argument[] = "#base: bad argument";
11359const char wuffs_base__error__bad_call_sequence[] = "#base: bad call sequence";
11360const char wuffs_base__error__bad_data[] = "#base: bad data";
11361const char wuffs_base__error__bad_receiver[] = "#base: bad receiver";
11362const char wuffs_base__error__bad_restart[] = "#base: bad restart";
11363const char wuffs_base__error__bad_sizeof_receiver[] = "#base: bad sizeof receiver";
11364const char wuffs_base__error__bad_vtable[] = "#base: bad vtable";
11365const char wuffs_base__error__bad_workbuf_length[] = "#base: bad workbuf length";
11366const char wuffs_base__error__bad_wuffs_version[] = "#base: bad wuffs version";
11367const char wuffs_base__error__cannot_return_a_suspension[] = "#base: cannot return a suspension";
11368const char wuffs_base__error__disabled_by_previous_error[] = "#base: disabled by previous error";
11369const char wuffs_base__error__initialize_falsely_claimed_already_zeroed[] = "#base: initialize falsely claimed already zeroed";
11370const char wuffs_base__error__initialize_not_called[] = "#base: initialize not called";
11371const char wuffs_base__error__interleaved_coroutine_calls[] = "#base: interleaved coroutine calls";
11372const char wuffs_base__error__no_more_information[] = "#base: no more information";
11373const char wuffs_base__error__not_enough_data[] = "#base: not enough data";
11374const char wuffs_base__error__out_of_bounds[] = "#base: out of bounds";
11375const char wuffs_base__error__unsupported_method[] = "#base: unsupported method";
11376const char wuffs_base__error__unsupported_option[] = "#base: unsupported option";
11377const char wuffs_base__error__unsupported_pixel_swizzler_option[] = "#base: unsupported pixel swizzler option";
11378const char wuffs_base__error__too_much_data[] = "#base: too much data";
11379
11380const char wuffs_base__hasher_u32__vtable_name[] = "{vtable}wuffs_base__hasher_u32";
11381const char wuffs_base__image_decoder__vtable_name[] = "{vtable}wuffs_base__image_decoder";
11382const char wuffs_base__io_transformer__vtable_name[] = "{vtable}wuffs_base__io_transformer";
11383const char wuffs_base__token_decoder__vtable_name[] = "{vtable}wuffs_base__token_decoder";
11384
11385#endif // !defined(WUFFS_CONFIG__MODULES) ||
11386 // defined(WUFFS_CONFIG__MODULE__BASE) ||
11387 // defined(WUFFS_CONFIG__MODULE__BASE__CORE)
11388
11389#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
11390 defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES)
11391
11392// ---------------- Interface Definitions.
11393
11394WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
11395wuffs_base__hasher_u32__set_quirk_enabled(
11396 wuffs_base__hasher_u32* self,
11397 uint32_t a_quirk,
11398 bool a_enabled) {
11399 if (!self) {
11400 return wuffs_base__make_empty_struct();
11401 }
11402 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11403 return wuffs_base__make_empty_struct();
11404 }
11405
11406 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11407 int i;
11408 for (i = 0; i < 63; i++) {
11409 if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) {
11410 const wuffs_base__hasher_u32__func_ptrs* func_ptrs =
11411 (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers);
11412 return (*func_ptrs->set_quirk_enabled)(self, a_quirk, a_enabled);
11413 } else if (v->vtable_name == NULL) {
11414 break;
11415 }
11416 v++;
11417 }
11418
11419 return wuffs_base__make_empty_struct();
11420}
11421
11422WUFFS_BASE__MAYBE_STATIC uint32_t
11423wuffs_base__hasher_u32__update_u32(
11424 wuffs_base__hasher_u32* self,
11425 wuffs_base__slice_u8 a_x) {
11426 if (!self) {
11427 return 0;
11428 }
11429 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11430 return 0;
11431 }
11432
11433 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11434 int i;
11435 for (i = 0; i < 63; i++) {
11436 if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) {
11437 const wuffs_base__hasher_u32__func_ptrs* func_ptrs =
11438 (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers);
11439 return (*func_ptrs->update_u32)(self, a_x);
11440 } else if (v->vtable_name == NULL) {
11441 break;
11442 }
11443 v++;
11444 }
11445
11446 return 0;
11447}
11448
11449// --------
11450
11451WUFFS_BASE__MAYBE_STATIC wuffs_base__status
11452wuffs_base__image_decoder__decode_frame(
11453 wuffs_base__image_decoder* self,
11454 wuffs_base__pixel_buffer* a_dst,
11455 wuffs_base__io_buffer* a_src,
11456 wuffs_base__pixel_blend a_blend,
11457 wuffs_base__slice_u8 a_workbuf,
11458 wuffs_base__decode_frame_options* a_opts) {
11459 if (!self) {
11460 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
11461 }
11462 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11463 return wuffs_base__make_status(
11464 (self->private_impl.magic == WUFFS_BASE__DISABLED)
11465 ? wuffs_base__error__disabled_by_previous_error
11466 : wuffs_base__error__initialize_not_called);
11467 }
11468
11469 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11470 int i;
11471 for (i = 0; i < 63; i++) {
11472 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11473 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11474 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11475 return (*func_ptrs->decode_frame)(self, a_dst, a_src, a_blend, a_workbuf, a_opts);
11476 } else if (v->vtable_name == NULL) {
11477 break;
11478 }
11479 v++;
11480 }
11481
11482 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
11483}
11484
11485WUFFS_BASE__MAYBE_STATIC wuffs_base__status
11486wuffs_base__image_decoder__decode_frame_config(
11487 wuffs_base__image_decoder* self,
11488 wuffs_base__frame_config* a_dst,
11489 wuffs_base__io_buffer* a_src) {
11490 if (!self) {
11491 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
11492 }
11493 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11494 return wuffs_base__make_status(
11495 (self->private_impl.magic == WUFFS_BASE__DISABLED)
11496 ? wuffs_base__error__disabled_by_previous_error
11497 : wuffs_base__error__initialize_not_called);
11498 }
11499
11500 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11501 int i;
11502 for (i = 0; i < 63; i++) {
11503 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11504 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11505 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11506 return (*func_ptrs->decode_frame_config)(self, a_dst, a_src);
11507 } else if (v->vtable_name == NULL) {
11508 break;
11509 }
11510 v++;
11511 }
11512
11513 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
11514}
11515
11516WUFFS_BASE__MAYBE_STATIC wuffs_base__status
11517wuffs_base__image_decoder__decode_image_config(
11518 wuffs_base__image_decoder* self,
11519 wuffs_base__image_config* a_dst,
11520 wuffs_base__io_buffer* a_src) {
11521 if (!self) {
11522 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
11523 }
11524 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11525 return wuffs_base__make_status(
11526 (self->private_impl.magic == WUFFS_BASE__DISABLED)
11527 ? wuffs_base__error__disabled_by_previous_error
11528 : wuffs_base__error__initialize_not_called);
11529 }
11530
11531 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11532 int i;
11533 for (i = 0; i < 63; i++) {
11534 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11535 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11536 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11537 return (*func_ptrs->decode_image_config)(self, a_dst, a_src);
11538 } else if (v->vtable_name == NULL) {
11539 break;
11540 }
11541 v++;
11542 }
11543
11544 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
11545}
11546
11547WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
11548wuffs_base__image_decoder__frame_dirty_rect(
11549 const wuffs_base__image_decoder* self) {
11550 if (!self) {
11551 return wuffs_base__utility__empty_rect_ie_u32();
11552 }
11553 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
11554 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
11555 return wuffs_base__utility__empty_rect_ie_u32();
11556 }
11557
11558 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11559 int i;
11560 for (i = 0; i < 63; i++) {
11561 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11562 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11563 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11564 return (*func_ptrs->frame_dirty_rect)(self);
11565 } else if (v->vtable_name == NULL) {
11566 break;
11567 }
11568 v++;
11569 }
11570
11571 return wuffs_base__utility__empty_rect_ie_u32();
11572}
11573
11574WUFFS_BASE__MAYBE_STATIC uint32_t
11575wuffs_base__image_decoder__num_animation_loops(
11576 const wuffs_base__image_decoder* self) {
11577 if (!self) {
11578 return 0;
11579 }
11580 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
11581 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
11582 return 0;
11583 }
11584
11585 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11586 int i;
11587 for (i = 0; i < 63; i++) {
11588 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11589 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11590 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11591 return (*func_ptrs->num_animation_loops)(self);
11592 } else if (v->vtable_name == NULL) {
11593 break;
11594 }
11595 v++;
11596 }
11597
11598 return 0;
11599}
11600
11601WUFFS_BASE__MAYBE_STATIC uint64_t
11602wuffs_base__image_decoder__num_decoded_frame_configs(
11603 const wuffs_base__image_decoder* self) {
11604 if (!self) {
11605 return 0;
11606 }
11607 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
11608 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
11609 return 0;
11610 }
11611
11612 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11613 int i;
11614 for (i = 0; i < 63; i++) {
11615 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11616 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11617 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11618 return (*func_ptrs->num_decoded_frame_configs)(self);
11619 } else if (v->vtable_name == NULL) {
11620 break;
11621 }
11622 v++;
11623 }
11624
11625 return 0;
11626}
11627
11628WUFFS_BASE__MAYBE_STATIC uint64_t
11629wuffs_base__image_decoder__num_decoded_frames(
11630 const wuffs_base__image_decoder* self) {
11631 if (!self) {
11632 return 0;
11633 }
11634 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
11635 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
11636 return 0;
11637 }
11638
11639 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11640 int i;
11641 for (i = 0; i < 63; i++) {
11642 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11643 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11644 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11645 return (*func_ptrs->num_decoded_frames)(self);
11646 } else if (v->vtable_name == NULL) {
11647 break;
11648 }
11649 v++;
11650 }
11651
11652 return 0;
11653}
11654
11655WUFFS_BASE__MAYBE_STATIC wuffs_base__status
11656wuffs_base__image_decoder__restart_frame(
11657 wuffs_base__image_decoder* self,
11658 uint64_t a_index,
11659 uint64_t a_io_position) {
11660 if (!self) {
11661 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
11662 }
11663 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11664 return wuffs_base__make_status(
11665 (self->private_impl.magic == WUFFS_BASE__DISABLED)
11666 ? wuffs_base__error__disabled_by_previous_error
11667 : wuffs_base__error__initialize_not_called);
11668 }
11669
11670 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11671 int i;
11672 for (i = 0; i < 63; i++) {
11673 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11674 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11675 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11676 return (*func_ptrs->restart_frame)(self, a_index, a_io_position);
11677 } else if (v->vtable_name == NULL) {
11678 break;
11679 }
11680 v++;
11681 }
11682
11683 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
11684}
11685
11686WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
11687wuffs_base__image_decoder__set_quirk_enabled(
11688 wuffs_base__image_decoder* self,
11689 uint32_t a_quirk,
11690 bool a_enabled) {
11691 if (!self) {
11692 return wuffs_base__make_empty_struct();
11693 }
11694 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11695 return wuffs_base__make_empty_struct();
11696 }
11697
11698 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11699 int i;
11700 for (i = 0; i < 63; i++) {
11701 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11702 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11703 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11704 return (*func_ptrs->set_quirk_enabled)(self, a_quirk, a_enabled);
11705 } else if (v->vtable_name == NULL) {
11706 break;
11707 }
11708 v++;
11709 }
11710
11711 return wuffs_base__make_empty_struct();
11712}
11713
11714WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
11715wuffs_base__image_decoder__set_report_metadata(
11716 wuffs_base__image_decoder* self,
11717 uint32_t a_fourcc,
11718 bool a_report) {
11719 if (!self) {
11720 return wuffs_base__make_empty_struct();
11721 }
11722 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11723 return wuffs_base__make_empty_struct();
11724 }
11725
11726 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11727 int i;
11728 for (i = 0; i < 63; i++) {
11729 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11730 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11731 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11732 return (*func_ptrs->set_report_metadata)(self, a_fourcc, a_report);
11733 } else if (v->vtable_name == NULL) {
11734 break;
11735 }
11736 v++;
11737 }
11738
11739 return wuffs_base__make_empty_struct();
11740}
11741
11742WUFFS_BASE__MAYBE_STATIC wuffs_base__status
11743wuffs_base__image_decoder__tell_me_more(
11744 wuffs_base__image_decoder* self,
11745 wuffs_base__io_buffer* a_dst,
11746 wuffs_base__more_information* a_minfo,
11747 wuffs_base__io_buffer* a_src) {
11748 if (!self) {
11749 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
11750 }
11751 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11752 return wuffs_base__make_status(
11753 (self->private_impl.magic == WUFFS_BASE__DISABLED)
11754 ? wuffs_base__error__disabled_by_previous_error
11755 : wuffs_base__error__initialize_not_called);
11756 }
11757
11758 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11759 int i;
11760 for (i = 0; i < 63; i++) {
11761 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11762 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11763 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11764 return (*func_ptrs->tell_me_more)(self, a_dst, a_minfo, a_src);
11765 } else if (v->vtable_name == NULL) {
11766 break;
11767 }
11768 v++;
11769 }
11770
11771 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
11772}
11773
11774WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
11775wuffs_base__image_decoder__workbuf_len(
11776 const wuffs_base__image_decoder* self) {
11777 if (!self) {
11778 return wuffs_base__utility__empty_range_ii_u64();
11779 }
11780 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
11781 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
11782 return wuffs_base__utility__empty_range_ii_u64();
11783 }
11784
11785 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11786 int i;
11787 for (i = 0; i < 63; i++) {
11788 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
11789 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
11790 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
11791 return (*func_ptrs->workbuf_len)(self);
11792 } else if (v->vtable_name == NULL) {
11793 break;
11794 }
11795 v++;
11796 }
11797
11798 return wuffs_base__utility__empty_range_ii_u64();
11799}
11800
11801// --------
11802
11803WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
11804wuffs_base__io_transformer__set_quirk_enabled(
11805 wuffs_base__io_transformer* self,
11806 uint32_t a_quirk,
11807 bool a_enabled) {
11808 if (!self) {
11809 return wuffs_base__make_empty_struct();
11810 }
11811 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11812 return wuffs_base__make_empty_struct();
11813 }
11814
11815 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11816 int i;
11817 for (i = 0; i < 63; i++) {
11818 if (v->vtable_name == wuffs_base__io_transformer__vtable_name) {
11819 const wuffs_base__io_transformer__func_ptrs* func_ptrs =
11820 (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers);
11821 return (*func_ptrs->set_quirk_enabled)(self, a_quirk, a_enabled);
11822 } else if (v->vtable_name == NULL) {
11823 break;
11824 }
11825 v++;
11826 }
11827
11828 return wuffs_base__make_empty_struct();
11829}
11830
11831WUFFS_BASE__MAYBE_STATIC wuffs_base__status
11832wuffs_base__io_transformer__transform_io(
11833 wuffs_base__io_transformer* self,
11834 wuffs_base__io_buffer* a_dst,
11835 wuffs_base__io_buffer* a_src,
11836 wuffs_base__slice_u8 a_workbuf) {
11837 if (!self) {
11838 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
11839 }
11840 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11841 return wuffs_base__make_status(
11842 (self->private_impl.magic == WUFFS_BASE__DISABLED)
11843 ? wuffs_base__error__disabled_by_previous_error
11844 : wuffs_base__error__initialize_not_called);
11845 }
11846
11847 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11848 int i;
11849 for (i = 0; i < 63; i++) {
11850 if (v->vtable_name == wuffs_base__io_transformer__vtable_name) {
11851 const wuffs_base__io_transformer__func_ptrs* func_ptrs =
11852 (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers);
11853 return (*func_ptrs->transform_io)(self, a_dst, a_src, a_workbuf);
11854 } else if (v->vtable_name == NULL) {
11855 break;
11856 }
11857 v++;
11858 }
11859
11860 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
11861}
11862
11863WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
11864wuffs_base__io_transformer__workbuf_len(
11865 const wuffs_base__io_transformer* self) {
11866 if (!self) {
11867 return wuffs_base__utility__empty_range_ii_u64();
11868 }
11869 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
11870 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
11871 return wuffs_base__utility__empty_range_ii_u64();
11872 }
11873
11874 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11875 int i;
11876 for (i = 0; i < 63; i++) {
11877 if (v->vtable_name == wuffs_base__io_transformer__vtable_name) {
11878 const wuffs_base__io_transformer__func_ptrs* func_ptrs =
11879 (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers);
11880 return (*func_ptrs->workbuf_len)(self);
11881 } else if (v->vtable_name == NULL) {
11882 break;
11883 }
11884 v++;
11885 }
11886
11887 return wuffs_base__utility__empty_range_ii_u64();
11888}
11889
11890// --------
11891
11892WUFFS_BASE__MAYBE_STATIC wuffs_base__status
11893wuffs_base__token_decoder__decode_tokens(
11894 wuffs_base__token_decoder* self,
11895 wuffs_base__token_buffer* a_dst,
11896 wuffs_base__io_buffer* a_src,
11897 wuffs_base__slice_u8 a_workbuf) {
11898 if (!self) {
11899 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
11900 }
11901 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11902 return wuffs_base__make_status(
11903 (self->private_impl.magic == WUFFS_BASE__DISABLED)
11904 ? wuffs_base__error__disabled_by_previous_error
11905 : wuffs_base__error__initialize_not_called);
11906 }
11907
11908 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11909 int i;
11910 for (i = 0; i < 63; i++) {
11911 if (v->vtable_name == wuffs_base__token_decoder__vtable_name) {
11912 const wuffs_base__token_decoder__func_ptrs* func_ptrs =
11913 (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers);
11914 return (*func_ptrs->decode_tokens)(self, a_dst, a_src, a_workbuf);
11915 } else if (v->vtable_name == NULL) {
11916 break;
11917 }
11918 v++;
11919 }
11920
11921 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
11922}
11923
11924WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
11925wuffs_base__token_decoder__set_quirk_enabled(
11926 wuffs_base__token_decoder* self,
11927 uint32_t a_quirk,
11928 bool a_enabled) {
11929 if (!self) {
11930 return wuffs_base__make_empty_struct();
11931 }
11932 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
11933 return wuffs_base__make_empty_struct();
11934 }
11935
11936 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11937 int i;
11938 for (i = 0; i < 63; i++) {
11939 if (v->vtable_name == wuffs_base__token_decoder__vtable_name) {
11940 const wuffs_base__token_decoder__func_ptrs* func_ptrs =
11941 (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers);
11942 return (*func_ptrs->set_quirk_enabled)(self, a_quirk, a_enabled);
11943 } else if (v->vtable_name == NULL) {
11944 break;
11945 }
11946 v++;
11947 }
11948
11949 return wuffs_base__make_empty_struct();
11950}
11951
11952WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
11953wuffs_base__token_decoder__workbuf_len(
11954 const wuffs_base__token_decoder* self) {
11955 if (!self) {
11956 return wuffs_base__utility__empty_range_ii_u64();
11957 }
11958 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
11959 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
11960 return wuffs_base__utility__empty_range_ii_u64();
11961 }
11962
11963 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
11964 int i;
11965 for (i = 0; i < 63; i++) {
11966 if (v->vtable_name == wuffs_base__token_decoder__vtable_name) {
11967 const wuffs_base__token_decoder__func_ptrs* func_ptrs =
11968 (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers);
11969 return (*func_ptrs->workbuf_len)(self);
11970 } else if (v->vtable_name == NULL) {
11971 break;
11972 }
11973 v++;
11974 }
11975
11976 return wuffs_base__utility__empty_range_ii_u64();
11977}
11978
11979#endif // !defined(WUFFS_CONFIG__MODULES) ||
11980 // defined(WUFFS_CONFIG__MODULE__BASE) ||
11981 // defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES)
11982
11983#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
11984 defined(WUFFS_CONFIG__MODULE__BASE__FLOATCONV)
11985
11986// ---------------- IEEE 754 Floating Point
11987
11988// The etc__hpd_left_shift and etc__powers_of_5 tables were printed by
11989// script/print-hpd-left-shift.go. That script has an optional -comments flag,
11990// whose output is not copied here, which prints further detail.
11991//
11992// These tables are used in
11993// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits.
11994
11995// wuffs_base__private_implementation__hpd_left_shift[i] encodes the number of
11996// new digits created after multiplying a positive integer by (1 << i): the
11997// additional length in the decimal representation. For example, shifting "234"
11998// by 3 (equivalent to multiplying by 8) will produce "1872". Going from a
11999// 3-length string to a 4-length string means that 1 new digit was added (and
12000// existing digits may have changed).
12001//
12002// Shifting by i can add either N or N-1 new digits, depending on whether the
12003// original positive integer compares >= or < to the i'th power of 5 (as 10
12004// equals 2 * 5). Comparison is lexicographic, not numerical.
12005//
12006// For example, shifting by 4 (i.e. multiplying by 16) can add 1 or 2 new
12007// digits, depending on a lexicographic comparison to (5 ** 4), i.e. "625":
12008// - ("1" << 4) is "16", which adds 1 new digit.
12009// - ("5678" << 4) is "90848", which adds 1 new digit.
12010// - ("624" << 4) is "9984", which adds 1 new digit.
12011// - ("62498" << 4) is "999968", which adds 1 new digit.
12012// - ("625" << 4) is "10000", which adds 2 new digits.
12013// - ("625001" << 4) is "10000016", which adds 2 new digits.
12014// - ("7008" << 4) is "112128", which adds 2 new digits.
12015// - ("99" << 4) is "1584", which adds 2 new digits.
12016//
12017// Thus, when i is 4, N is 2 and (5 ** i) is "625". This etc__hpd_left_shift
12018// array encodes this as:
12019// - etc__hpd_left_shift[4] is 0x1006 = (2 << 11) | 0x0006.
12020// - etc__hpd_left_shift[5] is 0x1009 = (? << 11) | 0x0009.
12021// where the ? isn't relevant for i == 4.
12022//
12023// The high 5 bits of etc__hpd_left_shift[i] is N, the higher of the two
12024// possible number of new digits. The low 11 bits are an offset into the
12025// etc__powers_of_5 array (of length 0x051C, so offsets fit in 11 bits). When i
12026// is 4, its offset and the next one is 6 and 9, and etc__powers_of_5[6 .. 9]
12027// is the string "\x06\x02\x05", so the relevant power of 5 is "625".
12028//
12029// Thanks to Ken Thompson for the original idea.
12030static const uint16_t wuffs_base__private_implementation__hpd_left_shift[65] = {
12031 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817,
12032 0x181D, 0x2024, 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067,
12033 0x3073, 0x3080, 0x388E, 0x389C, 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF,
12034 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, 0x5180, 0x5998, 0x59B0,
12035 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, 0x72AA,
12036 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC,
12037 0x8C02, 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C,
12038 0x051C, 0x051C,
12039};
12040
12041// wuffs_base__private_implementation__powers_of_5 contains the powers of 5,
12042// concatenated together: "5", "25", "125", "625", "3125", etc.
12043static const uint8_t wuffs_base__private_implementation__powers_of_5[0x051C] = {
12044 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9,
12045 0, 6, 2, 5, 1, 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2,
12046 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, 1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5,
12047 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, 5, 1, 5, 2, 5, 8, 7, 8, 9, 0,
12048 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6, 9, 7, 2, 6, 5,
12049 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1,
12050 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4,
12051 1, 8, 5, 7, 9, 1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7,
12052 8, 1, 2, 5, 5, 9, 6, 0, 4, 6, 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0,
12053 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1, 4, 9, 0, 1, 1, 6, 1, 1, 9, 3,
12054 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2, 3, 8, 2, 8, 1,
12055 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6,
12056 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5,
12057 7, 4, 6, 1, 5, 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0,
12058 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, 5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6,
12059 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5, 3, 2, 1, 8, 2, 6, 9, 3, 4, 8,
12060 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4, 6, 7, 4, 0, 7,
12061 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6,
12062 1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8,
12063 0, 6, 6, 4, 0, 6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9,
12064 0, 3, 3, 2, 0, 3, 1, 2, 5, 3, 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2,
12065 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, 9, 8, 9, 4, 0, 3, 5, 4, 5, 8,
12066 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, 7, 0, 1, 7, 7,
12067 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5,
12068 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3,
12069 7, 3, 6, 7, 5, 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2,
12070 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, 7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9,
12071 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8, 8, 6, 0, 8, 0, 8, 0, 1, 4, 8,
12072 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0, 9, 4, 3, 0, 4,
12073 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0,
12074 8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5,
12075 6, 2, 5, 7, 1, 0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1,
12076 2, 4, 2, 6, 7, 5, 7, 8, 1, 2, 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5,
12077 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, 9, 0, 6, 2, 5, 1, 7, 7, 6, 3,
12078 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0, 6, 6, 8, 9, 4,
12079 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3,
12080 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8,
12081 5, 0, 0, 6, 2, 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2,
12082 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, 9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6,
12083 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1, 1, 0, 2, 2, 3, 0, 2, 4, 6, 2,
12084 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8, 2, 0, 3, 1, 2,
12085 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5,
12086 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5,
12087 6, 2, 8, 9, 1, 3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8,
12088 1, 2, 5, 1, 3, 8, 7, 7, 7, 8, 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9,
12089 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, 6, 2, 5, 6, 9, 3, 8, 8, 9, 3,
12090 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, 5, 5, 6, 7, 6,
12091 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1,
12092 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1,
12093 7, 3, 4, 7, 2, 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4,
12094 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, 8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7,
12095 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2, 2, 4, 0, 6, 9, 5, 9, 5, 3, 3,
12096 6, 9, 1, 4, 0, 6, 2, 5,
12097};
12098
12099// --------
12100
12101// wuffs_base__private_implementation__powers_of_10 contains truncated
12102// approximations to the powers of 10, ranging from 1e-307 to 1e+288 inclusive,
12103// as 596 pairs of uint64_t values (a 128-bit mantissa).
12104//
12105// There's also an implicit third column (implied by a linear formula involving
12106// the base-10 exponent) that is the base-2 exponent, biased by a magic
12107// constant. That constant (1214 or 0x04BE) equals 1023 + 191. 1023 is the bias
12108// for IEEE 754 double-precision floating point. 191 is ((3 * 64) - 1) and
12109// wuffs_base__private_implementation__parse_number_f64_eisel_lemire works with
12110// multiples-of-64-bit mantissas.
12111//
12112// For example, the third row holds the approximation to 1e-305:
12113// 0xE0B62E29_29ABA83C_331ACDAB_FE94DE87 * (2 ** (0x0049 - 0x04BE))
12114//
12115// Similarly, 1e+4 is approximated by:
12116// 0x9C400000_00000000_00000000_00000000 * (2 ** (0x044C - 0x04BE))
12117//
12118// Similarly, 1e+68 is approximated by:
12119// 0xED63A231_D4C4FB27_4CA7AAA8_63EE4BDD * (2 ** (0x0520 - 0x04BE))
12120//
12121// This table was generated by by script/print-mpb-powers-of-10.go
12122static const uint64_t wuffs_base__private_implementation__powers_of_10[596][2] =
12123 {
12124 {0xA5D3B6D479F8E056, 0x8FD0C16206306BAB}, // 1e-307
12125 {0x8F48A4899877186C, 0xB3C4F1BA87BC8696}, // 1e-306
12126 {0x331ACDABFE94DE87, 0xE0B62E2929ABA83C}, // 1e-305
12127 {0x9FF0C08B7F1D0B14, 0x8C71DCD9BA0B4925}, // 1e-304
12128 {0x07ECF0AE5EE44DD9, 0xAF8E5410288E1B6F}, // 1e-303
12129 {0xC9E82CD9F69D6150, 0xDB71E91432B1A24A}, // 1e-302
12130 {0xBE311C083A225CD2, 0x892731AC9FAF056E}, // 1e-301
12131 {0x6DBD630A48AAF406, 0xAB70FE17C79AC6CA}, // 1e-300
12132 {0x092CBBCCDAD5B108, 0xD64D3D9DB981787D}, // 1e-299
12133 {0x25BBF56008C58EA5, 0x85F0468293F0EB4E}, // 1e-298
12134 {0xAF2AF2B80AF6F24E, 0xA76C582338ED2621}, // 1e-297
12135 {0x1AF5AF660DB4AEE1, 0xD1476E2C07286FAA}, // 1e-296
12136 {0x50D98D9FC890ED4D, 0x82CCA4DB847945CA}, // 1e-295
12137 {0xE50FF107BAB528A0, 0xA37FCE126597973C}, // 1e-294
12138 {0x1E53ED49A96272C8, 0xCC5FC196FEFD7D0C}, // 1e-293
12139 {0x25E8E89C13BB0F7A, 0xFF77B1FCBEBCDC4F}, // 1e-292
12140 {0x77B191618C54E9AC, 0x9FAACF3DF73609B1}, // 1e-291
12141 {0xD59DF5B9EF6A2417, 0xC795830D75038C1D}, // 1e-290
12142 {0x4B0573286B44AD1D, 0xF97AE3D0D2446F25}, // 1e-289
12143 {0x4EE367F9430AEC32, 0x9BECCE62836AC577}, // 1e-288
12144 {0x229C41F793CDA73F, 0xC2E801FB244576D5}, // 1e-287
12145 {0x6B43527578C1110F, 0xF3A20279ED56D48A}, // 1e-286
12146 {0x830A13896B78AAA9, 0x9845418C345644D6}, // 1e-285
12147 {0x23CC986BC656D553, 0xBE5691EF416BD60C}, // 1e-284
12148 {0x2CBFBE86B7EC8AA8, 0xEDEC366B11C6CB8F}, // 1e-283
12149 {0x7BF7D71432F3D6A9, 0x94B3A202EB1C3F39}, // 1e-282
12150 {0xDAF5CCD93FB0CC53, 0xB9E08A83A5E34F07}, // 1e-281
12151 {0xD1B3400F8F9CFF68, 0xE858AD248F5C22C9}, // 1e-280
12152 {0x23100809B9C21FA1, 0x91376C36D99995BE}, // 1e-279
12153 {0xABD40A0C2832A78A, 0xB58547448FFFFB2D}, // 1e-278
12154 {0x16C90C8F323F516C, 0xE2E69915B3FFF9F9}, // 1e-277
12155 {0xAE3DA7D97F6792E3, 0x8DD01FAD907FFC3B}, // 1e-276
12156 {0x99CD11CFDF41779C, 0xB1442798F49FFB4A}, // 1e-275
12157 {0x40405643D711D583, 0xDD95317F31C7FA1D}, // 1e-274
12158 {0x482835EA666B2572, 0x8A7D3EEF7F1CFC52}, // 1e-273
12159 {0xDA3243650005EECF, 0xAD1C8EAB5EE43B66}, // 1e-272
12160 {0x90BED43E40076A82, 0xD863B256369D4A40}, // 1e-271
12161 {0x5A7744A6E804A291, 0x873E4F75E2224E68}, // 1e-270
12162 {0x711515D0A205CB36, 0xA90DE3535AAAE202}, // 1e-269
12163 {0x0D5A5B44CA873E03, 0xD3515C2831559A83}, // 1e-268
12164 {0xE858790AFE9486C2, 0x8412D9991ED58091}, // 1e-267
12165 {0x626E974DBE39A872, 0xA5178FFF668AE0B6}, // 1e-266
12166 {0xFB0A3D212DC8128F, 0xCE5D73FF402D98E3}, // 1e-265
12167 {0x7CE66634BC9D0B99, 0x80FA687F881C7F8E}, // 1e-264
12168 {0x1C1FFFC1EBC44E80, 0xA139029F6A239F72}, // 1e-263
12169 {0xA327FFB266B56220, 0xC987434744AC874E}, // 1e-262
12170 {0x4BF1FF9F0062BAA8, 0xFBE9141915D7A922}, // 1e-261
12171 {0x6F773FC3603DB4A9, 0x9D71AC8FADA6C9B5}, // 1e-260
12172 {0xCB550FB4384D21D3, 0xC4CE17B399107C22}, // 1e-259
12173 {0x7E2A53A146606A48, 0xF6019DA07F549B2B}, // 1e-258
12174 {0x2EDA7444CBFC426D, 0x99C102844F94E0FB}, // 1e-257
12175 {0xFA911155FEFB5308, 0xC0314325637A1939}, // 1e-256
12176 {0x793555AB7EBA27CA, 0xF03D93EEBC589F88}, // 1e-255
12177 {0x4BC1558B2F3458DE, 0x96267C7535B763B5}, // 1e-254
12178 {0x9EB1AAEDFB016F16, 0xBBB01B9283253CA2}, // 1e-253
12179 {0x465E15A979C1CADC, 0xEA9C227723EE8BCB}, // 1e-252
12180 {0x0BFACD89EC191EC9, 0x92A1958A7675175F}, // 1e-251
12181 {0xCEF980EC671F667B, 0xB749FAED14125D36}, // 1e-250
12182 {0x82B7E12780E7401A, 0xE51C79A85916F484}, // 1e-249
12183 {0xD1B2ECB8B0908810, 0x8F31CC0937AE58D2}, // 1e-248
12184 {0x861FA7E6DCB4AA15, 0xB2FE3F0B8599EF07}, // 1e-247
12185 {0x67A791E093E1D49A, 0xDFBDCECE67006AC9}, // 1e-246
12186 {0xE0C8BB2C5C6D24E0, 0x8BD6A141006042BD}, // 1e-245
12187 {0x58FAE9F773886E18, 0xAECC49914078536D}, // 1e-244
12188 {0xAF39A475506A899E, 0xDA7F5BF590966848}, // 1e-243
12189 {0x6D8406C952429603, 0x888F99797A5E012D}, // 1e-242
12190 {0xC8E5087BA6D33B83, 0xAAB37FD7D8F58178}, // 1e-241
12191 {0xFB1E4A9A90880A64, 0xD5605FCDCF32E1D6}, // 1e-240
12192 {0x5CF2EEA09A55067F, 0x855C3BE0A17FCD26}, // 1e-239
12193 {0xF42FAA48C0EA481E, 0xA6B34AD8C9DFC06F}, // 1e-238
12194 {0xF13B94DAF124DA26, 0xD0601D8EFC57B08B}, // 1e-237
12195 {0x76C53D08D6B70858, 0x823C12795DB6CE57}, // 1e-236
12196 {0x54768C4B0C64CA6E, 0xA2CB1717B52481ED}, // 1e-235
12197 {0xA9942F5DCF7DFD09, 0xCB7DDCDDA26DA268}, // 1e-234
12198 {0xD3F93B35435D7C4C, 0xFE5D54150B090B02}, // 1e-233
12199 {0xC47BC5014A1A6DAF, 0x9EFA548D26E5A6E1}, // 1e-232
12200 {0x359AB6419CA1091B, 0xC6B8E9B0709F109A}, // 1e-231
12201 {0xC30163D203C94B62, 0xF867241C8CC6D4C0}, // 1e-230
12202 {0x79E0DE63425DCF1D, 0x9B407691D7FC44F8}, // 1e-229
12203 {0x985915FC12F542E4, 0xC21094364DFB5636}, // 1e-228
12204 {0x3E6F5B7B17B2939D, 0xF294B943E17A2BC4}, // 1e-227
12205 {0xA705992CEECF9C42, 0x979CF3CA6CEC5B5A}, // 1e-226
12206 {0x50C6FF782A838353, 0xBD8430BD08277231}, // 1e-225
12207 {0xA4F8BF5635246428, 0xECE53CEC4A314EBD}, // 1e-224
12208 {0x871B7795E136BE99, 0x940F4613AE5ED136}, // 1e-223
12209 {0x28E2557B59846E3F, 0xB913179899F68584}, // 1e-222
12210 {0x331AEADA2FE589CF, 0xE757DD7EC07426E5}, // 1e-221
12211 {0x3FF0D2C85DEF7621, 0x9096EA6F3848984F}, // 1e-220
12212 {0x0FED077A756B53A9, 0xB4BCA50B065ABE63}, // 1e-219
12213 {0xD3E8495912C62894, 0xE1EBCE4DC7F16DFB}, // 1e-218
12214 {0x64712DD7ABBBD95C, 0x8D3360F09CF6E4BD}, // 1e-217
12215 {0xBD8D794D96AACFB3, 0xB080392CC4349DEC}, // 1e-216
12216 {0xECF0D7A0FC5583A0, 0xDCA04777F541C567}, // 1e-215
12217 {0xF41686C49DB57244, 0x89E42CAAF9491B60}, // 1e-214
12218 {0x311C2875C522CED5, 0xAC5D37D5B79B6239}, // 1e-213
12219 {0x7D633293366B828B, 0xD77485CB25823AC7}, // 1e-212
12220 {0xAE5DFF9C02033197, 0x86A8D39EF77164BC}, // 1e-211
12221 {0xD9F57F830283FDFC, 0xA8530886B54DBDEB}, // 1e-210
12222 {0xD072DF63C324FD7B, 0xD267CAA862A12D66}, // 1e-209
12223 {0x4247CB9E59F71E6D, 0x8380DEA93DA4BC60}, // 1e-208
12224 {0x52D9BE85F074E608, 0xA46116538D0DEB78}, // 1e-207
12225 {0x67902E276C921F8B, 0xCD795BE870516656}, // 1e-206
12226 {0x00BA1CD8A3DB53B6, 0x806BD9714632DFF6}, // 1e-205
12227 {0x80E8A40ECCD228A4, 0xA086CFCD97BF97F3}, // 1e-204
12228 {0x6122CD128006B2CD, 0xC8A883C0FDAF7DF0}, // 1e-203
12229 {0x796B805720085F81, 0xFAD2A4B13D1B5D6C}, // 1e-202
12230 {0xCBE3303674053BB0, 0x9CC3A6EEC6311A63}, // 1e-201
12231 {0xBEDBFC4411068A9C, 0xC3F490AA77BD60FC}, // 1e-200
12232 {0xEE92FB5515482D44, 0xF4F1B4D515ACB93B}, // 1e-199
12233 {0x751BDD152D4D1C4A, 0x991711052D8BF3C5}, // 1e-198
12234 {0xD262D45A78A0635D, 0xBF5CD54678EEF0B6}, // 1e-197
12235 {0x86FB897116C87C34, 0xEF340A98172AACE4}, // 1e-196
12236 {0xD45D35E6AE3D4DA0, 0x9580869F0E7AAC0E}, // 1e-195
12237 {0x8974836059CCA109, 0xBAE0A846D2195712}, // 1e-194
12238 {0x2BD1A438703FC94B, 0xE998D258869FACD7}, // 1e-193
12239 {0x7B6306A34627DDCF, 0x91FF83775423CC06}, // 1e-192
12240 {0x1A3BC84C17B1D542, 0xB67F6455292CBF08}, // 1e-191
12241 {0x20CABA5F1D9E4A93, 0xE41F3D6A7377EECA}, // 1e-190
12242 {0x547EB47B7282EE9C, 0x8E938662882AF53E}, // 1e-189
12243 {0xE99E619A4F23AA43, 0xB23867FB2A35B28D}, // 1e-188
12244 {0x6405FA00E2EC94D4, 0xDEC681F9F4C31F31}, // 1e-187
12245 {0xDE83BC408DD3DD04, 0x8B3C113C38F9F37E}, // 1e-186
12246 {0x9624AB50B148D445, 0xAE0B158B4738705E}, // 1e-185
12247 {0x3BADD624DD9B0957, 0xD98DDAEE19068C76}, // 1e-184
12248 {0xE54CA5D70A80E5D6, 0x87F8A8D4CFA417C9}, // 1e-183
12249 {0x5E9FCF4CCD211F4C, 0xA9F6D30A038D1DBC}, // 1e-182
12250 {0x7647C3200069671F, 0xD47487CC8470652B}, // 1e-181
12251 {0x29ECD9F40041E073, 0x84C8D4DFD2C63F3B}, // 1e-180
12252 {0xF468107100525890, 0xA5FB0A17C777CF09}, // 1e-179
12253 {0x7182148D4066EEB4, 0xCF79CC9DB955C2CC}, // 1e-178
12254 {0xC6F14CD848405530, 0x81AC1FE293D599BF}, // 1e-177
12255 {0xB8ADA00E5A506A7C, 0xA21727DB38CB002F}, // 1e-176
12256 {0xA6D90811F0E4851C, 0xCA9CF1D206FDC03B}, // 1e-175
12257 {0x908F4A166D1DA663, 0xFD442E4688BD304A}, // 1e-174
12258 {0x9A598E4E043287FE, 0x9E4A9CEC15763E2E}, // 1e-173
12259 {0x40EFF1E1853F29FD, 0xC5DD44271AD3CDBA}, // 1e-172
12260 {0xD12BEE59E68EF47C, 0xF7549530E188C128}, // 1e-171
12261 {0x82BB74F8301958CE, 0x9A94DD3E8CF578B9}, // 1e-170
12262 {0xE36A52363C1FAF01, 0xC13A148E3032D6E7}, // 1e-169
12263 {0xDC44E6C3CB279AC1, 0xF18899B1BC3F8CA1}, // 1e-168
12264 {0x29AB103A5EF8C0B9, 0x96F5600F15A7B7E5}, // 1e-167
12265 {0x7415D448F6B6F0E7, 0xBCB2B812DB11A5DE}, // 1e-166
12266 {0x111B495B3464AD21, 0xEBDF661791D60F56}, // 1e-165
12267 {0xCAB10DD900BEEC34, 0x936B9FCEBB25C995}, // 1e-164
12268 {0x3D5D514F40EEA742, 0xB84687C269EF3BFB}, // 1e-163
12269 {0x0CB4A5A3112A5112, 0xE65829B3046B0AFA}, // 1e-162
12270 {0x47F0E785EABA72AB, 0x8FF71A0FE2C2E6DC}, // 1e-161
12271 {0x59ED216765690F56, 0xB3F4E093DB73A093}, // 1e-160
12272 {0x306869C13EC3532C, 0xE0F218B8D25088B8}, // 1e-159
12273 {0x1E414218C73A13FB, 0x8C974F7383725573}, // 1e-158
12274 {0xE5D1929EF90898FA, 0xAFBD2350644EEACF}, // 1e-157
12275 {0xDF45F746B74ABF39, 0xDBAC6C247D62A583}, // 1e-156
12276 {0x6B8BBA8C328EB783, 0x894BC396CE5DA772}, // 1e-155
12277 {0x066EA92F3F326564, 0xAB9EB47C81F5114F}, // 1e-154
12278 {0xC80A537B0EFEFEBD, 0xD686619BA27255A2}, // 1e-153
12279 {0xBD06742CE95F5F36, 0x8613FD0145877585}, // 1e-152
12280 {0x2C48113823B73704, 0xA798FC4196E952E7}, // 1e-151
12281 {0xF75A15862CA504C5, 0xD17F3B51FCA3A7A0}, // 1e-150
12282 {0x9A984D73DBE722FB, 0x82EF85133DE648C4}, // 1e-149
12283 {0xC13E60D0D2E0EBBA, 0xA3AB66580D5FDAF5}, // 1e-148
12284 {0x318DF905079926A8, 0xCC963FEE10B7D1B3}, // 1e-147
12285 {0xFDF17746497F7052, 0xFFBBCFE994E5C61F}, // 1e-146
12286 {0xFEB6EA8BEDEFA633, 0x9FD561F1FD0F9BD3}, // 1e-145
12287 {0xFE64A52EE96B8FC0, 0xC7CABA6E7C5382C8}, // 1e-144
12288 {0x3DFDCE7AA3C673B0, 0xF9BD690A1B68637B}, // 1e-143
12289 {0x06BEA10CA65C084E, 0x9C1661A651213E2D}, // 1e-142
12290 {0x486E494FCFF30A62, 0xC31BFA0FE5698DB8}, // 1e-141
12291 {0x5A89DBA3C3EFCCFA, 0xF3E2F893DEC3F126}, // 1e-140
12292 {0xF89629465A75E01C, 0x986DDB5C6B3A76B7}, // 1e-139
12293 {0xF6BBB397F1135823, 0xBE89523386091465}, // 1e-138
12294 {0x746AA07DED582E2C, 0xEE2BA6C0678B597F}, // 1e-137
12295 {0xA8C2A44EB4571CDC, 0x94DB483840B717EF}, // 1e-136
12296 {0x92F34D62616CE413, 0xBA121A4650E4DDEB}, // 1e-135
12297 {0x77B020BAF9C81D17, 0xE896A0D7E51E1566}, // 1e-134
12298 {0x0ACE1474DC1D122E, 0x915E2486EF32CD60}, // 1e-133
12299 {0x0D819992132456BA, 0xB5B5ADA8AAFF80B8}, // 1e-132
12300 {0x10E1FFF697ED6C69, 0xE3231912D5BF60E6}, // 1e-131
12301 {0xCA8D3FFA1EF463C1, 0x8DF5EFABC5979C8F}, // 1e-130
12302 {0xBD308FF8A6B17CB2, 0xB1736B96B6FD83B3}, // 1e-129
12303 {0xAC7CB3F6D05DDBDE, 0xDDD0467C64BCE4A0}, // 1e-128
12304 {0x6BCDF07A423AA96B, 0x8AA22C0DBEF60EE4}, // 1e-127
12305 {0x86C16C98D2C953C6, 0xAD4AB7112EB3929D}, // 1e-126
12306 {0xE871C7BF077BA8B7, 0xD89D64D57A607744}, // 1e-125
12307 {0x11471CD764AD4972, 0x87625F056C7C4A8B}, // 1e-124
12308 {0xD598E40D3DD89BCF, 0xA93AF6C6C79B5D2D}, // 1e-123
12309 {0x4AFF1D108D4EC2C3, 0xD389B47879823479}, // 1e-122
12310 {0xCEDF722A585139BA, 0x843610CB4BF160CB}, // 1e-121
12311 {0xC2974EB4EE658828, 0xA54394FE1EEDB8FE}, // 1e-120
12312 {0x733D226229FEEA32, 0xCE947A3DA6A9273E}, // 1e-119
12313 {0x0806357D5A3F525F, 0x811CCC668829B887}, // 1e-118
12314 {0xCA07C2DCB0CF26F7, 0xA163FF802A3426A8}, // 1e-117
12315 {0xFC89B393DD02F0B5, 0xC9BCFF6034C13052}, // 1e-116
12316 {0xBBAC2078D443ACE2, 0xFC2C3F3841F17C67}, // 1e-115
12317 {0xD54B944B84AA4C0D, 0x9D9BA7832936EDC0}, // 1e-114
12318 {0x0A9E795E65D4DF11, 0xC5029163F384A931}, // 1e-113
12319 {0x4D4617B5FF4A16D5, 0xF64335BCF065D37D}, // 1e-112
12320 {0x504BCED1BF8E4E45, 0x99EA0196163FA42E}, // 1e-111
12321 {0xE45EC2862F71E1D6, 0xC06481FB9BCF8D39}, // 1e-110
12322 {0x5D767327BB4E5A4C, 0xF07DA27A82C37088}, // 1e-109
12323 {0x3A6A07F8D510F86F, 0x964E858C91BA2655}, // 1e-108
12324 {0x890489F70A55368B, 0xBBE226EFB628AFEA}, // 1e-107
12325 {0x2B45AC74CCEA842E, 0xEADAB0ABA3B2DBE5}, // 1e-106
12326 {0x3B0B8BC90012929D, 0x92C8AE6B464FC96F}, // 1e-105
12327 {0x09CE6EBB40173744, 0xB77ADA0617E3BBCB}, // 1e-104
12328 {0xCC420A6A101D0515, 0xE55990879DDCAABD}, // 1e-103
12329 {0x9FA946824A12232D, 0x8F57FA54C2A9EAB6}, // 1e-102
12330 {0x47939822DC96ABF9, 0xB32DF8E9F3546564}, // 1e-101
12331 {0x59787E2B93BC56F7, 0xDFF9772470297EBD}, // 1e-100
12332 {0x57EB4EDB3C55B65A, 0x8BFBEA76C619EF36}, // 1e-99
12333 {0xEDE622920B6B23F1, 0xAEFAE51477A06B03}, // 1e-98
12334 {0xE95FAB368E45ECED, 0xDAB99E59958885C4}, // 1e-97
12335 {0x11DBCB0218EBB414, 0x88B402F7FD75539B}, // 1e-96
12336 {0xD652BDC29F26A119, 0xAAE103B5FCD2A881}, // 1e-95
12337 {0x4BE76D3346F0495F, 0xD59944A37C0752A2}, // 1e-94
12338 {0x6F70A4400C562DDB, 0x857FCAE62D8493A5}, // 1e-93
12339 {0xCB4CCD500F6BB952, 0xA6DFBD9FB8E5B88E}, // 1e-92
12340 {0x7E2000A41346A7A7, 0xD097AD07A71F26B2}, // 1e-91
12341 {0x8ED400668C0C28C8, 0x825ECC24C873782F}, // 1e-90
12342 {0x728900802F0F32FA, 0xA2F67F2DFA90563B}, // 1e-89
12343 {0x4F2B40A03AD2FFB9, 0xCBB41EF979346BCA}, // 1e-88
12344 {0xE2F610C84987BFA8, 0xFEA126B7D78186BC}, // 1e-87
12345 {0x0DD9CA7D2DF4D7C9, 0x9F24B832E6B0F436}, // 1e-86
12346 {0x91503D1C79720DBB, 0xC6EDE63FA05D3143}, // 1e-85
12347 {0x75A44C6397CE912A, 0xF8A95FCF88747D94}, // 1e-84
12348 {0xC986AFBE3EE11ABA, 0x9B69DBE1B548CE7C}, // 1e-83
12349 {0xFBE85BADCE996168, 0xC24452DA229B021B}, // 1e-82
12350 {0xFAE27299423FB9C3, 0xF2D56790AB41C2A2}, // 1e-81
12351 {0xDCCD879FC967D41A, 0x97C560BA6B0919A5}, // 1e-80
12352 {0x5400E987BBC1C920, 0xBDB6B8E905CB600F}, // 1e-79
12353 {0x290123E9AAB23B68, 0xED246723473E3813}, // 1e-78
12354 {0xF9A0B6720AAF6521, 0x9436C0760C86E30B}, // 1e-77
12355 {0xF808E40E8D5B3E69, 0xB94470938FA89BCE}, // 1e-76
12356 {0xB60B1D1230B20E04, 0xE7958CB87392C2C2}, // 1e-75
12357 {0xB1C6F22B5E6F48C2, 0x90BD77F3483BB9B9}, // 1e-74
12358 {0x1E38AEB6360B1AF3, 0xB4ECD5F01A4AA828}, // 1e-73
12359 {0x25C6DA63C38DE1B0, 0xE2280B6C20DD5232}, // 1e-72
12360 {0x579C487E5A38AD0E, 0x8D590723948A535F}, // 1e-71
12361 {0x2D835A9DF0C6D851, 0xB0AF48EC79ACE837}, // 1e-70
12362 {0xF8E431456CF88E65, 0xDCDB1B2798182244}, // 1e-69
12363 {0x1B8E9ECB641B58FF, 0x8A08F0F8BF0F156B}, // 1e-68
12364 {0xE272467E3D222F3F, 0xAC8B2D36EED2DAC5}, // 1e-67
12365 {0x5B0ED81DCC6ABB0F, 0xD7ADF884AA879177}, // 1e-66
12366 {0x98E947129FC2B4E9, 0x86CCBB52EA94BAEA}, // 1e-65
12367 {0x3F2398D747B36224, 0xA87FEA27A539E9A5}, // 1e-64
12368 {0x8EEC7F0D19A03AAD, 0xD29FE4B18E88640E}, // 1e-63
12369 {0x1953CF68300424AC, 0x83A3EEEEF9153E89}, // 1e-62
12370 {0x5FA8C3423C052DD7, 0xA48CEAAAB75A8E2B}, // 1e-61
12371 {0x3792F412CB06794D, 0xCDB02555653131B6}, // 1e-60
12372 {0xE2BBD88BBEE40BD0, 0x808E17555F3EBF11}, // 1e-59
12373 {0x5B6ACEAEAE9D0EC4, 0xA0B19D2AB70E6ED6}, // 1e-58
12374 {0xF245825A5A445275, 0xC8DE047564D20A8B}, // 1e-57
12375 {0xEED6E2F0F0D56712, 0xFB158592BE068D2E}, // 1e-56
12376 {0x55464DD69685606B, 0x9CED737BB6C4183D}, // 1e-55
12377 {0xAA97E14C3C26B886, 0xC428D05AA4751E4C}, // 1e-54
12378 {0xD53DD99F4B3066A8, 0xF53304714D9265DF}, // 1e-53
12379 {0xE546A8038EFE4029, 0x993FE2C6D07B7FAB}, // 1e-52
12380 {0xDE98520472BDD033, 0xBF8FDB78849A5F96}, // 1e-51
12381 {0x963E66858F6D4440, 0xEF73D256A5C0F77C}, // 1e-50
12382 {0xDDE7001379A44AA8, 0x95A8637627989AAD}, // 1e-49
12383 {0x5560C018580D5D52, 0xBB127C53B17EC159}, // 1e-48
12384 {0xAAB8F01E6E10B4A6, 0xE9D71B689DDE71AF}, // 1e-47
12385 {0xCAB3961304CA70E8, 0x9226712162AB070D}, // 1e-46
12386 {0x3D607B97C5FD0D22, 0xB6B00D69BB55C8D1}, // 1e-45
12387 {0x8CB89A7DB77C506A, 0xE45C10C42A2B3B05}, // 1e-44
12388 {0x77F3608E92ADB242, 0x8EB98A7A9A5B04E3}, // 1e-43
12389 {0x55F038B237591ED3, 0xB267ED1940F1C61C}, // 1e-42
12390 {0x6B6C46DEC52F6688, 0xDF01E85F912E37A3}, // 1e-41
12391 {0x2323AC4B3B3DA015, 0x8B61313BBABCE2C6}, // 1e-40
12392 {0xABEC975E0A0D081A, 0xAE397D8AA96C1B77}, // 1e-39
12393 {0x96E7BD358C904A21, 0xD9C7DCED53C72255}, // 1e-38
12394 {0x7E50D64177DA2E54, 0x881CEA14545C7575}, // 1e-37
12395 {0xDDE50BD1D5D0B9E9, 0xAA242499697392D2}, // 1e-36
12396 {0x955E4EC64B44E864, 0xD4AD2DBFC3D07787}, // 1e-35
12397 {0xBD5AF13BEF0B113E, 0x84EC3C97DA624AB4}, // 1e-34
12398 {0xECB1AD8AEACDD58E, 0xA6274BBDD0FADD61}, // 1e-33
12399 {0x67DE18EDA5814AF2, 0xCFB11EAD453994BA}, // 1e-32
12400 {0x80EACF948770CED7, 0x81CEB32C4B43FCF4}, // 1e-31
12401 {0xA1258379A94D028D, 0xA2425FF75E14FC31}, // 1e-30
12402 {0x096EE45813A04330, 0xCAD2F7F5359A3B3E}, // 1e-29
12403 {0x8BCA9D6E188853FC, 0xFD87B5F28300CA0D}, // 1e-28
12404 {0x775EA264CF55347D, 0x9E74D1B791E07E48}, // 1e-27
12405 {0x95364AFE032A819D, 0xC612062576589DDA}, // 1e-26
12406 {0x3A83DDBD83F52204, 0xF79687AED3EEC551}, // 1e-25
12407 {0xC4926A9672793542, 0x9ABE14CD44753B52}, // 1e-24
12408 {0x75B7053C0F178293, 0xC16D9A0095928A27}, // 1e-23
12409 {0x5324C68B12DD6338, 0xF1C90080BAF72CB1}, // 1e-22
12410 {0xD3F6FC16EBCA5E03, 0x971DA05074DA7BEE}, // 1e-21
12411 {0x88F4BB1CA6BCF584, 0xBCE5086492111AEA}, // 1e-20
12412 {0x2B31E9E3D06C32E5, 0xEC1E4A7DB69561A5}, // 1e-19
12413 {0x3AFF322E62439FCF, 0x9392EE8E921D5D07}, // 1e-18
12414 {0x09BEFEB9FAD487C2, 0xB877AA3236A4B449}, // 1e-17
12415 {0x4C2EBE687989A9B3, 0xE69594BEC44DE15B}, // 1e-16
12416 {0x0F9D37014BF60A10, 0x901D7CF73AB0ACD9}, // 1e-15
12417 {0x538484C19EF38C94, 0xB424DC35095CD80F}, // 1e-14
12418 {0x2865A5F206B06FB9, 0xE12E13424BB40E13}, // 1e-13
12419 {0xF93F87B7442E45D3, 0x8CBCCC096F5088CB}, // 1e-12
12420 {0xF78F69A51539D748, 0xAFEBFF0BCB24AAFE}, // 1e-11
12421 {0xB573440E5A884D1B, 0xDBE6FECEBDEDD5BE}, // 1e-10
12422 {0x31680A88F8953030, 0x89705F4136B4A597}, // 1e-9
12423 {0xFDC20D2B36BA7C3D, 0xABCC77118461CEFC}, // 1e-8
12424 {0x3D32907604691B4C, 0xD6BF94D5E57A42BC}, // 1e-7
12425 {0xA63F9A49C2C1B10F, 0x8637BD05AF6C69B5}, // 1e-6
12426 {0x0FCF80DC33721D53, 0xA7C5AC471B478423}, // 1e-5
12427 {0xD3C36113404EA4A8, 0xD1B71758E219652B}, // 1e-4
12428 {0x645A1CAC083126E9, 0x83126E978D4FDF3B}, // 1e-3
12429 {0x3D70A3D70A3D70A3, 0xA3D70A3D70A3D70A}, // 1e-2
12430 {0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC}, // 1e-1
12431 {0x0000000000000000, 0x8000000000000000}, // 1e0
12432 {0x0000000000000000, 0xA000000000000000}, // 1e1
12433 {0x0000000000000000, 0xC800000000000000}, // 1e2
12434 {0x0000000000000000, 0xFA00000000000000}, // 1e3
12435 {0x0000000000000000, 0x9C40000000000000}, // 1e4
12436 {0x0000000000000000, 0xC350000000000000}, // 1e5
12437 {0x0000000000000000, 0xF424000000000000}, // 1e6
12438 {0x0000000000000000, 0x9896800000000000}, // 1e7
12439 {0x0000000000000000, 0xBEBC200000000000}, // 1e8
12440 {0x0000000000000000, 0xEE6B280000000000}, // 1e9
12441 {0x0000000000000000, 0x9502F90000000000}, // 1e10
12442 {0x0000000000000000, 0xBA43B74000000000}, // 1e11
12443 {0x0000000000000000, 0xE8D4A51000000000}, // 1e12
12444 {0x0000000000000000, 0x9184E72A00000000}, // 1e13
12445 {0x0000000000000000, 0xB5E620F480000000}, // 1e14
12446 {0x0000000000000000, 0xE35FA931A0000000}, // 1e15
12447 {0x0000000000000000, 0x8E1BC9BF04000000}, // 1e16
12448 {0x0000000000000000, 0xB1A2BC2EC5000000}, // 1e17
12449 {0x0000000000000000, 0xDE0B6B3A76400000}, // 1e18
12450 {0x0000000000000000, 0x8AC7230489E80000}, // 1e19
12451 {0x0000000000000000, 0xAD78EBC5AC620000}, // 1e20
12452 {0x0000000000000000, 0xD8D726B7177A8000}, // 1e21
12453 {0x0000000000000000, 0x878678326EAC9000}, // 1e22
12454 {0x0000000000000000, 0xA968163F0A57B400}, // 1e23
12455 {0x0000000000000000, 0xD3C21BCECCEDA100}, // 1e24
12456 {0x0000000000000000, 0x84595161401484A0}, // 1e25
12457 {0x0000000000000000, 0xA56FA5B99019A5C8}, // 1e26
12458 {0x0000000000000000, 0xCECB8F27F4200F3A}, // 1e27
12459 {0x4000000000000000, 0x813F3978F8940984}, // 1e28
12460 {0x5000000000000000, 0xA18F07D736B90BE5}, // 1e29
12461 {0xA400000000000000, 0xC9F2C9CD04674EDE}, // 1e30
12462 {0x4D00000000000000, 0xFC6F7C4045812296}, // 1e31
12463 {0xF020000000000000, 0x9DC5ADA82B70B59D}, // 1e32
12464 {0x6C28000000000000, 0xC5371912364CE305}, // 1e33
12465 {0xC732000000000000, 0xF684DF56C3E01BC6}, // 1e34
12466 {0x3C7F400000000000, 0x9A130B963A6C115C}, // 1e35
12467 {0x4B9F100000000000, 0xC097CE7BC90715B3}, // 1e36
12468 {0x1E86D40000000000, 0xF0BDC21ABB48DB20}, // 1e37
12469 {0x1314448000000000, 0x96769950B50D88F4}, // 1e38
12470 {0x17D955A000000000, 0xBC143FA4E250EB31}, // 1e39
12471 {0x5DCFAB0800000000, 0xEB194F8E1AE525FD}, // 1e40
12472 {0x5AA1CAE500000000, 0x92EFD1B8D0CF37BE}, // 1e41
12473 {0xF14A3D9E40000000, 0xB7ABC627050305AD}, // 1e42
12474 {0x6D9CCD05D0000000, 0xE596B7B0C643C719}, // 1e43
12475 {0xE4820023A2000000, 0x8F7E32CE7BEA5C6F}, // 1e44
12476 {0xDDA2802C8A800000, 0xB35DBF821AE4F38B}, // 1e45
12477 {0xD50B2037AD200000, 0xE0352F62A19E306E}, // 1e46
12478 {0x4526F422CC340000, 0x8C213D9DA502DE45}, // 1e47
12479 {0x9670B12B7F410000, 0xAF298D050E4395D6}, // 1e48
12480 {0x3C0CDD765F114000, 0xDAF3F04651D47B4C}, // 1e49
12481 {0xA5880A69FB6AC800, 0x88D8762BF324CD0F}, // 1e50
12482 {0x8EEA0D047A457A00, 0xAB0E93B6EFEE0053}, // 1e51
12483 {0x72A4904598D6D880, 0xD5D238A4ABE98068}, // 1e52
12484 {0x47A6DA2B7F864750, 0x85A36366EB71F041}, // 1e53
12485 {0x999090B65F67D924, 0xA70C3C40A64E6C51}, // 1e54
12486 {0xFFF4B4E3F741CF6D, 0xD0CF4B50CFE20765}, // 1e55
12487 {0xBFF8F10E7A8921A4, 0x82818F1281ED449F}, // 1e56
12488 {0xAFF72D52192B6A0D, 0xA321F2D7226895C7}, // 1e57
12489 {0x9BF4F8A69F764490, 0xCBEA6F8CEB02BB39}, // 1e58
12490 {0x02F236D04753D5B4, 0xFEE50B7025C36A08}, // 1e59
12491 {0x01D762422C946590, 0x9F4F2726179A2245}, // 1e60
12492 {0x424D3AD2B7B97EF5, 0xC722F0EF9D80AAD6}, // 1e61
12493 {0xD2E0898765A7DEB2, 0xF8EBAD2B84E0D58B}, // 1e62
12494 {0x63CC55F49F88EB2F, 0x9B934C3B330C8577}, // 1e63
12495 {0x3CBF6B71C76B25FB, 0xC2781F49FFCFA6D5}, // 1e64
12496 {0x8BEF464E3945EF7A, 0xF316271C7FC3908A}, // 1e65
12497 {0x97758BF0E3CBB5AC, 0x97EDD871CFDA3A56}, // 1e66
12498 {0x3D52EEED1CBEA317, 0xBDE94E8E43D0C8EC}, // 1e67
12499 {0x4CA7AAA863EE4BDD, 0xED63A231D4C4FB27}, // 1e68
12500 {0x8FE8CAA93E74EF6A, 0x945E455F24FB1CF8}, // 1e69
12501 {0xB3E2FD538E122B44, 0xB975D6B6EE39E436}, // 1e70
12502 {0x60DBBCA87196B616, 0xE7D34C64A9C85D44}, // 1e71
12503 {0xBC8955E946FE31CD, 0x90E40FBEEA1D3A4A}, // 1e72
12504 {0x6BABAB6398BDBE41, 0xB51D13AEA4A488DD}, // 1e73
12505 {0xC696963C7EED2DD1, 0xE264589A4DCDAB14}, // 1e74
12506 {0xFC1E1DE5CF543CA2, 0x8D7EB76070A08AEC}, // 1e75
12507 {0x3B25A55F43294BCB, 0xB0DE65388CC8ADA8}, // 1e76
12508 {0x49EF0EB713F39EBE, 0xDD15FE86AFFAD912}, // 1e77
12509 {0x6E3569326C784337, 0x8A2DBF142DFCC7AB}, // 1e78
12510 {0x49C2C37F07965404, 0xACB92ED9397BF996}, // 1e79
12511 {0xDC33745EC97BE906, 0xD7E77A8F87DAF7FB}, // 1e80
12512 {0x69A028BB3DED71A3, 0x86F0AC99B4E8DAFD}, // 1e81
12513 {0xC40832EA0D68CE0C, 0xA8ACD7C0222311BC}, // 1e82
12514 {0xF50A3FA490C30190, 0xD2D80DB02AABD62B}, // 1e83
12515 {0x792667C6DA79E0FA, 0x83C7088E1AAB65DB}, // 1e84
12516 {0x577001B891185938, 0xA4B8CAB1A1563F52}, // 1e85
12517 {0xED4C0226B55E6F86, 0xCDE6FD5E09ABCF26}, // 1e86
12518 {0x544F8158315B05B4, 0x80B05E5AC60B6178}, // 1e87
12519 {0x696361AE3DB1C721, 0xA0DC75F1778E39D6}, // 1e88
12520 {0x03BC3A19CD1E38E9, 0xC913936DD571C84C}, // 1e89
12521 {0x04AB48A04065C723, 0xFB5878494ACE3A5F}, // 1e90
12522 {0x62EB0D64283F9C76, 0x9D174B2DCEC0E47B}, // 1e91
12523 {0x3BA5D0BD324F8394, 0xC45D1DF942711D9A}, // 1e92
12524 {0xCA8F44EC7EE36479, 0xF5746577930D6500}, // 1e93
12525 {0x7E998B13CF4E1ECB, 0x9968BF6ABBE85F20}, // 1e94
12526 {0x9E3FEDD8C321A67E, 0xBFC2EF456AE276E8}, // 1e95
12527 {0xC5CFE94EF3EA101E, 0xEFB3AB16C59B14A2}, // 1e96
12528 {0xBBA1F1D158724A12, 0x95D04AEE3B80ECE5}, // 1e97
12529 {0x2A8A6E45AE8EDC97, 0xBB445DA9CA61281F}, // 1e98
12530 {0xF52D09D71A3293BD, 0xEA1575143CF97226}, // 1e99
12531 {0x593C2626705F9C56, 0x924D692CA61BE758}, // 1e100
12532 {0x6F8B2FB00C77836C, 0xB6E0C377CFA2E12E}, // 1e101
12533 {0x0B6DFB9C0F956447, 0xE498F455C38B997A}, // 1e102
12534 {0x4724BD4189BD5EAC, 0x8EDF98B59A373FEC}, // 1e103
12535 {0x58EDEC91EC2CB657, 0xB2977EE300C50FE7}, // 1e104
12536 {0x2F2967B66737E3ED, 0xDF3D5E9BC0F653E1}, // 1e105
12537 {0xBD79E0D20082EE74, 0x8B865B215899F46C}, // 1e106
12538 {0xECD8590680A3AA11, 0xAE67F1E9AEC07187}, // 1e107
12539 {0xE80E6F4820CC9495, 0xDA01EE641A708DE9}, // 1e108
12540 {0x3109058D147FDCDD, 0x884134FE908658B2}, // 1e109
12541 {0xBD4B46F0599FD415, 0xAA51823E34A7EEDE}, // 1e110
12542 {0x6C9E18AC7007C91A, 0xD4E5E2CDC1D1EA96}, // 1e111
12543 {0x03E2CF6BC604DDB0, 0x850FADC09923329E}, // 1e112
12544 {0x84DB8346B786151C, 0xA6539930BF6BFF45}, // 1e113
12545 {0xE612641865679A63, 0xCFE87F7CEF46FF16}, // 1e114
12546 {0x4FCB7E8F3F60C07E, 0x81F14FAE158C5F6E}, // 1e115
12547 {0xE3BE5E330F38F09D, 0xA26DA3999AEF7749}, // 1e116
12548 {0x5CADF5BFD3072CC5, 0xCB090C8001AB551C}, // 1e117
12549 {0x73D9732FC7C8F7F6, 0xFDCB4FA002162A63}, // 1e118
12550 {0x2867E7FDDCDD9AFA, 0x9E9F11C4014DDA7E}, // 1e119
12551 {0xB281E1FD541501B8, 0xC646D63501A1511D}, // 1e120
12552 {0x1F225A7CA91A4226, 0xF7D88BC24209A565}, // 1e121
12553 {0x3375788DE9B06958, 0x9AE757596946075F}, // 1e122
12554 {0x0052D6B1641C83AE, 0xC1A12D2FC3978937}, // 1e123
12555 {0xC0678C5DBD23A49A, 0xF209787BB47D6B84}, // 1e124
12556 {0xF840B7BA963646E0, 0x9745EB4D50CE6332}, // 1e125
12557 {0xB650E5A93BC3D898, 0xBD176620A501FBFF}, // 1e126
12558 {0xA3E51F138AB4CEBE, 0xEC5D3FA8CE427AFF}, // 1e127
12559 {0xC66F336C36B10137, 0x93BA47C980E98CDF}, // 1e128
12560 {0xB80B0047445D4184, 0xB8A8D9BBE123F017}, // 1e129
12561 {0xA60DC059157491E5, 0xE6D3102AD96CEC1D}, // 1e130
12562 {0x87C89837AD68DB2F, 0x9043EA1AC7E41392}, // 1e131
12563 {0x29BABE4598C311FB, 0xB454E4A179DD1877}, // 1e132
12564 {0xF4296DD6FEF3D67A, 0xE16A1DC9D8545E94}, // 1e133
12565 {0x1899E4A65F58660C, 0x8CE2529E2734BB1D}, // 1e134
12566 {0x5EC05DCFF72E7F8F, 0xB01AE745B101E9E4}, // 1e135
12567 {0x76707543F4FA1F73, 0xDC21A1171D42645D}, // 1e136
12568 {0x6A06494A791C53A8, 0x899504AE72497EBA}, // 1e137
12569 {0x0487DB9D17636892, 0xABFA45DA0EDBDE69}, // 1e138
12570 {0x45A9D2845D3C42B6, 0xD6F8D7509292D603}, // 1e139
12571 {0x0B8A2392BA45A9B2, 0x865B86925B9BC5C2}, // 1e140
12572 {0x8E6CAC7768D7141E, 0xA7F26836F282B732}, // 1e141
12573 {0x3207D795430CD926, 0xD1EF0244AF2364FF}, // 1e142
12574 {0x7F44E6BD49E807B8, 0x8335616AED761F1F}, // 1e143
12575 {0x5F16206C9C6209A6, 0xA402B9C5A8D3A6E7}, // 1e144
12576 {0x36DBA887C37A8C0F, 0xCD036837130890A1}, // 1e145
12577 {0xC2494954DA2C9789, 0x802221226BE55A64}, // 1e146
12578 {0xF2DB9BAA10B7BD6C, 0xA02AA96B06DEB0FD}, // 1e147
12579 {0x6F92829494E5ACC7, 0xC83553C5C8965D3D}, // 1e148
12580 {0xCB772339BA1F17F9, 0xFA42A8B73ABBF48C}, // 1e149
12581 {0xFF2A760414536EFB, 0x9C69A97284B578D7}, // 1e150
12582 {0xFEF5138519684ABA, 0xC38413CF25E2D70D}, // 1e151
12583 {0x7EB258665FC25D69, 0xF46518C2EF5B8CD1}, // 1e152
12584 {0xEF2F773FFBD97A61, 0x98BF2F79D5993802}, // 1e153
12585 {0xAAFB550FFACFD8FA, 0xBEEEFB584AFF8603}, // 1e154
12586 {0x95BA2A53F983CF38, 0xEEAABA2E5DBF6784}, // 1e155
12587 {0xDD945A747BF26183, 0x952AB45CFA97A0B2}, // 1e156
12588 {0x94F971119AEEF9E4, 0xBA756174393D88DF}, // 1e157
12589 {0x7A37CD5601AAB85D, 0xE912B9D1478CEB17}, // 1e158
12590 {0xAC62E055C10AB33A, 0x91ABB422CCB812EE}, // 1e159
12591 {0x577B986B314D6009, 0xB616A12B7FE617AA}, // 1e160
12592 {0xED5A7E85FDA0B80B, 0xE39C49765FDF9D94}, // 1e161
12593 {0x14588F13BE847307, 0x8E41ADE9FBEBC27D}, // 1e162
12594 {0x596EB2D8AE258FC8, 0xB1D219647AE6B31C}, // 1e163
12595 {0x6FCA5F8ED9AEF3BB, 0xDE469FBD99A05FE3}, // 1e164
12596 {0x25DE7BB9480D5854, 0x8AEC23D680043BEE}, // 1e165
12597 {0xAF561AA79A10AE6A, 0xADA72CCC20054AE9}, // 1e166
12598 {0x1B2BA1518094DA04, 0xD910F7FF28069DA4}, // 1e167
12599 {0x90FB44D2F05D0842, 0x87AA9AFF79042286}, // 1e168
12600 {0x353A1607AC744A53, 0xA99541BF57452B28}, // 1e169
12601 {0x42889B8997915CE8, 0xD3FA922F2D1675F2}, // 1e170
12602 {0x69956135FEBADA11, 0x847C9B5D7C2E09B7}, // 1e171
12603 {0x43FAB9837E699095, 0xA59BC234DB398C25}, // 1e172
12604 {0x94F967E45E03F4BB, 0xCF02B2C21207EF2E}, // 1e173
12605 {0x1D1BE0EEBAC278F5, 0x8161AFB94B44F57D}, // 1e174
12606 {0x6462D92A69731732, 0xA1BA1BA79E1632DC}, // 1e175
12607 {0x7D7B8F7503CFDCFE, 0xCA28A291859BBF93}, // 1e176
12608 {0x5CDA735244C3D43E, 0xFCB2CB35E702AF78}, // 1e177
12609 {0x3A0888136AFA64A7, 0x9DEFBF01B061ADAB}, // 1e178
12610 {0x088AAA1845B8FDD0, 0xC56BAEC21C7A1916}, // 1e179
12611 {0x8AAD549E57273D45, 0xF6C69A72A3989F5B}, // 1e180
12612 {0x36AC54E2F678864B, 0x9A3C2087A63F6399}, // 1e181
12613 {0x84576A1BB416A7DD, 0xC0CB28A98FCF3C7F}, // 1e182
12614 {0x656D44A2A11C51D5, 0xF0FDF2D3F3C30B9F}, // 1e183
12615 {0x9F644AE5A4B1B325, 0x969EB7C47859E743}, // 1e184
12616 {0x873D5D9F0DDE1FEE, 0xBC4665B596706114}, // 1e185
12617 {0xA90CB506D155A7EA, 0xEB57FF22FC0C7959}, // 1e186
12618 {0x09A7F12442D588F2, 0x9316FF75DD87CBD8}, // 1e187
12619 {0x0C11ED6D538AEB2F, 0xB7DCBF5354E9BECE}, // 1e188
12620 {0x8F1668C8A86DA5FA, 0xE5D3EF282A242E81}, // 1e189
12621 {0xF96E017D694487BC, 0x8FA475791A569D10}, // 1e190
12622 {0x37C981DCC395A9AC, 0xB38D92D760EC4455}, // 1e191
12623 {0x85BBE253F47B1417, 0xE070F78D3927556A}, // 1e192
12624 {0x93956D7478CCEC8E, 0x8C469AB843B89562}, // 1e193
12625 {0x387AC8D1970027B2, 0xAF58416654A6BABB}, // 1e194
12626 {0x06997B05FCC0319E, 0xDB2E51BFE9D0696A}, // 1e195
12627 {0x441FECE3BDF81F03, 0x88FCF317F22241E2}, // 1e196
12628 {0xD527E81CAD7626C3, 0xAB3C2FDDEEAAD25A}, // 1e197
12629 {0x8A71E223D8D3B074, 0xD60B3BD56A5586F1}, // 1e198
12630 {0xF6872D5667844E49, 0x85C7056562757456}, // 1e199
12631 {0xB428F8AC016561DB, 0xA738C6BEBB12D16C}, // 1e200
12632 {0xE13336D701BEBA52, 0xD106F86E69D785C7}, // 1e201
12633 {0xECC0024661173473, 0x82A45B450226B39C}, // 1e202
12634 {0x27F002D7F95D0190, 0xA34D721642B06084}, // 1e203
12635 {0x31EC038DF7B441F4, 0xCC20CE9BD35C78A5}, // 1e204
12636 {0x7E67047175A15271, 0xFF290242C83396CE}, // 1e205
12637 {0x0F0062C6E984D386, 0x9F79A169BD203E41}, // 1e206
12638 {0x52C07B78A3E60868, 0xC75809C42C684DD1}, // 1e207
12639 {0xA7709A56CCDF8A82, 0xF92E0C3537826145}, // 1e208
12640 {0x88A66076400BB691, 0x9BBCC7A142B17CCB}, // 1e209
12641 {0x6ACFF893D00EA435, 0xC2ABF989935DDBFE}, // 1e210
12642 {0x0583F6B8C4124D43, 0xF356F7EBF83552FE}, // 1e211
12643 {0xC3727A337A8B704A, 0x98165AF37B2153DE}, // 1e212
12644 {0x744F18C0592E4C5C, 0xBE1BF1B059E9A8D6}, // 1e213
12645 {0x1162DEF06F79DF73, 0xEDA2EE1C7064130C}, // 1e214
12646 {0x8ADDCB5645AC2BA8, 0x9485D4D1C63E8BE7}, // 1e215
12647 {0x6D953E2BD7173692, 0xB9A74A0637CE2EE1}, // 1e216
12648 {0xC8FA8DB6CCDD0437, 0xE8111C87C5C1BA99}, // 1e217
12649 {0x1D9C9892400A22A2, 0x910AB1D4DB9914A0}, // 1e218
12650 {0x2503BEB6D00CAB4B, 0xB54D5E4A127F59C8}, // 1e219
12651 {0x2E44AE64840FD61D, 0xE2A0B5DC971F303A}, // 1e220
12652 {0x5CEAECFED289E5D2, 0x8DA471A9DE737E24}, // 1e221
12653 {0x7425A83E872C5F47, 0xB10D8E1456105DAD}, // 1e222
12654 {0xD12F124E28F77719, 0xDD50F1996B947518}, // 1e223
12655 {0x82BD6B70D99AAA6F, 0x8A5296FFE33CC92F}, // 1e224
12656 {0x636CC64D1001550B, 0xACE73CBFDC0BFB7B}, // 1e225
12657 {0x3C47F7E05401AA4E, 0xD8210BEFD30EFA5A}, // 1e226
12658 {0x65ACFAEC34810A71, 0x8714A775E3E95C78}, // 1e227
12659 {0x7F1839A741A14D0D, 0xA8D9D1535CE3B396}, // 1e228
12660 {0x1EDE48111209A050, 0xD31045A8341CA07C}, // 1e229
12661 {0x934AED0AAB460432, 0x83EA2B892091E44D}, // 1e230
12662 {0xF81DA84D5617853F, 0xA4E4B66B68B65D60}, // 1e231
12663 {0x36251260AB9D668E, 0xCE1DE40642E3F4B9}, // 1e232
12664 {0xC1D72B7C6B426019, 0x80D2AE83E9CE78F3}, // 1e233
12665 {0xB24CF65B8612F81F, 0xA1075A24E4421730}, // 1e234
12666 {0xDEE033F26797B627, 0xC94930AE1D529CFC}, // 1e235
12667 {0x169840EF017DA3B1, 0xFB9B7CD9A4A7443C}, // 1e236
12668 {0x8E1F289560EE864E, 0x9D412E0806E88AA5}, // 1e237
12669 {0xF1A6F2BAB92A27E2, 0xC491798A08A2AD4E}, // 1e238
12670 {0xAE10AF696774B1DB, 0xF5B5D7EC8ACB58A2}, // 1e239
12671 {0xACCA6DA1E0A8EF29, 0x9991A6F3D6BF1765}, // 1e240
12672 {0x17FD090A58D32AF3, 0xBFF610B0CC6EDD3F}, // 1e241
12673 {0xDDFC4B4CEF07F5B0, 0xEFF394DCFF8A948E}, // 1e242
12674 {0x4ABDAF101564F98E, 0x95F83D0A1FB69CD9}, // 1e243
12675 {0x9D6D1AD41ABE37F1, 0xBB764C4CA7A4440F}, // 1e244
12676 {0x84C86189216DC5ED, 0xEA53DF5FD18D5513}, // 1e245
12677 {0x32FD3CF5B4E49BB4, 0x92746B9BE2F8552C}, // 1e246
12678 {0x3FBC8C33221DC2A1, 0xB7118682DBB66A77}, // 1e247
12679 {0x0FABAF3FEAA5334A, 0xE4D5E82392A40515}, // 1e248
12680 {0x29CB4D87F2A7400E, 0x8F05B1163BA6832D}, // 1e249
12681 {0x743E20E9EF511012, 0xB2C71D5BCA9023F8}, // 1e250
12682 {0x914DA9246B255416, 0xDF78E4B2BD342CF6}, // 1e251
12683 {0x1AD089B6C2F7548E, 0x8BAB8EEFB6409C1A}, // 1e252
12684 {0xA184AC2473B529B1, 0xAE9672ABA3D0C320}, // 1e253
12685 {0xC9E5D72D90A2741E, 0xDA3C0F568CC4F3E8}, // 1e254
12686 {0x7E2FA67C7A658892, 0x8865899617FB1871}, // 1e255
12687 {0xDDBB901B98FEEAB7, 0xAA7EEBFB9DF9DE8D}, // 1e256
12688 {0x552A74227F3EA565, 0xD51EA6FA85785631}, // 1e257
12689 {0xD53A88958F87275F, 0x8533285C936B35DE}, // 1e258
12690 {0x8A892ABAF368F137, 0xA67FF273B8460356}, // 1e259
12691 {0x2D2B7569B0432D85, 0xD01FEF10A657842C}, // 1e260
12692 {0x9C3B29620E29FC73, 0x8213F56A67F6B29B}, // 1e261
12693 {0x8349F3BA91B47B8F, 0xA298F2C501F45F42}, // 1e262
12694 {0x241C70A936219A73, 0xCB3F2F7642717713}, // 1e263
12695 {0xED238CD383AA0110, 0xFE0EFB53D30DD4D7}, // 1e264
12696 {0xF4363804324A40AA, 0x9EC95D1463E8A506}, // 1e265
12697 {0xB143C6053EDCD0D5, 0xC67BB4597CE2CE48}, // 1e266
12698 {0xDD94B7868E94050A, 0xF81AA16FDC1B81DA}, // 1e267
12699 {0xCA7CF2B4191C8326, 0x9B10A4E5E9913128}, // 1e268
12700 {0xFD1C2F611F63A3F0, 0xC1D4CE1F63F57D72}, // 1e269
12701 {0xBC633B39673C8CEC, 0xF24A01A73CF2DCCF}, // 1e270
12702 {0xD5BE0503E085D813, 0x976E41088617CA01}, // 1e271
12703 {0x4B2D8644D8A74E18, 0xBD49D14AA79DBC82}, // 1e272
12704 {0xDDF8E7D60ED1219E, 0xEC9C459D51852BA2}, // 1e273
12705 {0xCABB90E5C942B503, 0x93E1AB8252F33B45}, // 1e274
12706 {0x3D6A751F3B936243, 0xB8DA1662E7B00A17}, // 1e275
12707 {0x0CC512670A783AD4, 0xE7109BFBA19C0C9D}, // 1e276
12708 {0x27FB2B80668B24C5, 0x906A617D450187E2}, // 1e277
12709 {0xB1F9F660802DEDF6, 0xB484F9DC9641E9DA}, // 1e278
12710 {0x5E7873F8A0396973, 0xE1A63853BBD26451}, // 1e279
12711 {0xDB0B487B6423E1E8, 0x8D07E33455637EB2}, // 1e280
12712 {0x91CE1A9A3D2CDA62, 0xB049DC016ABC5E5F}, // 1e281
12713 {0x7641A140CC7810FB, 0xDC5C5301C56B75F7}, // 1e282
12714 {0xA9E904C87FCB0A9D, 0x89B9B3E11B6329BA}, // 1e283
12715 {0x546345FA9FBDCD44, 0xAC2820D9623BF429}, // 1e284
12716 {0xA97C177947AD4095, 0xD732290FBACAF133}, // 1e285
12717 {0x49ED8EABCCCC485D, 0x867F59A9D4BED6C0}, // 1e286
12718 {0x5C68F256BFFF5A74, 0xA81F301449EE8C70}, // 1e287
12719 {0x73832EEC6FFF3111, 0xD226FC195C6A2F8C}, // 1e288
12720};
12721
12722// wuffs_base__private_implementation__f64_powers_of_10 holds powers of 10 that
12723// can be exactly represented by a float64 (what C calls a double).
12724static const double wuffs_base__private_implementation__f64_powers_of_10[23] = {
12725 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
12726 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
12727};
12728
12729// ---------------- IEEE 754 Floating Point
12730
12731WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16 //
12732wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f) {
12733 uint64_t u = 0;
12734 if (sizeof(uint64_t) == sizeof(double)) {
12735 memcpy(&u, &f, sizeof(uint64_t));
12736 }
12737 uint16_t neg = ((uint16_t)((u >> 63) << 15));
12738 u &= 0x7FFFFFFFFFFFFFFF;
12739 uint64_t exp = u >> 52;
12740 uint64_t man = u & 0x000FFFFFFFFFFFFF;
12741
12742 if (exp == 0x7FF) {
12743 if (man == 0) { // Infinity.
12744 wuffs_base__lossy_value_u16 ret;
12745 ret.value = neg | 0x7C00;
12746 ret.lossy = false;
12747 return ret;
12748 }
12749 // NaN. Shift the 52 mantissa bits to 10 mantissa bits, keeping the most
12750 // significant mantissa bit (quiet vs signaling NaNs). Also set the low 9
12751 // bits of ret.value so that the 10-bit mantissa is non-zero.
12752 wuffs_base__lossy_value_u16 ret;
12753 ret.value = neg | 0x7DFF | ((uint16_t)(man >> 42));
12754 ret.lossy = false;
12755 return ret;
12756
12757 } else if (exp > 0x40E) { // Truncate to the largest finite f16.
12758 wuffs_base__lossy_value_u16 ret;
12759 ret.value = neg | 0x7BFF;
12760 ret.lossy = true;
12761 return ret;
12762
12763 } else if (exp <= 0x3E6) { // Truncate to zero.
12764 wuffs_base__lossy_value_u16 ret;
12765 ret.value = neg;
12766 ret.lossy = (u != 0);
12767 return ret;
12768
12769 } else if (exp <= 0x3F0) { // Normal f64, subnormal f16.
12770 // Convert from a 53-bit mantissa (after realizing the implicit bit) to a
12771 // 10-bit mantissa and then adjust for the exponent.
12772 man |= 0x0010000000000000;
12773 uint32_t shift = ((uint32_t)(1051 - exp)); // 1051 = 0x3F0 + 53 - 10.
12774 uint64_t shifted_man = man >> shift;
12775 wuffs_base__lossy_value_u16 ret;
12776 ret.value = neg | ((uint16_t)shifted_man);
12777 ret.lossy = (shifted_man << shift) != man;
12778 return ret;
12779 }
12780
12781 // Normal f64, normal f16.
12782
12783 // Re-bias from 1023 to 15 and shift above f16's 10 mantissa bits.
12784 exp = (exp - 1008) << 10; // 1008 = 1023 - 15 = 0x3FF - 0xF.
12785
12786 // Convert from a 52-bit mantissa (excluding the implicit bit) to a 10-bit
12787 // mantissa (again excluding the implicit bit). We lose some information if
12788 // any of the bottom 42 bits are non-zero.
12789 wuffs_base__lossy_value_u16 ret;
12790 ret.value = neg | ((uint16_t)exp) | ((uint16_t)(man >> 42));
12791 ret.lossy = (man << 22) != 0;
12792 return ret;
12793}
12794
12795WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32 //
12796wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f) {
12797 uint64_t u = 0;
12798 if (sizeof(uint64_t) == sizeof(double)) {
12799 memcpy(&u, &f, sizeof(uint64_t));
12800 }
12801 uint32_t neg = ((uint32_t)(u >> 63)) << 31;
12802 u &= 0x7FFFFFFFFFFFFFFF;
12803 uint64_t exp = u >> 52;
12804 uint64_t man = u & 0x000FFFFFFFFFFFFF;
12805
12806 if (exp == 0x7FF) {
12807 if (man == 0) { // Infinity.
12808 wuffs_base__lossy_value_u32 ret;
12809 ret.value = neg | 0x7F800000;
12810 ret.lossy = false;
12811 return ret;
12812 }
12813 // NaN. Shift the 52 mantissa bits to 23 mantissa bits, keeping the most
12814 // significant mantissa bit (quiet vs signaling NaNs). Also set the low 22
12815 // bits of ret.value so that the 23-bit mantissa is non-zero.
12816 wuffs_base__lossy_value_u32 ret;
12817 ret.value = neg | 0x7FBFFFFF | ((uint32_t)(man >> 29));
12818 ret.lossy = false;
12819 return ret;
12820
12821 } else if (exp > 0x47E) { // Truncate to the largest finite f32.
12822 wuffs_base__lossy_value_u32 ret;
12823 ret.value = neg | 0x7F7FFFFF;
12824 ret.lossy = true;
12825 return ret;
12826
12827 } else if (exp <= 0x369) { // Truncate to zero.
12828 wuffs_base__lossy_value_u32 ret;
12829 ret.value = neg;
12830 ret.lossy = (u != 0);
12831 return ret;
12832
12833 } else if (exp <= 0x380) { // Normal f64, subnormal f32.
12834 // Convert from a 53-bit mantissa (after realizing the implicit bit) to a
12835 // 23-bit mantissa and then adjust for the exponent.
12836 man |= 0x0010000000000000;
12837 uint32_t shift = ((uint32_t)(926 - exp)); // 926 = 0x380 + 53 - 23.
12838 uint64_t shifted_man = man >> shift;
12839 wuffs_base__lossy_value_u32 ret;
12840 ret.value = neg | ((uint32_t)shifted_man);
12841 ret.lossy = (shifted_man << shift) != man;
12842 return ret;
12843 }
12844
12845 // Normal f64, normal f32.
12846
12847 // Re-bias from 1023 to 127 and shift above f32's 23 mantissa bits.
12848 exp = (exp - 896) << 23; // 896 = 1023 - 127 = 0x3FF - 0x7F.
12849
12850 // Convert from a 52-bit mantissa (excluding the implicit bit) to a 23-bit
12851 // mantissa (again excluding the implicit bit). We lose some information if
12852 // any of the bottom 29 bits are non-zero.
12853 wuffs_base__lossy_value_u32 ret;
12854 ret.value = neg | ((uint32_t)exp) | ((uint32_t)(man >> 29));
12855 ret.lossy = (man << 35) != 0;
12856 return ret;
12857}
12858
12859// --------
12860
12861#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 2047
12862#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 800
12863
12864// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL is the largest N
12865// such that ((10 << N) < (1 << 64)).
12866#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL 60
12867
12868// wuffs_base__private_implementation__high_prec_dec (abbreviated as HPD) is a
12869// fixed precision floating point decimal number, augmented with ±infinity
12870// values, but it cannot represent NaN (Not a Number).
12871//
12872// "High precision" means that the mantissa holds 800 decimal digits. 800 is
12873// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION.
12874//
12875// An HPD isn't for general purpose arithmetic, only for conversions to and
12876// from IEEE 754 double-precision floating point, where the largest and
12877// smallest positive, finite values are approximately 1.8e+308 and 4.9e-324.
12878// HPD exponents above +2047 mean infinity, below -2047 mean zero. The ±2047
12879// bounds are further away from zero than ±(324 + 800), where 800 and 2047 is
12880// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION and
12881// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
12882//
12883// digits[.. num_digits] are the number's digits in big-endian order. The
12884// uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7'
12885// is the ASCII value 0x37.
12886//
12887// decimal_point is the index (within digits) of the decimal point. It may be
12888// negative or be larger than num_digits, in which case the explicit digits are
12889// padded with implicit zeroes.
12890//
12891// For example, if num_digits is 3 and digits is "\x07\x08\x09":
Nigel Taobf9dab32021-11-18 19:19:55 +110012892// - A decimal_point of -2 means ".00789"
12893// - A decimal_point of -1 means ".0789"
12894// - A decimal_point of +0 means ".789"
12895// - A decimal_point of +1 means "7.89"
12896// - A decimal_point of +2 means "78.9"
12897// - A decimal_point of +3 means "789."
12898// - A decimal_point of +4 means "7890."
12899// - A decimal_point of +5 means "78900."
Nigel Taoe360a532021-04-05 22:47:03 +100012900//
12901// As above, a decimal_point higher than +2047 means that the overall value is
12902// infinity, lower than -2047 means zero.
12903//
12904// negative is a sign bit. An HPD can distinguish positive and negative zero.
12905//
12906// truncated is whether there are more than
12907// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION digits, and at
12908// least one of those extra digits are non-zero. The existence of long-tail
12909// digits can affect rounding.
12910//
12911// The "all fields are zero" value is valid, and represents the number +0.
12912typedef struct wuffs_base__private_implementation__high_prec_dec__struct {
12913 uint32_t num_digits;
12914 int32_t decimal_point;
12915 bool negative;
12916 bool truncated;
12917 uint8_t digits[WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION];
12918} wuffs_base__private_implementation__high_prec_dec;
12919
12920// wuffs_base__private_implementation__high_prec_dec__trim trims trailing
12921// zeroes from the h->digits[.. h->num_digits] slice. They have no benefit,
12922// since we explicitly track h->decimal_point.
12923//
12924// Preconditions:
12925// - h is non-NULL.
12926static inline void //
12927wuffs_base__private_implementation__high_prec_dec__trim(
12928 wuffs_base__private_implementation__high_prec_dec* h) {
12929 while ((h->num_digits > 0) && (h->digits[h->num_digits - 1] == 0)) {
12930 h->num_digits--;
12931 }
12932}
12933
12934// wuffs_base__private_implementation__high_prec_dec__assign sets h to
12935// represent the number x.
12936//
12937// Preconditions:
12938// - h is non-NULL.
12939static void //
12940wuffs_base__private_implementation__high_prec_dec__assign(
12941 wuffs_base__private_implementation__high_prec_dec* h,
12942 uint64_t x,
12943 bool negative) {
12944 uint32_t n = 0;
12945
12946 // Set h->digits.
12947 if (x > 0) {
12948 // Calculate the digits, working right-to-left. After we determine n (how
12949 // many digits there are), copy from buf to h->digits.
12950 //
12951 // UINT64_MAX, 18446744073709551615, is 20 digits long. It can be faster to
12952 // copy a constant number of bytes than a variable number (20 instead of
12953 // n). Make buf large enough (and start writing to it from the middle) so
12954 // that can we always copy 20 bytes: the slice buf[(20-n) .. (40-n)].
12955 uint8_t buf[40] = {0};
12956 uint8_t* ptr = &buf[20];
12957 do {
12958 uint64_t remaining = x / 10;
12959 x -= remaining * 10;
12960 ptr--;
12961 *ptr = (uint8_t)x;
12962 n++;
12963 x = remaining;
12964 } while (x > 0);
12965 memcpy(h->digits, ptr, 20);
12966 }
12967
12968 // Set h's other fields.
12969 h->num_digits = n;
12970 h->decimal_point = (int32_t)n;
12971 h->negative = negative;
12972 h->truncated = false;
12973 wuffs_base__private_implementation__high_prec_dec__trim(h);
12974}
12975
12976static wuffs_base__status //
12977wuffs_base__private_implementation__high_prec_dec__parse(
12978 wuffs_base__private_implementation__high_prec_dec* h,
12979 wuffs_base__slice_u8 s,
12980 uint32_t options) {
12981 if (!h) {
12982 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
12983 }
12984 h->num_digits = 0;
12985 h->decimal_point = 0;
12986 h->negative = false;
12987 h->truncated = false;
12988
12989 uint8_t* p = s.ptr;
12990 uint8_t* q = s.ptr + s.len;
12991
12992 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
12993 for (;; p++) {
12994 if (p >= q) {
12995 return wuffs_base__make_status(wuffs_base__error__bad_argument);
12996 } else if (*p != '_') {
12997 break;
12998 }
12999 }
13000 }
13001
13002 // Parse sign.
13003 do {
13004 if (*p == '+') {
13005 p++;
13006 } else if (*p == '-') {
13007 h->negative = true;
13008 p++;
13009 } else {
13010 break;
13011 }
13012 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
13013 for (;; p++) {
13014 if (p >= q) {
13015 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13016 } else if (*p != '_') {
13017 break;
13018 }
13019 }
13020 }
13021 } while (0);
13022
13023 // Parse digits, up to (and including) a '.', 'E' or 'e'. Examples for each
13024 // limb in this if-else chain:
13025 // - "0.789"
13026 // - "1002.789"
13027 // - ".789"
13028 // - Other (invalid input).
13029 uint32_t nd = 0;
13030 int32_t dp = 0;
13031 bool no_digits_before_separator = false;
13032 if (('0' == *p) &&
13033 !(options &
13034 WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES)) {
13035 p++;
13036 for (;; p++) {
13037 if (p >= q) {
13038 goto after_all;
13039 } else if (*p ==
13040 ((options &
13041 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
13042 ? ','
13043 : '.')) {
13044 p++;
13045 goto after_sep;
13046 } else if ((*p == 'E') || (*p == 'e')) {
13047 p++;
13048 goto after_exp;
13049 } else if ((*p != '_') ||
13050 !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
13051 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13052 }
13053 }
13054
13055 } else if (('0' <= *p) && (*p <= '9')) {
13056 if (*p == '0') {
13057 for (; (p < q) && (*p == '0'); p++) {
13058 }
13059 } else {
13060 h->digits[nd++] = (uint8_t)(*p - '0');
13061 dp = (int32_t)nd;
13062 p++;
13063 }
13064
13065 for (;; p++) {
13066 if (p >= q) {
13067 goto after_all;
13068 } else if (('0' <= *p) && (*p <= '9')) {
13069 if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13070 h->digits[nd++] = (uint8_t)(*p - '0');
13071 dp = (int32_t)nd;
13072 } else if ('0' != *p) {
13073 // Long-tail non-zeroes set the truncated bit.
13074 h->truncated = true;
13075 }
13076 } else if (*p ==
13077 ((options &
13078 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
13079 ? ','
13080 : '.')) {
13081 p++;
13082 goto after_sep;
13083 } else if ((*p == 'E') || (*p == 'e')) {
13084 p++;
13085 goto after_exp;
13086 } else if ((*p != '_') ||
13087 !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
13088 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13089 }
13090 }
13091
13092 } else if (*p == ((options &
13093 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
13094 ? ','
13095 : '.')) {
13096 p++;
13097 no_digits_before_separator = true;
13098
13099 } else {
13100 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13101 }
13102
13103after_sep:
13104 for (;; p++) {
13105 if (p >= q) {
13106 goto after_all;
13107 } else if ('0' == *p) {
13108 if (nd == 0) {
13109 // Track leading zeroes implicitly.
13110 dp--;
13111 } else if (nd <
13112 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13113 h->digits[nd++] = (uint8_t)(*p - '0');
13114 }
13115 } else if (('0' < *p) && (*p <= '9')) {
13116 if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13117 h->digits[nd++] = (uint8_t)(*p - '0');
13118 } else {
13119 // Long-tail non-zeroes set the truncated bit.
13120 h->truncated = true;
13121 }
13122 } else if ((*p == 'E') || (*p == 'e')) {
13123 p++;
13124 goto after_exp;
13125 } else if ((*p != '_') ||
13126 !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
13127 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13128 }
13129 }
13130
13131after_exp:
13132 do {
13133 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
13134 for (;; p++) {
13135 if (p >= q) {
13136 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13137 } else if (*p != '_') {
13138 break;
13139 }
13140 }
13141 }
13142
13143 int32_t exp_sign = +1;
13144 if (*p == '+') {
13145 p++;
13146 } else if (*p == '-') {
13147 exp_sign = -1;
13148 p++;
13149 }
13150
13151 int32_t exp = 0;
13152 const int32_t exp_large =
13153 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE +
13154 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION;
13155 bool saw_exp_digits = false;
13156 for (; p < q; p++) {
13157 if ((*p == '_') &&
13158 (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
13159 // No-op.
13160 } else if (('0' <= *p) && (*p <= '9')) {
13161 saw_exp_digits = true;
13162 if (exp < exp_large) {
13163 exp = (10 * exp) + ((int32_t)(*p - '0'));
13164 }
13165 } else {
13166 break;
13167 }
13168 }
13169 if (!saw_exp_digits) {
13170 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13171 }
13172 dp += exp_sign * exp;
13173 } while (0);
13174
13175after_all:
13176 if (p != q) {
13177 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13178 }
13179 h->num_digits = nd;
13180 if (nd == 0) {
13181 if (no_digits_before_separator) {
13182 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13183 }
13184 h->decimal_point = 0;
13185 } else if (dp <
13186 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
13187 h->decimal_point =
13188 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE - 1;
13189 } else if (dp >
13190 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
13191 h->decimal_point =
13192 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + 1;
13193 } else {
13194 h->decimal_point = dp;
13195 }
13196 wuffs_base__private_implementation__high_prec_dec__trim(h);
13197 return wuffs_base__make_status(NULL);
13198}
13199
13200// --------
13201
13202// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits
13203// returns the number of additional decimal digits when left-shifting by shift.
13204//
13205// See below for preconditions.
13206static uint32_t //
13207wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits(
13208 wuffs_base__private_implementation__high_prec_dec* h,
13209 uint32_t shift) {
13210 // Masking with 0x3F should be unnecessary (assuming the preconditions) but
13211 // it's cheap and ensures that we don't overflow the
13212 // wuffs_base__private_implementation__hpd_left_shift array.
13213 shift &= 63;
13214
13215 uint32_t x_a = wuffs_base__private_implementation__hpd_left_shift[shift];
13216 uint32_t x_b = wuffs_base__private_implementation__hpd_left_shift[shift + 1];
13217 uint32_t num_new_digits = x_a >> 11;
13218 uint32_t pow5_a = 0x7FF & x_a;
13219 uint32_t pow5_b = 0x7FF & x_b;
13220
13221 const uint8_t* pow5 =
13222 &wuffs_base__private_implementation__powers_of_5[pow5_a];
13223 uint32_t i = 0;
13224 uint32_t n = pow5_b - pow5_a;
13225 for (; i < n; i++) {
13226 if (i >= h->num_digits) {
13227 return num_new_digits - 1;
13228 } else if (h->digits[i] == pow5[i]) {
13229 continue;
13230 } else if (h->digits[i] < pow5[i]) {
13231 return num_new_digits - 1;
13232 } else {
13233 return num_new_digits;
13234 }
13235 }
13236 return num_new_digits;
13237}
13238
13239// --------
13240
13241// wuffs_base__private_implementation__high_prec_dec__rounded_integer returns
13242// the integral (non-fractional) part of h, provided that it is 18 or fewer
13243// decimal digits. For 19 or more digits, it returns UINT64_MAX. Note that:
Nigel Taobf9dab32021-11-18 19:19:55 +110013244// - (1 << 53) is 9007199254740992, which has 16 decimal digits.
13245// - (1 << 56) is 72057594037927936, which has 17 decimal digits.
13246// - (1 << 59) is 576460752303423488, which has 18 decimal digits.
13247// - (1 << 63) is 9223372036854775808, which has 19 decimal digits.
Nigel Taoe360a532021-04-05 22:47:03 +100013248// and that IEEE 754 double precision has 52 mantissa bits.
13249//
13250// That integral part is rounded-to-even: rounding 7.5 or 8.5 both give 8.
13251//
13252// h's negative bit is ignored: rounding -8.6 returns 9.
13253//
13254// See below for preconditions.
13255static uint64_t //
13256wuffs_base__private_implementation__high_prec_dec__rounded_integer(
13257 wuffs_base__private_implementation__high_prec_dec* h) {
13258 if ((h->num_digits == 0) || (h->decimal_point < 0)) {
13259 return 0;
13260 } else if (h->decimal_point > 18) {
13261 return UINT64_MAX;
13262 }
13263
13264 uint32_t dp = (uint32_t)(h->decimal_point);
13265 uint64_t n = 0;
13266 uint32_t i = 0;
13267 for (; i < dp; i++) {
13268 n = (10 * n) + ((i < h->num_digits) ? h->digits[i] : 0);
13269 }
13270
13271 bool round_up = false;
13272 if (dp < h->num_digits) {
13273 round_up = h->digits[dp] >= 5;
13274 if ((h->digits[dp] == 5) && (dp + 1 == h->num_digits)) {
13275 // We are exactly halfway. If we're truncated, round up, otherwise round
13276 // to even.
13277 round_up = h->truncated || //
13278 ((dp > 0) && (1 & h->digits[dp - 1]));
13279 }
13280 }
13281 if (round_up) {
13282 n++;
13283 }
13284
13285 return n;
13286}
13287
13288// wuffs_base__private_implementation__high_prec_dec__small_xshift shifts h's
13289// number (where 'x' is 'l' or 'r' for left or right) by a small shift value.
13290//
13291// Preconditions:
13292// - h is non-NULL.
13293// - h->decimal_point is "not extreme".
13294// - shift is non-zero.
13295// - shift is "a small shift".
13296//
13297// "Not extreme" means within
13298// ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
13299//
13300// "A small shift" means not more than
13301// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL.
13302//
13303// wuffs_base__private_implementation__high_prec_dec__rounded_integer and
13304// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits
13305// have the same preconditions.
13306//
13307// wuffs_base__private_implementation__high_prec_dec__lshift keeps the first
13308// two preconditions but not the last two. Its shift argument is signed and
13309// does not need to be "small": zero is a no-op, positive means left shift and
13310// negative means right shift.
13311
13312static void //
13313wuffs_base__private_implementation__high_prec_dec__small_lshift(
13314 wuffs_base__private_implementation__high_prec_dec* h,
13315 uint32_t shift) {
13316 if (h->num_digits == 0) {
13317 return;
13318 }
13319 uint32_t num_new_digits =
13320 wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits(
13321 h, shift);
13322 uint32_t rx = h->num_digits - 1; // Read index.
13323 uint32_t wx = h->num_digits - 1 + num_new_digits; // Write index.
13324 uint64_t n = 0;
13325
13326 // Repeat: pick up a digit, put down a digit, right to left.
13327 while (((int32_t)rx) >= 0) {
13328 n += ((uint64_t)(h->digits[rx])) << shift;
13329 uint64_t quo = n / 10;
13330 uint64_t rem = n - (10 * quo);
13331 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13332 h->digits[wx] = (uint8_t)rem;
13333 } else if (rem > 0) {
13334 h->truncated = true;
13335 }
13336 n = quo;
13337 wx--;
13338 rx--;
13339 }
13340
13341 // Put down leading digits, right to left.
13342 while (n > 0) {
13343 uint64_t quo = n / 10;
13344 uint64_t rem = n - (10 * quo);
13345 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13346 h->digits[wx] = (uint8_t)rem;
13347 } else if (rem > 0) {
13348 h->truncated = true;
13349 }
13350 n = quo;
13351 wx--;
13352 }
13353
13354 // Finish.
13355 h->num_digits += num_new_digits;
13356 if (h->num_digits >
13357 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13358 h->num_digits = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION;
13359 }
13360 h->decimal_point += (int32_t)num_new_digits;
13361 wuffs_base__private_implementation__high_prec_dec__trim(h);
13362}
13363
13364static void //
13365wuffs_base__private_implementation__high_prec_dec__small_rshift(
13366 wuffs_base__private_implementation__high_prec_dec* h,
13367 uint32_t shift) {
13368 uint32_t rx = 0; // Read index.
13369 uint32_t wx = 0; // Write index.
13370 uint64_t n = 0;
13371
13372 // Pick up enough leading digits to cover the first shift.
13373 while ((n >> shift) == 0) {
13374 if (rx < h->num_digits) {
13375 // Read a digit.
13376 n = (10 * n) + h->digits[rx++];
13377 } else if (n == 0) {
13378 // h's number used to be zero and remains zero.
13379 return;
13380 } else {
13381 // Read sufficient implicit trailing zeroes.
13382 while ((n >> shift) == 0) {
13383 n = 10 * n;
13384 rx++;
13385 }
13386 break;
13387 }
13388 }
13389 h->decimal_point -= ((int32_t)(rx - 1));
13390 if (h->decimal_point <
13391 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
13392 // After the shift, h's number is effectively zero.
13393 h->num_digits = 0;
13394 h->decimal_point = 0;
13395 h->truncated = false;
13396 return;
13397 }
13398
13399 // Repeat: pick up a digit, put down a digit, left to right.
13400 uint64_t mask = (((uint64_t)(1)) << shift) - 1;
13401 while (rx < h->num_digits) {
13402 uint8_t new_digit = ((uint8_t)(n >> shift));
13403 n = (10 * (n & mask)) + h->digits[rx++];
13404 h->digits[wx++] = new_digit;
13405 }
13406
13407 // Put down trailing digits, left to right.
13408 while (n > 0) {
13409 uint8_t new_digit = ((uint8_t)(n >> shift));
13410 n = 10 * (n & mask);
13411 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13412 h->digits[wx++] = new_digit;
13413 } else if (new_digit > 0) {
13414 h->truncated = true;
13415 }
13416 }
13417
13418 // Finish.
13419 h->num_digits = wx;
13420 wuffs_base__private_implementation__high_prec_dec__trim(h);
13421}
13422
13423static void //
13424wuffs_base__private_implementation__high_prec_dec__lshift(
13425 wuffs_base__private_implementation__high_prec_dec* h,
13426 int32_t shift) {
13427 if (shift > 0) {
13428 while (shift > +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
13429 wuffs_base__private_implementation__high_prec_dec__small_lshift(
13430 h, WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL);
13431 shift -= WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
13432 }
13433 wuffs_base__private_implementation__high_prec_dec__small_lshift(
13434 h, ((uint32_t)(+shift)));
13435 } else if (shift < 0) {
13436 while (shift < -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
13437 wuffs_base__private_implementation__high_prec_dec__small_rshift(
13438 h, WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL);
13439 shift += WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
13440 }
13441 wuffs_base__private_implementation__high_prec_dec__small_rshift(
13442 h, ((uint32_t)(-shift)));
13443 }
13444}
13445
13446// --------
13447
13448// wuffs_base__private_implementation__high_prec_dec__round_etc rounds h's
13449// number. For those functions that take an n argument, rounding produces at
13450// most n digits (which is not necessarily at most n decimal places). Negative
13451// n values are ignored, as well as any n greater than or equal to h's number
13452// of digits. The etc__round_just_enough function implicitly chooses an n to
13453// implement WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION.
13454//
13455// Preconditions:
13456// - h is non-NULL.
13457// - h->decimal_point is "not extreme".
13458//
13459// "Not extreme" means within
13460// ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
13461
13462static void //
13463wuffs_base__private_implementation__high_prec_dec__round_down(
13464 wuffs_base__private_implementation__high_prec_dec* h,
13465 int32_t n) {
13466 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
13467 return;
13468 }
13469 h->num_digits = (uint32_t)(n);
13470 wuffs_base__private_implementation__high_prec_dec__trim(h);
13471}
13472
13473static void //
13474wuffs_base__private_implementation__high_prec_dec__round_up(
13475 wuffs_base__private_implementation__high_prec_dec* h,
13476 int32_t n) {
13477 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
13478 return;
13479 }
13480
13481 for (n--; n >= 0; n--) {
13482 if (h->digits[n] < 9) {
13483 h->digits[n]++;
13484 h->num_digits = (uint32_t)(n + 1);
13485 return;
13486 }
13487 }
13488
13489 // The number is all 9s. Change to a single 1 and adjust the decimal point.
13490 h->digits[0] = 1;
13491 h->num_digits = 1;
13492 h->decimal_point++;
13493}
13494
13495static void //
13496wuffs_base__private_implementation__high_prec_dec__round_nearest(
13497 wuffs_base__private_implementation__high_prec_dec* h,
13498 int32_t n) {
13499 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
13500 return;
13501 }
13502 bool up = h->digits[n] >= 5;
13503 if ((h->digits[n] == 5) && ((n + 1) == ((int32_t)(h->num_digits)))) {
13504 up = h->truncated || //
13505 ((n > 0) && ((h->digits[n - 1] & 1) != 0));
13506 }
13507
13508 if (up) {
13509 wuffs_base__private_implementation__high_prec_dec__round_up(h, n);
13510 } else {
13511 wuffs_base__private_implementation__high_prec_dec__round_down(h, n);
13512 }
13513}
13514
13515static void //
13516wuffs_base__private_implementation__high_prec_dec__round_just_enough(
13517 wuffs_base__private_implementation__high_prec_dec* h,
13518 int32_t exp2,
13519 uint64_t mantissa) {
13520 // The magic numbers 52 and 53 in this function are because IEEE 754 double
13521 // precision has 52 mantissa bits.
13522 //
13523 // Let f be the floating point number represented by exp2 and mantissa (and
13524 // also the number in h): the number (mantissa * (2 ** (exp2 - 52))).
13525 //
13526 // If f is zero or a small integer, we can return early.
13527 if ((mantissa == 0) ||
13528 ((exp2 < 53) && (h->decimal_point >= ((int32_t)(h->num_digits))))) {
13529 return;
13530 }
13531
13532 // The smallest normal f has an exp2 of -1022 and a mantissa of (1 << 52).
13533 // Subnormal numbers have the same exp2 but a smaller mantissa.
13534 static const int32_t min_incl_normal_exp2 = -1022;
13535 static const uint64_t min_incl_normal_mantissa = 0x0010000000000000ul;
13536
13537 // Compute lower and upper bounds such that any number between them (possibly
13538 // inclusive) will round to f. First, the lower bound. Our number f is:
13539 // ((mantissa + 0) * (2 ** ( exp2 - 52)))
13540 //
13541 // The next lowest floating point number is:
13542 // ((mantissa - 1) * (2 ** ( exp2 - 52)))
13543 // unless (mantissa - 1) drops the (1 << 52) bit and exp2 is not the
13544 // min_incl_normal_exp2. Either way, call it:
13545 // ((l_mantissa) * (2 ** (l_exp2 - 52)))
13546 //
13547 // The lower bound is halfway between them (noting that 52 became 53):
13548 // (((2 * l_mantissa) + 1) * (2 ** (l_exp2 - 53)))
13549 int32_t l_exp2 = exp2;
13550 uint64_t l_mantissa = mantissa - 1;
13551 if ((exp2 > min_incl_normal_exp2) && (mantissa <= min_incl_normal_mantissa)) {
13552 l_exp2 = exp2 - 1;
13553 l_mantissa = (2 * mantissa) - 1;
13554 }
13555 wuffs_base__private_implementation__high_prec_dec lower;
13556 wuffs_base__private_implementation__high_prec_dec__assign(
13557 &lower, (2 * l_mantissa) + 1, false);
13558 wuffs_base__private_implementation__high_prec_dec__lshift(&lower,
13559 l_exp2 - 53);
13560
13561 // Next, the upper bound. Our number f is:
13562 // ((mantissa + 0) * (2 ** (exp2 - 52)))
13563 //
13564 // The next highest floating point number is:
13565 // ((mantissa + 1) * (2 ** (exp2 - 52)))
13566 //
13567 // The upper bound is halfway between them (noting that 52 became 53):
13568 // (((2 * mantissa) + 1) * (2 ** (exp2 - 53)))
13569 wuffs_base__private_implementation__high_prec_dec upper;
13570 wuffs_base__private_implementation__high_prec_dec__assign(
13571 &upper, (2 * mantissa) + 1, false);
13572 wuffs_base__private_implementation__high_prec_dec__lshift(&upper, exp2 - 53);
13573
13574 // The lower and upper bounds are possible outputs only if the original
13575 // mantissa is even, so that IEEE round-to-even would round to the original
13576 // mantissa and not its neighbors.
13577 bool inclusive = (mantissa & 1) == 0;
13578
13579 // As we walk the digits, we want to know whether rounding up would fall
13580 // within the upper bound. This is tracked by upper_delta:
13581 // - When -1, the digits of h and upper are the same so far.
13582 // - When +0, we saw a difference of 1 between h and upper on a previous
13583 // digit and subsequently only 9s for h and 0s for upper. Thus, rounding
13584 // up may fall outside of the bound if !inclusive.
13585 // - When +1, the difference is greater than 1 and we know that rounding up
13586 // falls within the bound.
13587 //
13588 // This is a state machine with three states. The numerical value for each
13589 // state (-1, +0 or +1) isn't important, other than their order.
13590 int upper_delta = -1;
13591
13592 // We can now figure out the shortest number of digits required. Walk the
13593 // digits until h has distinguished itself from lower or upper.
13594 //
13595 // The zi and zd variables are indexes and digits, for z in l (lower), h (the
13596 // number) and u (upper).
13597 //
13598 // The lower, h and upper numbers may have their decimal points at different
13599 // places. In this case, upper is the longest, so we iterate ui starting from
13600 // 0 and iterate li and hi starting from either 0 or -1.
13601 int32_t ui = 0;
13602 for (;; ui++) {
13603 // Calculate hd, the middle number's digit.
13604 int32_t hi = ui - upper.decimal_point + h->decimal_point;
13605 if (hi >= ((int32_t)(h->num_digits))) {
13606 break;
13607 }
13608 uint8_t hd = (((uint32_t)hi) < h->num_digits) ? h->digits[hi] : 0;
13609
13610 // Calculate ld, the lower bound's digit.
13611 int32_t li = ui - upper.decimal_point + lower.decimal_point;
13612 uint8_t ld = (((uint32_t)li) < lower.num_digits) ? lower.digits[li] : 0;
13613
13614 // We can round down (truncate) if lower has a different digit than h or if
13615 // lower is inclusive and is exactly the result of rounding down (i.e. we
13616 // have reached the final digit of lower).
13617 bool can_round_down =
13618 (ld != hd) || //
13619 (inclusive && ((li + 1) == ((int32_t)(lower.num_digits))));
13620
13621 // Calculate ud, the upper bound's digit, and update upper_delta.
13622 uint8_t ud = (((uint32_t)ui) < upper.num_digits) ? upper.digits[ui] : 0;
13623 if (upper_delta < 0) {
13624 if ((hd + 1) < ud) {
13625 // For example:
13626 // h = 12345???
13627 // upper = 12347???
13628 upper_delta = +1;
13629 } else if (hd != ud) {
13630 // For example:
13631 // h = 12345???
13632 // upper = 12346???
13633 upper_delta = +0;
13634 }
13635 } else if (upper_delta == 0) {
13636 if ((hd != 9) || (ud != 0)) {
13637 // For example:
13638 // h = 1234598?
13639 // upper = 1234600?
13640 upper_delta = +1;
13641 }
13642 }
13643
13644 // We can round up if upper has a different digit than h and either upper
13645 // is inclusive or upper is bigger than the result of rounding up.
13646 bool can_round_up =
13647 (upper_delta > 0) || //
13648 ((upper_delta == 0) && //
13649 (inclusive || ((ui + 1) < ((int32_t)(upper.num_digits)))));
13650
13651 // If we can round either way, round to nearest. If we can round only one
13652 // way, do it. If we can't round, continue the loop.
13653 if (can_round_down) {
13654 if (can_round_up) {
13655 wuffs_base__private_implementation__high_prec_dec__round_nearest(
13656 h, hi + 1);
13657 return;
13658 } else {
13659 wuffs_base__private_implementation__high_prec_dec__round_down(h,
13660 hi + 1);
13661 return;
13662 }
13663 } else {
13664 if (can_round_up) {
13665 wuffs_base__private_implementation__high_prec_dec__round_up(h, hi + 1);
13666 return;
13667 }
13668 }
13669 }
13670}
13671
13672// --------
13673
13674// wuffs_base__private_implementation__parse_number_f64_eisel_lemire produces
13675// the IEEE 754 double-precision value for an exact mantissa and base-10
13676// exponent. For example:
13677// - when parsing "12345.678e+02", man is 12345678 and exp10 is -1.
13678// - when parsing "-12", man is 12 and exp10 is 0. Processing the leading
13679// minus sign is the responsibility of the caller, not this function.
13680//
13681// On success, it returns a non-negative int64_t such that the low 63 bits hold
13682// the 11-bit exponent and 52-bit mantissa.
13683//
13684// On failure, it returns a negative value.
13685//
13686// The algorithm is based on an original idea by Michael Eisel that was refined
13687// by Daniel Lemire. See
13688// https://lemire.me/blog/2020/03/10/fast-float-parsing-in-practice/
13689// and
13690// https://nigeltao.github.io/blog/2020/eisel-lemire.html
13691//
13692// Preconditions:
13693// - man is non-zero.
13694// - exp10 is in the range [-307 ..= 288], the same range of the
13695// wuffs_base__private_implementation__powers_of_10 array.
13696//
13697// The exp10 range (and the fact that man is in the range [1 ..= UINT64_MAX],
13698// approximately [1 ..= 1.85e+19]) means that (man * (10 ** exp10)) is in the
13699// range [1e-307 ..= 1.85e+307]. This is entirely within the range of normal
13700// (neither subnormal nor non-finite) f64 values: DBL_MIN and DBL_MAX are
13701// approximately 2.23e–308 and 1.80e+308.
13702static int64_t //
13703wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
13704 uint64_t man,
13705 int32_t exp10) {
13706 // Look up the (possibly truncated) base-2 representation of (10 ** exp10).
13707 // The look-up table was constructed so that it is already normalized: the
13708 // table entry's mantissa's MSB (most significant bit) is on.
13709 const uint64_t* po10 =
13710 &wuffs_base__private_implementation__powers_of_10[exp10 + 307][0];
13711
13712 // Normalize the man argument. The (man != 0) precondition means that a
13713 // non-zero bit exists.
13714 uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);
13715 man <<= clz;
13716
13717 // Calculate the return value's base-2 exponent. We might tweak it by ±1
13718 // later, but its initial value comes from a linear scaling of exp10,
13719 // converting from power-of-10 to power-of-2, and adjusting by clz.
13720 //
13721 // The magic constants are:
13722 // - 1087 = 1023 + 64. The 1023 is the f64 exponent bias. The 64 is because
13723 // the look-up table uses 64-bit mantissas.
13724 // - 217706 is such that the ratio 217706 / 65536 ≈ 3.321930 is close enough
13725 // (over the practical range of exp10) to log(10) / log(2) ≈ 3.321928.
13726 // - 65536 = 1<<16 is arbitrary but a power of 2, so division is a shift.
13727 //
13728 // Equality of the linearly-scaled value and the actual power-of-2, over the
13729 // range of exp10 arguments that this function accepts, is confirmed by
13730 // script/print-mpb-powers-of-10.go
13731 uint64_t ret_exp2 =
13732 ((uint64_t)(((217706 * exp10) >> 16) + 1087)) - ((uint64_t)clz);
13733
13734 // Multiply the two mantissas. Normalization means that both mantissas are at
13735 // least (1<<63), so the 128-bit product must be at least (1<<126). The high
13736 // 64 bits of the product, x_hi, must therefore be at least (1<<62).
13737 //
13738 // As a consequence, x_hi has either 0 or 1 leading zeroes. Shifting x_hi
13739 // right by either 9 or 10 bits (depending on x_hi's MSB) will therefore
13740 // leave the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on.
13741 wuffs_base__multiply_u64__output x = wuffs_base__multiply_u64(man, po10[1]);
13742 uint64_t x_hi = x.hi;
13743 uint64_t x_lo = x.lo;
13744
13745 // Before we shift right by at least 9 bits, recall that the look-up table
13746 // entry was possibly truncated. We have so far only calculated a lower bound
13747 // for the product (man * e), where e is (10 ** exp10). The upper bound would
13748 // add a further (man * 1) to the 128-bit product, which overflows the lower
13749 // 64-bit limb if ((x_lo + man) < man).
13750 //
13751 // If overflow occurs, that adds 1 to x_hi. Since we're about to shift right
13752 // by at least 9 bits, that carried 1 can be ignored unless the higher 64-bit
13753 // limb's low 9 bits are all on.
13754 //
13755 // For example, parsing "9999999999999999999" will take the if-true branch
13756 // here, since:
13757 // - x_hi = 0x4563918244F3FFFF
13758 // - x_lo = 0x8000000000000000
13759 // - man = 0x8AC7230489E7FFFF
13760 if (((x_hi & 0x1FF) == 0x1FF) && ((x_lo + man) < man)) {
13761 // Refine our calculation of (man * e). Before, our approximation of e used
13762 // a "low resolution" 64-bit mantissa. Now use a "high resolution" 128-bit
13763 // mantissa. We've already calculated x = (man * bits_0_to_63_incl_of_e).
13764 // Now calculate y = (man * bits_64_to_127_incl_of_e).
13765 wuffs_base__multiply_u64__output y = wuffs_base__multiply_u64(man, po10[0]);
13766 uint64_t y_hi = y.hi;
13767 uint64_t y_lo = y.lo;
13768
13769 // Merge the 128-bit x and 128-bit y, which overlap by 64 bits, to
13770 // calculate the 192-bit product of the 64-bit man by the 128-bit e.
13771 // As we exit this if-block, we only care about the high 128 bits
13772 // (merged_hi and merged_lo) of that 192-bit product.
13773 //
13774 // For example, parsing "1.234e-45" will take the if-true branch here,
13775 // since:
13776 // - x_hi = 0x70B7E3696DB29FFF
13777 // - x_lo = 0xE040000000000000
13778 // - y_hi = 0x33718BBEAB0E0D7A
13779 // - y_lo = 0xA880000000000000
13780 uint64_t merged_hi = x_hi;
13781 uint64_t merged_lo = x_lo + y_hi;
13782 if (merged_lo < x_lo) {
13783 merged_hi++; // Carry the overflow bit.
13784 }
13785
13786 // The "high resolution" approximation of e is still a lower bound. Once
13787 // again, see if the upper bound is large enough to produce a different
13788 // result. This time, if it does, give up instead of reaching for an even
13789 // more precise approximation to e.
13790 //
13791 // This three-part check is similar to the two-part check that guarded the
13792 // if block that we're now in, but it has an extra term for the middle 64
13793 // bits (checking that adding 1 to merged_lo would overflow).
13794 //
13795 // For example, parsing "5.9604644775390625e-8" will take the if-true
13796 // branch here, since:
13797 // - merged_hi = 0x7FFFFFFFFFFFFFFF
13798 // - merged_lo = 0xFFFFFFFFFFFFFFFF
13799 // - y_lo = 0x4DB3FFC120988200
13800 // - man = 0xD3C21BCECCEDA100
13801 if (((merged_hi & 0x1FF) == 0x1FF) && ((merged_lo + 1) == 0) &&
13802 (y_lo + man < man)) {
13803 return -1;
13804 }
13805
13806 // Replace the 128-bit x with merged.
13807 x_hi = merged_hi;
13808 x_lo = merged_lo;
13809 }
13810
13811 // As mentioned above, shifting x_hi right by either 9 or 10 bits will leave
13812 // the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on. If the
13813 // MSB (before shifting) was on, adjust ret_exp2 for the larger shift.
13814 //
13815 // Having bit 53 on (and higher bits off) means that ret_mantissa is a 54-bit
13816 // number.
13817 uint64_t msb = x_hi >> 63;
13818 uint64_t ret_mantissa = x_hi >> (msb + 9);
13819 ret_exp2 -= 1 ^ msb;
13820
13821 // IEEE 754 rounds to-nearest with ties rounded to-even. Rounding to-even can
13822 // be tricky. If we're half-way between two exactly representable numbers
13823 // (x's low 73 bits are zero and the next 2 bits that matter are "01"), give
13824 // up instead of trying to pick the winner.
13825 //
13826 // Technically, we could tighten the condition by changing "73" to "73 or 74,
13827 // depending on msb", but a flat "73" is simpler.
13828 //
13829 // For example, parsing "1e+23" will take the if-true branch here, since:
13830 // - x_hi = 0x54B40B1F852BDA00
13831 // - ret_mantissa = 0x002A5A058FC295ED
13832 if ((x_lo == 0) && ((x_hi & 0x1FF) == 0) && ((ret_mantissa & 3) == 1)) {
13833 return -1;
13834 }
13835
13836 // If we're not halfway then it's rounding to-nearest. Starting with a 54-bit
13837 // number, carry the lowest bit (bit 0) up if it's on. Regardless of whether
13838 // it was on or off, shifting right by one then produces a 53-bit number. If
13839 // carrying up overflowed, shift again.
13840 ret_mantissa += ret_mantissa & 1;
13841 ret_mantissa >>= 1;
13842 // This if block is equivalent to (but benchmarks slightly faster than) the
13843 // following branchless form:
13844 // uint64_t overflow_adjustment = ret_mantissa >> 53;
13845 // ret_mantissa >>= overflow_adjustment;
13846 // ret_exp2 += overflow_adjustment;
13847 //
13848 // For example, parsing "7.2057594037927933e+16" will take the if-true
13849 // branch here, since:
13850 // - x_hi = 0x7FFFFFFFFFFFFE80
13851 // - ret_mantissa = 0x0020000000000000
13852 if ((ret_mantissa >> 53) > 0) {
13853 ret_mantissa >>= 1;
13854 ret_exp2++;
13855 }
13856
13857 // Starting with a 53-bit number, IEEE 754 double-precision normal numbers
13858 // have an implicit mantissa bit. Mask that away and keep the low 52 bits.
13859 ret_mantissa &= 0x000FFFFFFFFFFFFF;
13860
13861 // Pack the bits and return.
13862 return ((int64_t)(ret_mantissa | (ret_exp2 << 52)));
13863}
13864
13865// --------
13866
13867static wuffs_base__result_f64 //
13868wuffs_base__private_implementation__parse_number_f64_special(
13869 wuffs_base__slice_u8 s,
13870 uint32_t options) {
13871 do {
13872 if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) {
13873 goto fail;
13874 }
13875
13876 uint8_t* p = s.ptr;
13877 uint8_t* q = s.ptr + s.len;
13878
13879 for (; (p < q) && (*p == '_'); p++) {
13880 }
13881 if (p >= q) {
13882 goto fail;
13883 }
13884
13885 // Parse sign.
13886 bool negative = false;
13887 do {
13888 if (*p == '+') {
13889 p++;
13890 } else if (*p == '-') {
13891 negative = true;
13892 p++;
13893 } else {
13894 break;
13895 }
13896 for (; (p < q) && (*p == '_'); p++) {
13897 }
13898 } while (0);
13899 if (p >= q) {
13900 goto fail;
13901 }
13902
13903 bool nan = false;
13904 switch (p[0]) {
13905 case 'I':
13906 case 'i':
13907 if (((q - p) < 3) || //
13908 ((p[1] != 'N') && (p[1] != 'n')) || //
13909 ((p[2] != 'F') && (p[2] != 'f'))) {
13910 goto fail;
13911 }
13912 p += 3;
13913
13914 if ((p >= q) || (*p == '_')) {
13915 break;
13916 } else if (((q - p) < 5) || //
13917 ((p[0] != 'I') && (p[0] != 'i')) || //
13918 ((p[1] != 'N') && (p[1] != 'n')) || //
13919 ((p[2] != 'I') && (p[2] != 'i')) || //
13920 ((p[3] != 'T') && (p[3] != 't')) || //
13921 ((p[4] != 'Y') && (p[4] != 'y'))) {
13922 goto fail;
13923 }
13924 p += 5;
13925
13926 if ((p >= q) || (*p == '_')) {
13927 break;
13928 }
13929 goto fail;
13930
13931 case 'N':
13932 case 'n':
13933 if (((q - p) < 3) || //
13934 ((p[1] != 'A') && (p[1] != 'a')) || //
13935 ((p[2] != 'N') && (p[2] != 'n'))) {
13936 goto fail;
13937 }
13938 p += 3;
13939
13940 if ((p >= q) || (*p == '_')) {
13941 nan = true;
13942 break;
13943 }
13944 goto fail;
13945
13946 default:
13947 goto fail;
13948 }
13949
13950 // Finish.
13951 for (; (p < q) && (*p == '_'); p++) {
13952 }
13953 if (p != q) {
13954 goto fail;
13955 }
13956 wuffs_base__result_f64 ret;
13957 ret.status.repr = NULL;
13958 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
13959 (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) |
13960 (negative ? 0x8000000000000000 : 0));
13961 return ret;
13962 } while (0);
13963
13964fail:
13965 do {
13966 wuffs_base__result_f64 ret;
13967 ret.status.repr = wuffs_base__error__bad_argument;
13968 ret.value = 0;
13969 return ret;
13970 } while (0);
13971}
13972
13973WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
13974wuffs_base__private_implementation__high_prec_dec__to_f64(
13975 wuffs_base__private_implementation__high_prec_dec* h,
13976 uint32_t options) {
13977 do {
13978 // powers converts decimal powers of 10 to binary powers of 2. For example,
13979 // (10000 >> 13) is 1. It stops before the elements exceed 60, also known
13980 // as WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL.
13981 static const uint32_t num_powers = 19;
13982 static const uint8_t powers[19] = {
13983 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, //
13984 33, 36, 39, 43, 46, 49, 53, 56, 59, //
13985 };
13986
13987 // Handle zero and obvious extremes. The largest and smallest positive
13988 // finite f64 values are approximately 1.8e+308 and 4.9e-324.
13989 if ((h->num_digits == 0) || (h->decimal_point < -326)) {
13990 goto zero;
13991 } else if (h->decimal_point > 310) {
13992 goto infinity;
13993 }
13994
13995 // Try the fast Eisel-Lemire algorithm again. Calculating the (man, exp10)
13996 // pair from the high_prec_dec h is more correct but slower than the
13997 // approach taken in wuffs_base__parse_number_f64. The latter is optimized
13998 // for the common cases (e.g. assuming no underscores or a leading '+'
13999 // sign) rather than the full set of cases allowed by the Wuffs API.
14000 if (h->num_digits <= 19) {
14001 uint64_t man = 0;
14002 uint32_t i;
14003 for (i = 0; i < h->num_digits; i++) {
14004 man = (10 * man) + h->digits[i];
14005 }
14006 int32_t exp10 = h->decimal_point - ((int32_t)(h->num_digits));
14007 if ((man != 0) && (-307 <= exp10) && (exp10 <= 288)) {
14008 int64_t r =
14009 wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
14010 man, exp10);
14011 if (r >= 0) {
14012 wuffs_base__result_f64 ret;
14013 ret.status.repr = NULL;
14014 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
14015 ((uint64_t)r) | (((uint64_t)(h->negative)) << 63));
14016 return ret;
14017 }
14018 }
14019 }
14020
14021 // When Eisel-Lemire fails, fall back to Simple Decimal Conversion. See
14022 // https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html
14023 //
14024 // Scale by powers of 2 until we're in the range [½ .. 1], which gives us
14025 // our exponent (in base-2). First we shift right, possibly a little too
14026 // far, ending with a value certainly below 1 and possibly below ½...
14027 const int32_t f64_bias = -1023;
14028 int32_t exp2 = 0;
14029 while (h->decimal_point > 0) {
14030 uint32_t n = (uint32_t)(+h->decimal_point);
14031 uint32_t shift =
14032 (n < num_powers)
14033 ? powers[n]
14034 : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
14035
14036 wuffs_base__private_implementation__high_prec_dec__small_rshift(h, shift);
14037 if (h->decimal_point <
14038 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
14039 goto zero;
14040 }
14041 exp2 += (int32_t)shift;
14042 }
14043 // ...then we shift left, putting us in [½ .. 1].
14044 while (h->decimal_point <= 0) {
14045 uint32_t shift;
14046 if (h->decimal_point == 0) {
14047 if (h->digits[0] >= 5) {
14048 break;
14049 }
14050 shift = (h->digits[0] < 2) ? 2 : 1;
14051 } else {
14052 uint32_t n = (uint32_t)(-h->decimal_point);
14053 shift = (n < num_powers)
14054 ? powers[n]
14055 : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
14056 }
14057
14058 wuffs_base__private_implementation__high_prec_dec__small_lshift(h, shift);
14059 if (h->decimal_point >
14060 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
14061 goto infinity;
14062 }
14063 exp2 -= (int32_t)shift;
14064 }
14065
14066 // We're in the range [½ .. 1] but f64 uses [1 .. 2].
14067 exp2--;
14068
14069 // The minimum normal exponent is (f64_bias + 1).
14070 while ((f64_bias + 1) > exp2) {
14071 uint32_t n = (uint32_t)((f64_bias + 1) - exp2);
14072 if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
14073 n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
14074 }
14075 wuffs_base__private_implementation__high_prec_dec__small_rshift(h, n);
14076 exp2 += (int32_t)n;
14077 }
14078
14079 // Check for overflow.
14080 if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1.
14081 goto infinity;
14082 }
14083
14084 // Extract 53 bits for the mantissa (in base-2).
14085 wuffs_base__private_implementation__high_prec_dec__small_lshift(h, 53);
14086 uint64_t man2 =
14087 wuffs_base__private_implementation__high_prec_dec__rounded_integer(h);
14088
14089 // Rounding might have added one bit. If so, shift and re-check overflow.
14090 if ((man2 >> 53) != 0) {
14091 man2 >>= 1;
14092 exp2++;
14093 if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1.
14094 goto infinity;
14095 }
14096 }
14097
14098 // Handle subnormal numbers.
14099 if ((man2 >> 52) == 0) {
14100 exp2 = f64_bias;
14101 }
14102
14103 // Pack the bits and return.
14104 uint64_t exp2_bits =
14105 (uint64_t)((exp2 - f64_bias) & 0x07FF); // (1 << 11) - 1.
14106 uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) | // (1 << 52) - 1.
14107 (exp2_bits << 52) | //
14108 (h->negative ? 0x8000000000000000 : 0); // (1 << 63).
14109
14110 wuffs_base__result_f64 ret;
14111 ret.status.repr = NULL;
14112 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
14113 return ret;
14114 } while (0);
14115
14116zero:
14117 do {
14118 uint64_t bits = h->negative ? 0x8000000000000000 : 0;
14119
14120 wuffs_base__result_f64 ret;
14121 ret.status.repr = NULL;
14122 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
14123 return ret;
14124 } while (0);
14125
14126infinity:
14127 do {
14128 if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) {
14129 wuffs_base__result_f64 ret;
14130 ret.status.repr = wuffs_base__error__bad_argument;
14131 ret.value = 0;
14132 return ret;
14133 }
14134
14135 uint64_t bits = h->negative ? 0xFFF0000000000000 : 0x7FF0000000000000;
14136
14137 wuffs_base__result_f64 ret;
14138 ret.status.repr = NULL;
14139 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
14140 return ret;
14141 } while (0);
14142}
14143
14144static inline bool //
14145wuffs_base__private_implementation__is_decimal_digit(uint8_t c) {
14146 return ('0' <= c) && (c <= '9');
14147}
14148
14149WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
14150wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options) {
14151 // In practice, almost all "dd.ddddE±xxx" numbers can be represented
14152 // losslessly by a uint64_t mantissa "dddddd" and an int32_t base-10
14153 // exponent, adjusting "xxx" for the position (if present) of the decimal
14154 // separator '.' or ','.
14155 //
14156 // This (u64 man, i32 exp10) data structure is superficially similar to the
14157 // "Do It Yourself Floating Point" type from Loitsch (†), but the exponent
14158 // here is base-10, not base-2.
14159 //
14160 // If s's number fits in a (man, exp10), parse that pair with the
14161 // Eisel-Lemire algorithm. If not, or if Eisel-Lemire fails, parsing s with
14162 // the fallback algorithm is slower but comprehensive.
14163 //
14164 // † "Printing Floating-Point Numbers Quickly and Accurately with Integers"
14165 // (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf).
14166 // Florian Loitsch is also the primary contributor to
14167 // https://github.com/google/double-conversion
14168 do {
14169 // Calculating that (man, exp10) pair needs to stay within s's bounds.
14170 // Provided that s isn't extremely long, work on a NUL-terminated copy of
14171 // s's contents. The NUL byte isn't a valid part of "±dd.ddddE±xxx".
14172 //
14173 // As the pointer p walks the contents, it's faster to repeatedly check "is
14174 // *p a valid digit" than "is p within bounds and *p a valid digit".
14175 if (s.len >= 256) {
14176 goto fallback;
14177 }
14178 uint8_t z[256];
14179 memcpy(&z[0], s.ptr, s.len);
14180 z[s.len] = 0;
14181 const uint8_t* p = &z[0];
14182
14183 // Look for a leading minus sign. Technically, we could also look for an
14184 // optional plus sign, but the "script/process-json-numbers.c with -p"
14185 // benchmark is noticably slower if we do. It's optional and, in practice,
14186 // usually absent. Let the fallback catch it.
14187 bool negative = (*p == '-');
14188 if (negative) {
14189 p++;
14190 }
14191
14192 // After walking "dd.dddd", comparing p later with p now will produce the
14193 // number of "d"s and "."s.
14194 const uint8_t* const start_of_digits_ptr = p;
14195
14196 // Walk the "d"s before a '.', 'E', NUL byte, etc. If it starts with '0',
14197 // it must be a single '0'. If it starts with a non-zero decimal digit, it
14198 // can be a sequence of decimal digits.
14199 //
14200 // Update the man variable during the walk. It's OK if man overflows now.
14201 // We'll detect that later.
14202 uint64_t man;
14203 if (*p == '0') {
14204 man = 0;
14205 p++;
14206 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
14207 goto fallback;
14208 }
14209 } else if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
14210 man = ((uint8_t)(*p - '0'));
14211 p++;
14212 for (; wuffs_base__private_implementation__is_decimal_digit(*p); p++) {
14213 man = (10 * man) + ((uint8_t)(*p - '0'));
14214 }
14215 } else {
14216 goto fallback;
14217 }
14218
14219 // Walk the "d"s after the optional decimal separator ('.' or ','),
14220 // updating the man and exp10 variables.
14221 int32_t exp10 = 0;
14222 if (*p ==
14223 ((options & WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
14224 ? ','
14225 : '.')) {
14226 p++;
14227 const uint8_t* first_after_separator_ptr = p;
14228 if (!wuffs_base__private_implementation__is_decimal_digit(*p)) {
14229 goto fallback;
14230 }
14231 man = (10 * man) + ((uint8_t)(*p - '0'));
14232 p++;
14233 for (; wuffs_base__private_implementation__is_decimal_digit(*p); p++) {
14234 man = (10 * man) + ((uint8_t)(*p - '0'));
14235 }
14236 exp10 = ((int32_t)(first_after_separator_ptr - p));
14237 }
14238
14239 // Count the number of digits:
14240 // - for an input of "314159", digit_count is 6.
14241 // - for an input of "3.14159", digit_count is 7.
14242 //
14243 // This is off-by-one if there is a decimal separator. That's OK for now.
14244 // We'll correct for that later. The "script/process-json-numbers.c with
14245 // -p" benchmark is noticably slower if we try to correct for that now.
14246 uint32_t digit_count = (uint32_t)(p - start_of_digits_ptr);
14247
14248 // Update exp10 for the optional exponent, starting with 'E' or 'e'.
14249 if ((*p | 0x20) == 'e') {
14250 p++;
14251 int32_t exp_sign = +1;
14252 if (*p == '-') {
14253 p++;
14254 exp_sign = -1;
14255 } else if (*p == '+') {
14256 p++;
14257 }
14258 if (!wuffs_base__private_implementation__is_decimal_digit(*p)) {
14259 goto fallback;
14260 }
14261 int32_t exp_num = ((uint8_t)(*p - '0'));
14262 p++;
14263 // The rest of the exp_num walking has a peculiar control flow but, once
14264 // again, the "script/process-json-numbers.c with -p" benchmark is
14265 // sensitive to alternative formulations.
14266 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
14267 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
14268 p++;
14269 }
14270 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
14271 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
14272 p++;
14273 }
14274 while (wuffs_base__private_implementation__is_decimal_digit(*p)) {
14275 if (exp_num > 0x1000000) {
14276 goto fallback;
14277 }
14278 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
14279 p++;
14280 }
14281 exp10 += exp_sign * exp_num;
14282 }
14283
14284 // The Wuffs API is that the original slice has no trailing data. It also
14285 // allows underscores, which we don't catch here but the fallback should.
14286 if (p != &z[s.len]) {
14287 goto fallback;
14288 }
14289
14290 // Check that the uint64_t typed man variable has not overflowed, based on
14291 // digit_count.
14292 //
14293 // For reference:
14294 // - (1 << 63) is 9223372036854775808, which has 19 decimal digits.
14295 // - (1 << 64) is 18446744073709551616, which has 20 decimal digits.
14296 // - 19 nines, 9999999999999999999, is 0x8AC7230489E7FFFF, which has 64
14297 // bits and 16 hexadecimal digits.
14298 // - 20 nines, 99999999999999999999, is 0x56BC75E2D630FFFFF, which has 67
14299 // bits and 17 hexadecimal digits.
14300 if (digit_count > 19) {
14301 // Even if we have more than 19 pseudo-digits, it's not yet definitely an
14302 // overflow. Recall that digit_count might be off-by-one (too large) if
14303 // there's a decimal separator. It will also over-report the number of
14304 // meaningful digits if the input looks something like "0.000dddExxx".
14305 //
14306 // We adjust by the number of leading '0's and '.'s and re-compare to 19.
14307 // Once again, technically, we could skip ','s too, but that perturbs the
14308 // "script/process-json-numbers.c with -p" benchmark.
14309 const uint8_t* q = start_of_digits_ptr;
14310 for (; (*q == '0') || (*q == '.'); q++) {
14311 }
14312 digit_count -= (uint32_t)(q - start_of_digits_ptr);
14313 if (digit_count > 19) {
14314 goto fallback;
14315 }
14316 }
14317
14318 // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire
14319 // preconditions include that exp10 is in the range [-307 ..= 288].
14320 if ((exp10 < -307) || (288 < exp10)) {
14321 goto fallback;
14322 }
14323
14324 // If both man and (10 ** exp10) are exactly representable by a double, we
14325 // don't need to run the Eisel-Lemire algorithm.
14326 if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) {
14327 double d = (double)man;
14328 if (exp10 >= 0) {
14329 d *= wuffs_base__private_implementation__f64_powers_of_10[+exp10];
14330 } else {
14331 d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10];
14332 }
14333 wuffs_base__result_f64 ret;
14334 ret.status.repr = NULL;
14335 ret.value = negative ? -d : +d;
14336 return ret;
14337 }
14338
14339 // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire
14340 // preconditions include that man is non-zero. Parsing "0" should be caught
14341 // by the "If both man and (10 ** exp10)" above, but "0e99" might not.
14342 if (man == 0) {
14343 goto fallback;
14344 }
14345
14346 // Our man and exp10 are in range. Run the Eisel-Lemire algorithm.
14347 int64_t r =
14348 wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
14349 man, exp10);
14350 if (r < 0) {
14351 goto fallback;
14352 }
14353 wuffs_base__result_f64 ret;
14354 ret.status.repr = NULL;
14355 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
14356 ((uint64_t)r) | (((uint64_t)negative) << 63));
14357 return ret;
14358 } while (0);
14359
14360fallback:
14361 do {
14362 wuffs_base__private_implementation__high_prec_dec h;
14363 wuffs_base__status status =
14364 wuffs_base__private_implementation__high_prec_dec__parse(&h, s,
14365 options);
14366 if (status.repr) {
14367 return wuffs_base__private_implementation__parse_number_f64_special(
14368 s, options);
14369 }
14370 return wuffs_base__private_implementation__high_prec_dec__to_f64(&h,
14371 options);
14372 } while (0);
14373}
14374
14375// --------
14376
14377static inline size_t //
14378wuffs_base__private_implementation__render_inf(wuffs_base__slice_u8 dst,
14379 bool neg,
14380 uint32_t options) {
14381 if (neg) {
14382 if (dst.len < 4) {
14383 return 0;
14384 }
14385 wuffs_base__poke_u32le__no_bounds_check(dst.ptr, 0x666E492D); // '-Inf'le.
14386 return 4;
14387 }
14388
14389 if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
14390 if (dst.len < 4) {
14391 return 0;
14392 }
14393 wuffs_base__poke_u32le__no_bounds_check(dst.ptr, 0x666E492B); // '+Inf'le.
14394 return 4;
14395 }
14396
14397 if (dst.len < 3) {
14398 return 0;
14399 }
14400 wuffs_base__poke_u24le__no_bounds_check(dst.ptr, 0x666E49); // 'Inf'le.
14401 return 3;
14402}
14403
14404static inline size_t //
14405wuffs_base__private_implementation__render_nan(wuffs_base__slice_u8 dst) {
14406 if (dst.len < 3) {
14407 return 0;
14408 }
14409 wuffs_base__poke_u24le__no_bounds_check(dst.ptr, 0x4E614E); // 'NaN'le.
14410 return 3;
14411}
14412
14413static size_t //
14414wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
14415 wuffs_base__slice_u8 dst,
14416 wuffs_base__private_implementation__high_prec_dec* h,
14417 uint32_t precision,
14418 uint32_t options) {
14419 size_t n = (h->negative ||
14420 (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN))
14421 ? 1
14422 : 0;
14423 if (h->decimal_point <= 0) {
14424 n += 1;
14425 } else {
14426 n += (size_t)(h->decimal_point);
14427 }
14428 if (precision > 0) {
14429 n += precision + 1; // +1 for the '.'.
14430 }
14431
14432 // Don't modify dst if the formatted number won't fit.
14433 if (n > dst.len) {
14434 return 0;
14435 }
14436
14437 // Align-left or align-right.
14438 uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)
14439 ? &dst.ptr[dst.len - n]
14440 : &dst.ptr[0];
14441
14442 // Leading "±".
14443 if (h->negative) {
14444 *ptr++ = '-';
14445 } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
14446 *ptr++ = '+';
14447 }
14448
14449 // Integral digits.
14450 if (h->decimal_point <= 0) {
14451 *ptr++ = '0';
14452 } else {
14453 uint32_t m =
14454 wuffs_base__u32__min(h->num_digits, (uint32_t)(h->decimal_point));
14455 uint32_t i = 0;
14456 for (; i < m; i++) {
14457 *ptr++ = (uint8_t)('0' | h->digits[i]);
14458 }
14459 for (; i < (uint32_t)(h->decimal_point); i++) {
14460 *ptr++ = '0';
14461 }
14462 }
14463
14464 // Separator and then fractional digits.
14465 if (precision > 0) {
14466 *ptr++ =
14467 (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
14468 ? ','
14469 : '.';
14470 uint32_t i = 0;
14471 for (; i < precision; i++) {
14472 uint32_t j = ((uint32_t)(h->decimal_point)) + i;
14473 *ptr++ = (uint8_t)('0' | ((j < h->num_digits) ? h->digits[j] : 0));
14474 }
14475 }
14476
14477 return n;
14478}
14479
14480static size_t //
14481wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
14482 wuffs_base__slice_u8 dst,
14483 wuffs_base__private_implementation__high_prec_dec* h,
14484 uint32_t precision,
14485 uint32_t options) {
14486 int32_t exp = 0;
14487 if (h->num_digits > 0) {
14488 exp = h->decimal_point - 1;
14489 }
14490 bool negative_exp = exp < 0;
14491 if (negative_exp) {
14492 exp = -exp;
14493 }
14494
14495 size_t n = (h->negative ||
14496 (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN))
14497 ? 4
14498 : 3; // Mininum 3 bytes: first digit and then "e±".
14499 if (precision > 0) {
14500 n += precision + 1; // +1 for the '.'.
14501 }
14502 n += (exp < 100) ? 2 : 3;
14503
14504 // Don't modify dst if the formatted number won't fit.
14505 if (n > dst.len) {
14506 return 0;
14507 }
14508
14509 // Align-left or align-right.
14510 uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)
14511 ? &dst.ptr[dst.len - n]
14512 : &dst.ptr[0];
14513
14514 // Leading "±".
14515 if (h->negative) {
14516 *ptr++ = '-';
14517 } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
14518 *ptr++ = '+';
14519 }
14520
14521 // Integral digit.
14522 if (h->num_digits > 0) {
14523 *ptr++ = (uint8_t)('0' | h->digits[0]);
14524 } else {
14525 *ptr++ = '0';
14526 }
14527
14528 // Separator and then fractional digits.
14529 if (precision > 0) {
14530 *ptr++ =
14531 (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
14532 ? ','
14533 : '.';
14534 uint32_t i = 1;
14535 uint32_t j = wuffs_base__u32__min(h->num_digits, precision + 1);
14536 for (; i < j; i++) {
14537 *ptr++ = (uint8_t)('0' | h->digits[i]);
14538 }
14539 for (; i <= precision; i++) {
14540 *ptr++ = '0';
14541 }
14542 }
14543
14544 // Exponent: "e±" and then 2 or 3 digits.
14545 *ptr++ = 'e';
14546 *ptr++ = negative_exp ? '-' : '+';
14547 if (exp < 10) {
14548 *ptr++ = '0';
14549 *ptr++ = (uint8_t)('0' | exp);
14550 } else if (exp < 100) {
14551 *ptr++ = (uint8_t)('0' | (exp / 10));
14552 *ptr++ = (uint8_t)('0' | (exp % 10));
14553 } else {
14554 int32_t e = exp / 100;
14555 exp -= e * 100;
14556 *ptr++ = (uint8_t)('0' | e);
14557 *ptr++ = (uint8_t)('0' | (exp / 10));
14558 *ptr++ = (uint8_t)('0' | (exp % 10));
14559 }
14560
14561 return n;
14562}
14563
14564WUFFS_BASE__MAYBE_STATIC size_t //
14565wuffs_base__render_number_f64(wuffs_base__slice_u8 dst,
14566 double x,
14567 uint32_t precision,
14568 uint32_t options) {
14569 // Decompose x (64 bits) into negativity (1 bit), base-2 exponent (11 bits
14570 // with a -1023 bias) and mantissa (52 bits).
14571 uint64_t bits = wuffs_base__ieee_754_bit_representation__from_f64_to_u64(x);
14572 bool neg = (bits >> 63) != 0;
14573 int32_t exp2 = ((int32_t)(bits >> 52)) & 0x7FF;
14574 uint64_t man = bits & 0x000FFFFFFFFFFFFFul;
14575
14576 // Apply the exponent bias and set the implicit top bit of the mantissa,
14577 // unless x is subnormal. Also take care of Inf and NaN.
14578 if (exp2 == 0x7FF) {
14579 if (man != 0) {
14580 return wuffs_base__private_implementation__render_nan(dst);
14581 }
14582 return wuffs_base__private_implementation__render_inf(dst, neg, options);
14583 } else if (exp2 == 0) {
14584 exp2 = -1022;
14585 } else {
14586 exp2 -= 1023;
14587 man |= 0x0010000000000000ul;
14588 }
14589
14590 // Ensure that precision isn't too large.
14591 if (precision > 4095) {
14592 precision = 4095;
14593 }
14594
14595 // Convert from the (neg, exp2, man) tuple to an HPD.
14596 wuffs_base__private_implementation__high_prec_dec h;
14597 wuffs_base__private_implementation__high_prec_dec__assign(&h, man, neg);
14598 if (h.num_digits > 0) {
14599 wuffs_base__private_implementation__high_prec_dec__lshift(
14600 &h, exp2 - 52); // 52 mantissa bits.
14601 }
14602
14603 // Handle the "%e" and "%f" formats.
14604 switch (options & (WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT |
14605 WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT)) {
14606 case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT: // The "%"f" format.
14607 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
14608 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
14609 &h, exp2, man);
14610 int32_t p = ((int32_t)(h.num_digits)) - h.decimal_point;
14611 precision = ((uint32_t)(wuffs_base__i32__max(0, p)));
14612 } else {
14613 wuffs_base__private_implementation__high_prec_dec__round_nearest(
14614 &h, ((int32_t)precision) + h.decimal_point);
14615 }
14616 return wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
14617 dst, &h, precision, options);
14618
14619 case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT: // The "%e" format.
14620 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
14621 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
14622 &h, exp2, man);
14623 precision = (h.num_digits > 0) ? (h.num_digits - 1) : 0;
14624 } else {
14625 wuffs_base__private_implementation__high_prec_dec__round_nearest(
14626 &h, ((int32_t)precision) + 1);
14627 }
14628 return wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
14629 dst, &h, precision, options);
14630 }
14631
14632 // We have the "%g" format and so precision means the number of significant
14633 // digits, not the number of digits after the decimal separator. Perform
14634 // rounding and determine whether to use "%e" or "%f".
14635 int32_t e_threshold = 0;
14636 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
14637 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
14638 &h, exp2, man);
14639 precision = h.num_digits;
14640 e_threshold = 6;
14641 } else {
14642 if (precision == 0) {
14643 precision = 1;
14644 }
14645 wuffs_base__private_implementation__high_prec_dec__round_nearest(
14646 &h, ((int32_t)precision));
14647 e_threshold = ((int32_t)precision);
14648 int32_t nd = ((int32_t)(h.num_digits));
14649 if ((e_threshold > nd) && (nd >= h.decimal_point)) {
14650 e_threshold = nd;
14651 }
14652 }
14653
14654 // Use the "%e" format if the exponent is large.
14655 int32_t e = h.decimal_point - 1;
14656 if ((e < -4) || (e_threshold <= e)) {
14657 uint32_t p = wuffs_base__u32__min(precision, h.num_digits);
14658 return wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
14659 dst, &h, (p > 0) ? (p - 1) : 0, options);
14660 }
14661
14662 // Use the "%f" format otherwise.
14663 int32_t p = ((int32_t)precision);
14664 if (p > h.decimal_point) {
14665 p = ((int32_t)(h.num_digits));
14666 }
14667 precision = ((uint32_t)(wuffs_base__i32__max(0, p - h.decimal_point)));
14668 return wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
14669 dst, &h, precision, options);
14670}
14671
14672#endif // !defined(WUFFS_CONFIG__MODULES) ||
14673 // defined(WUFFS_CONFIG__MODULE__BASE) ||
14674 // defined(WUFFS_CONFIG__MODULE__BASE__FLOATCONV)
14675
14676#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
14677 defined(WUFFS_CONFIG__MODULE__BASE__INTCONV)
14678
14679// ---------------- Integer
14680
14681// wuffs_base__parse_number__foo_digits entries are 0x00 for invalid digits,
14682// and (0x80 | v) for valid digits, where v is the 4 bit value.
14683
14684static const uint8_t wuffs_base__parse_number__decimal_digits[256] = {
14685 // 0 1 2 3 4 5 6 7
14686 // 8 9 A B C D E F
14687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07.
14688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F.
14689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17.
14690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F.
14691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27.
14692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F.
14693 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // 0x30 ..= 0x37. '0'-'7'.
14694 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. '8'-'9'.
14695
14696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 ..= 0x47.
14697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F.
14698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57.
14699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F.
14700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 ..= 0x67.
14701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F.
14702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77.
14703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F.
14704
14705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 ..= 0x87.
14706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 ..= 0x8F.
14707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 ..= 0x97.
14708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 ..= 0x9F.
14709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 ..= 0xA7.
14710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 ..= 0xAF.
14711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 ..= 0xB7.
14712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 ..= 0xBF.
14713
14714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 ..= 0xC7.
14715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 ..= 0xCF.
14716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 ..= 0xD7.
14717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 ..= 0xDF.
14718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 ..= 0xE7.
14719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 ..= 0xEF.
14720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 ..= 0xF7.
14721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF8 ..= 0xFF.
14722 // 0 1 2 3 4 5 6 7
14723 // 8 9 A B C D E F
14724};
14725
14726static const uint8_t wuffs_base__parse_number__hexadecimal_digits[256] = {
14727 // 0 1 2 3 4 5 6 7
14728 // 8 9 A B C D E F
14729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07.
14730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F.
14731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17.
14732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F.
14733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27.
14734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F.
14735 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // 0x30 ..= 0x37. '0'-'7'.
14736 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. '8'-'9'.
14737
14738 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00, // 0x40 ..= 0x47. 'A'-'F'.
14739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F.
14740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57.
14741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F.
14742 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00, // 0x60 ..= 0x67. 'a'-'f'.
14743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F.
14744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77.
14745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F.
14746
14747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 ..= 0x87.
14748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 ..= 0x8F.
14749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 ..= 0x97.
14750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 ..= 0x9F.
14751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 ..= 0xA7.
14752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 ..= 0xAF.
14753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 ..= 0xB7.
14754 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 ..= 0xBF.
14755
14756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 ..= 0xC7.
14757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 ..= 0xCF.
14758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 ..= 0xD7.
14759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 ..= 0xDF.
14760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 ..= 0xE7.
14761 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 ..= 0xEF.
14762 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 ..= 0xF7.
14763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF8 ..= 0xFF.
14764 // 0 1 2 3 4 5 6 7
14765 // 8 9 A B C D E F
14766};
14767
14768static const uint8_t wuffs_base__private_implementation__encode_base16[16] = {
14769 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 0x00 ..= 0x07.
14770 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, // 0x08 ..= 0x0F.
14771};
14772
14773// --------
14774
14775WUFFS_BASE__MAYBE_STATIC wuffs_base__result_i64 //
14776wuffs_base__parse_number_i64(wuffs_base__slice_u8 s, uint32_t options) {
14777 uint8_t* p = s.ptr;
14778 uint8_t* q = s.ptr + s.len;
14779
14780 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
14781 for (; (p < q) && (*p == '_'); p++) {
14782 }
14783 }
14784
14785 bool negative = false;
14786 if (p >= q) {
14787 goto fail_bad_argument;
14788 } else if (*p == '-') {
14789 p++;
14790 negative = true;
14791 } else if (*p == '+') {
14792 p++;
14793 }
14794
14795 do {
14796 wuffs_base__result_u64 r = wuffs_base__parse_number_u64(
14797 wuffs_base__make_slice_u8(p, (size_t)(q - p)), options);
14798 if (r.status.repr != NULL) {
14799 wuffs_base__result_i64 ret;
14800 ret.status.repr = r.status.repr;
14801 ret.value = 0;
14802 return ret;
14803 } else if (negative) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100014804 if (r.value < 0x8000000000000000) {
14805 wuffs_base__result_i64 ret;
14806 ret.status.repr = NULL;
14807 ret.value = -(int64_t)(r.value);
14808 return ret;
14809 } else if (r.value == 0x8000000000000000) {
14810 wuffs_base__result_i64 ret;
14811 ret.status.repr = NULL;
14812 ret.value = INT64_MIN;
14813 return ret;
Nigel Taoe360a532021-04-05 22:47:03 +100014814 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100014815 goto fail_out_of_bounds;
Nigel Taoe360a532021-04-05 22:47:03 +100014816 } else if (r.value > 0x7FFFFFFFFFFFFFFF) {
14817 goto fail_out_of_bounds;
14818 } else {
14819 wuffs_base__result_i64 ret;
14820 ret.status.repr = NULL;
14821 ret.value = +(int64_t)(r.value);
14822 return ret;
14823 }
14824 } while (0);
14825
14826fail_bad_argument:
14827 do {
14828 wuffs_base__result_i64 ret;
14829 ret.status.repr = wuffs_base__error__bad_argument;
14830 ret.value = 0;
14831 return ret;
14832 } while (0);
14833
14834fail_out_of_bounds:
14835 do {
14836 wuffs_base__result_i64 ret;
14837 ret.status.repr = wuffs_base__error__out_of_bounds;
14838 ret.value = 0;
14839 return ret;
14840 } while (0);
14841}
14842
14843WUFFS_BASE__MAYBE_STATIC wuffs_base__result_u64 //
14844wuffs_base__parse_number_u64(wuffs_base__slice_u8 s, uint32_t options) {
14845 uint8_t* p = s.ptr;
14846 uint8_t* q = s.ptr + s.len;
14847
14848 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
14849 for (; (p < q) && (*p == '_'); p++) {
14850 }
14851 }
14852
14853 if (p >= q) {
14854 goto fail_bad_argument;
14855
14856 } else if (*p == '0') {
14857 p++;
14858 if (p >= q) {
14859 goto ok_zero;
14860 }
14861 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
14862 if (*p == '_') {
14863 p++;
14864 for (; p < q; p++) {
14865 if (*p != '_') {
14866 if (options &
14867 WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES) {
14868 goto decimal;
14869 }
14870 goto fail_bad_argument;
14871 }
14872 }
14873 goto ok_zero;
14874 }
14875 }
14876
14877 if ((*p == 'x') || (*p == 'X')) {
14878 p++;
14879 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
14880 for (; (p < q) && (*p == '_'); p++) {
14881 }
14882 }
14883 if (p < q) {
14884 goto hexadecimal;
14885 }
14886
14887 } else if ((*p == 'd') || (*p == 'D')) {
14888 p++;
14889 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
14890 for (; (p < q) && (*p == '_'); p++) {
14891 }
14892 }
14893 if (p < q) {
14894 goto decimal;
14895 }
14896 }
14897
14898 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES) {
14899 goto decimal;
14900 }
14901 goto fail_bad_argument;
14902 }
14903
14904decimal:
14905 do {
14906 uint64_t v = wuffs_base__parse_number__decimal_digits[*p++];
14907 if (v == 0) {
14908 goto fail_bad_argument;
14909 }
14910 v &= 0x0F;
14911
14912 // UINT64_MAX is 18446744073709551615, which is ((10 * max10) + max1).
14913 const uint64_t max10 = 1844674407370955161u;
14914 const uint8_t max1 = 5;
14915
14916 for (; p < q; p++) {
14917 if ((*p == '_') &&
14918 (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
14919 continue;
14920 }
14921 uint8_t digit = wuffs_base__parse_number__decimal_digits[*p];
14922 if (digit == 0) {
14923 goto fail_bad_argument;
14924 }
14925 digit &= 0x0F;
14926 if ((v > max10) || ((v == max10) && (digit > max1))) {
14927 goto fail_out_of_bounds;
14928 }
14929 v = (10 * v) + ((uint64_t)(digit));
14930 }
14931
14932 wuffs_base__result_u64 ret;
14933 ret.status.repr = NULL;
14934 ret.value = v;
14935 return ret;
14936 } while (0);
14937
14938hexadecimal:
14939 do {
14940 uint64_t v = wuffs_base__parse_number__hexadecimal_digits[*p++];
14941 if (v == 0) {
14942 goto fail_bad_argument;
14943 }
14944 v &= 0x0F;
14945
14946 for (; p < q; p++) {
14947 if ((*p == '_') &&
14948 (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
14949 continue;
14950 }
14951 uint8_t digit = wuffs_base__parse_number__hexadecimal_digits[*p];
14952 if (digit == 0) {
14953 goto fail_bad_argument;
14954 }
14955 digit &= 0x0F;
14956 if ((v >> 60) != 0) {
14957 goto fail_out_of_bounds;
14958 }
14959 v = (v << 4) | ((uint64_t)(digit));
14960 }
14961
14962 wuffs_base__result_u64 ret;
14963 ret.status.repr = NULL;
14964 ret.value = v;
14965 return ret;
14966 } while (0);
14967
14968ok_zero:
14969 do {
14970 wuffs_base__result_u64 ret;
14971 ret.status.repr = NULL;
14972 ret.value = 0;
14973 return ret;
14974 } while (0);
14975
14976fail_bad_argument:
14977 do {
14978 wuffs_base__result_u64 ret;
14979 ret.status.repr = wuffs_base__error__bad_argument;
14980 ret.value = 0;
14981 return ret;
14982 } while (0);
14983
14984fail_out_of_bounds:
14985 do {
14986 wuffs_base__result_u64 ret;
14987 ret.status.repr = wuffs_base__error__out_of_bounds;
14988 ret.value = 0;
14989 return ret;
14990 } while (0);
14991}
14992
14993// --------
14994
14995// wuffs_base__render_number__first_hundred contains the decimal encodings of
14996// the first one hundred numbers [0 ..= 99].
14997static const uint8_t wuffs_base__render_number__first_hundred[200] = {
14998 '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', //
14999 '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', //
15000 '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', //
15001 '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', //
15002 '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', //
15003 '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', //
15004 '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', //
15005 '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', //
15006 '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', //
15007 '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', //
15008 '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', //
15009 '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', //
15010 '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', //
15011 '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', //
15012 '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', //
15013 '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', //
15014 '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', //
15015 '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', //
15016 '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', //
15017 '9', '5', '9', '6', '9', '7', '9', '8', '9', '9', //
15018};
15019
15020static size_t //
15021wuffs_base__private_implementation__render_number_u64(wuffs_base__slice_u8 dst,
15022 uint64_t x,
15023 uint32_t options,
15024 bool neg) {
15025 uint8_t buf[WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL];
15026 uint8_t* ptr = &buf[0] + sizeof(buf);
15027
15028 while (x >= 100) {
15029 size_t index = ((size_t)((x % 100) * 2));
15030 x /= 100;
15031 uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0];
15032 uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1];
15033 ptr -= 2;
15034 ptr[0] = s0;
15035 ptr[1] = s1;
15036 }
15037
15038 if (x < 10) {
15039 ptr -= 1;
15040 ptr[0] = (uint8_t)('0' + x);
15041 } else {
15042 size_t index = ((size_t)(x * 2));
15043 uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0];
15044 uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1];
15045 ptr -= 2;
15046 ptr[0] = s0;
15047 ptr[1] = s1;
15048 }
15049
15050 if (neg) {
15051 ptr -= 1;
15052 ptr[0] = '-';
15053 } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
15054 ptr -= 1;
15055 ptr[0] = '+';
15056 }
15057
15058 size_t n = sizeof(buf) - ((size_t)(ptr - &buf[0]));
15059 if (n > dst.len) {
15060 return 0;
15061 }
15062 memcpy(dst.ptr + ((options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)
15063 ? (dst.len - n)
15064 : 0),
15065 ptr, n);
15066 return n;
15067}
15068
15069WUFFS_BASE__MAYBE_STATIC size_t //
15070wuffs_base__render_number_i64(wuffs_base__slice_u8 dst,
15071 int64_t x,
15072 uint32_t options) {
15073 uint64_t u = (uint64_t)x;
15074 bool neg = x < 0;
15075 if (neg) {
15076 u = 1 + ~u;
15077 }
15078 return wuffs_base__private_implementation__render_number_u64(dst, u, options,
15079 neg);
15080}
15081
15082WUFFS_BASE__MAYBE_STATIC size_t //
15083wuffs_base__render_number_u64(wuffs_base__slice_u8 dst,
15084 uint64_t x,
15085 uint32_t options) {
15086 return wuffs_base__private_implementation__render_number_u64(dst, x, options,
15087 false);
15088}
15089
15090// ---------------- Base-16
15091
15092WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15093wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
15094 wuffs_base__slice_u8 src,
15095 bool src_closed,
15096 uint32_t options) {
15097 wuffs_base__transform__output o;
15098 size_t src_len2 = src.len / 2;
15099 size_t len;
15100 if (dst.len < src_len2) {
15101 len = dst.len;
15102 o.status.repr = wuffs_base__suspension__short_write;
15103 } else {
15104 len = src_len2;
15105 if (!src_closed) {
15106 o.status.repr = wuffs_base__suspension__short_read;
15107 } else if (src.len & 1) {
15108 o.status.repr = wuffs_base__error__bad_data;
15109 } else {
15110 o.status.repr = NULL;
15111 }
15112 }
15113
15114 uint8_t* d = dst.ptr;
15115 uint8_t* s = src.ptr;
15116 size_t n = len;
15117
15118 while (n--) {
15119 *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) |
15120 (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F));
15121 d += 1;
15122 s += 2;
15123 }
15124
15125 o.num_dst = len;
15126 o.num_src = len * 2;
15127 return o;
15128}
15129
15130WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15131wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
15132 wuffs_base__slice_u8 src,
15133 bool src_closed,
15134 uint32_t options) {
15135 wuffs_base__transform__output o;
15136 size_t src_len4 = src.len / 4;
15137 size_t len = dst.len < src_len4 ? dst.len : src_len4;
15138 if (dst.len < src_len4) {
15139 len = dst.len;
15140 o.status.repr = wuffs_base__suspension__short_write;
15141 } else {
15142 len = src_len4;
15143 if (!src_closed) {
15144 o.status.repr = wuffs_base__suspension__short_read;
15145 } else if (src.len & 1) {
15146 o.status.repr = wuffs_base__error__bad_data;
15147 } else {
15148 o.status.repr = NULL;
15149 }
15150 }
15151
15152 uint8_t* d = dst.ptr;
15153 uint8_t* s = src.ptr;
15154 size_t n = len;
15155
15156 while (n--) {
15157 *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) |
15158 (wuffs_base__parse_number__hexadecimal_digits[s[3]] & 0x0F));
15159 d += 1;
15160 s += 4;
15161 }
15162
15163 o.num_dst = len;
15164 o.num_src = len * 4;
15165 return o;
15166}
15167
15168WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15169wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
15170 wuffs_base__slice_u8 src,
15171 bool src_closed,
15172 uint32_t options) {
15173 wuffs_base__transform__output o;
15174 size_t dst_len2 = dst.len / 2;
15175 size_t len;
15176 if (dst_len2 < src.len) {
15177 len = dst_len2;
15178 o.status.repr = wuffs_base__suspension__short_write;
15179 } else {
15180 len = src.len;
15181 if (!src_closed) {
15182 o.status.repr = wuffs_base__suspension__short_read;
15183 } else {
15184 o.status.repr = NULL;
15185 }
15186 }
15187
15188 uint8_t* d = dst.ptr;
15189 uint8_t* s = src.ptr;
15190 size_t n = len;
15191
15192 while (n--) {
15193 uint8_t c = *s;
15194 d[0] = wuffs_base__private_implementation__encode_base16[c >> 4];
15195 d[1] = wuffs_base__private_implementation__encode_base16[c & 0x0F];
15196 d += 2;
15197 s += 1;
15198 }
15199
15200 o.num_dst = len * 2;
15201 o.num_src = len;
15202 return o;
15203}
15204
15205WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15206wuffs_base__base_16__encode4(wuffs_base__slice_u8 dst,
15207 wuffs_base__slice_u8 src,
15208 bool src_closed,
15209 uint32_t options) {
15210 wuffs_base__transform__output o;
15211 size_t dst_len4 = dst.len / 4;
15212 size_t len;
15213 if (dst_len4 < src.len) {
15214 len = dst_len4;
15215 o.status.repr = wuffs_base__suspension__short_write;
15216 } else {
15217 len = src.len;
15218 if (!src_closed) {
15219 o.status.repr = wuffs_base__suspension__short_read;
15220 } else {
15221 o.status.repr = NULL;
15222 }
15223 }
15224
15225 uint8_t* d = dst.ptr;
15226 uint8_t* s = src.ptr;
15227 size_t n = len;
15228
15229 while (n--) {
15230 uint8_t c = *s;
15231 d[0] = '\\';
15232 d[1] = 'x';
15233 d[2] = wuffs_base__private_implementation__encode_base16[c >> 4];
15234 d[3] = wuffs_base__private_implementation__encode_base16[c & 0x0F];
15235 d += 4;
15236 s += 1;
15237 }
15238
15239 o.num_dst = len * 4;
15240 o.num_src = len;
15241 return o;
15242}
15243
15244// ---------------- Base-64
15245
15246// The two base-64 alphabets, std and url, differ only in the last two codes.
15247// - std: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
15248// - url: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
15249
15250static const uint8_t wuffs_base__base_64__decode_std[256] = {
15251 // 0 1 2 3 4 5 6 7
15252 // 8 9 A B C D E F
15253 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07.
15254 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F.
15255 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17.
15256 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F.
15257 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27.
15258 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, // 0x28 ..= 0x2F.
15259 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37.
15260 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F.
15261
15262 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47.
15263 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F.
15264 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57.
15265 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x58 ..= 0x5F.
15266 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67.
15267 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F.
15268 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77.
15269 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F.
15270
15271 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87.
15272 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F.
15273 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97.
15274 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F.
15275 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7.
15276 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF.
15277 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB0 ..= 0xB7.
15278 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB8 ..= 0xBF.
15279
15280 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC0 ..= 0xC7.
15281 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC8 ..= 0xCF.
15282 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD0 ..= 0xD7.
15283 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD8 ..= 0xDF.
15284 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE0 ..= 0xE7.
15285 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE8 ..= 0xEF.
15286 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7.
15287 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF.
15288 // 0 1 2 3 4 5 6 7
15289 // 8 9 A B C D E F
15290};
15291
15292static const uint8_t wuffs_base__base_64__decode_url[256] = {
15293 // 0 1 2 3 4 5 6 7
15294 // 8 9 A B C D E F
15295 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07.
15296 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F.
15297 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17.
15298 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F.
15299 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27.
15300 0x80, 0x80, 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, // 0x28 ..= 0x2F.
15301 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37.
15302 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F.
15303
15304 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47.
15305 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F.
15306 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57.
15307 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x3F, // 0x58 ..= 0x5F.
15308 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67.
15309 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F.
15310 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77.
15311 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F.
15312
15313 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87.
15314 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F.
15315 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97.
15316 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F.
15317 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7.
15318 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF.
15319 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB0 ..= 0xB7.
15320 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB8 ..= 0xBF.
15321
15322 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC0 ..= 0xC7.
15323 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC8 ..= 0xCF.
15324 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD0 ..= 0xD7.
15325 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD8 ..= 0xDF.
15326 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE0 ..= 0xE7.
15327 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE8 ..= 0xEF.
15328 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7.
15329 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF.
15330 // 0 1 2 3 4 5 6 7
15331 // 8 9 A B C D E F
15332};
15333
15334static const uint8_t wuffs_base__base_64__encode_std[64] = {
15335 // 0 1 2 3 4 5 6 7
15336 // 8 9 A B C D E F
15337 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // 0x00 ..= 0x07.
15338 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, // 0x08 ..= 0x0F.
15339 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, // 0x10 ..= 0x17.
15340 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 0x18 ..= 0x1F.
15341 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, // 0x20 ..= 0x27.
15342 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, // 0x28 ..= 0x2F.
15343 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, // 0x30 ..= 0x37.
15344 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F, // 0x38 ..= 0x3F.
15345};
15346
15347static const uint8_t wuffs_base__base_64__encode_url[64] = {
15348 // 0 1 2 3 4 5 6 7
15349 // 8 9 A B C D E F
15350 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // 0x00 ..= 0x07.
15351 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, // 0x08 ..= 0x0F.
15352 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, // 0x10 ..= 0x17.
15353 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 0x18 ..= 0x1F.
15354 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, // 0x20 ..= 0x27.
15355 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, // 0x28 ..= 0x2F.
15356 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, // 0x30 ..= 0x37.
15357 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2D, 0x5F, // 0x38 ..= 0x3F.
15358};
15359
15360// --------
15361
15362WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15363wuffs_base__base_64__decode(wuffs_base__slice_u8 dst,
15364 wuffs_base__slice_u8 src,
15365 bool src_closed,
15366 uint32_t options) {
15367 const uint8_t* alphabet = (options & WUFFS_BASE__BASE_64__URL_ALPHABET)
15368 ? wuffs_base__base_64__decode_url
15369 : wuffs_base__base_64__decode_std;
15370 wuffs_base__transform__output o;
15371 uint8_t* d_ptr = dst.ptr;
15372 size_t d_len = dst.len;
15373 const uint8_t* s_ptr = src.ptr;
15374 size_t s_len = src.len;
15375 bool pad = false;
15376
15377 while (s_len >= 4) {
15378 uint32_t s = wuffs_base__peek_u32le__no_bounds_check(s_ptr);
15379 uint32_t s0 = alphabet[0xFF & (s >> 0)];
15380 uint32_t s1 = alphabet[0xFF & (s >> 8)];
15381 uint32_t s2 = alphabet[0xFF & (s >> 16)];
15382 uint32_t s3 = alphabet[0xFF & (s >> 24)];
15383
15384 if (((s0 | s1 | s2 | s3) & 0xC0) != 0) {
15385 if (s_len > 4) {
15386 o.status.repr = wuffs_base__error__bad_data;
15387 goto done;
15388 } else if (!src_closed) {
15389 o.status.repr = wuffs_base__suspension__short_read;
15390 goto done;
15391 } else if ((options & WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING) &&
15392 (s_ptr[3] == '=')) {
15393 pad = true;
15394 if (s_ptr[2] == '=') {
15395 goto src2;
15396 }
15397 goto src3;
15398 }
15399 o.status.repr = wuffs_base__error__bad_data;
15400 goto done;
15401 }
15402
15403 if (d_len < 3) {
15404 o.status.repr = wuffs_base__suspension__short_write;
15405 goto done;
15406 }
15407
15408 s_ptr += 4;
15409 s_len -= 4;
15410 s = (s0 << 18) | (s1 << 12) | (s2 << 6) | (s3 << 0);
15411 *d_ptr++ = (uint8_t)(s >> 16);
15412 *d_ptr++ = (uint8_t)(s >> 8);
15413 *d_ptr++ = (uint8_t)(s >> 0);
15414 d_len -= 3;
15415 }
15416
15417 if (!src_closed) {
15418 o.status.repr = wuffs_base__suspension__short_read;
15419 goto done;
15420 }
15421
15422 if (s_len == 0) {
15423 o.status.repr = NULL;
15424 goto done;
15425 } else if (s_len == 1) {
15426 o.status.repr = wuffs_base__error__bad_data;
15427 goto done;
15428 } else if (s_len == 2) {
15429 goto src2;
15430 }
15431
15432src3:
15433 do {
15434 uint32_t s = wuffs_base__peek_u24le__no_bounds_check(s_ptr);
15435 uint32_t s0 = alphabet[0xFF & (s >> 0)];
15436 uint32_t s1 = alphabet[0xFF & (s >> 8)];
15437 uint32_t s2 = alphabet[0xFF & (s >> 16)];
15438 if ((s0 & 0xC0) || (s1 & 0xC0) || (s2 & 0xC3)) {
15439 o.status.repr = wuffs_base__error__bad_data;
15440 goto done;
15441 }
15442 if (d_len < 2) {
15443 o.status.repr = wuffs_base__suspension__short_write;
15444 goto done;
15445 }
15446 s_ptr += pad ? 4 : 3;
15447 s = (s0 << 18) | (s1 << 12) | (s2 << 6);
15448 *d_ptr++ = (uint8_t)(s >> 16);
15449 *d_ptr++ = (uint8_t)(s >> 8);
15450 o.status.repr = NULL;
15451 goto done;
15452 } while (0);
15453
15454src2:
15455 do {
15456 uint32_t s = wuffs_base__peek_u16le__no_bounds_check(s_ptr);
15457 uint32_t s0 = alphabet[0xFF & (s >> 0)];
15458 uint32_t s1 = alphabet[0xFF & (s >> 8)];
15459 if ((s0 & 0xC0) || (s1 & 0xCF)) {
15460 o.status.repr = wuffs_base__error__bad_data;
15461 goto done;
15462 }
15463 if (d_len < 1) {
15464 o.status.repr = wuffs_base__suspension__short_write;
15465 goto done;
15466 }
15467 s_ptr += pad ? 4 : 2;
15468 s = (s0 << 18) | (s1 << 12);
15469 *d_ptr++ = (uint8_t)(s >> 16);
15470 o.status.repr = NULL;
15471 goto done;
15472 } while (0);
15473
15474done:
15475 o.num_dst = (size_t)(d_ptr - dst.ptr);
15476 o.num_src = (size_t)(s_ptr - src.ptr);
15477 return o;
15478}
15479
15480WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15481wuffs_base__base_64__encode(wuffs_base__slice_u8 dst,
15482 wuffs_base__slice_u8 src,
15483 bool src_closed,
15484 uint32_t options) {
15485 const uint8_t* alphabet = (options & WUFFS_BASE__BASE_64__URL_ALPHABET)
15486 ? wuffs_base__base_64__encode_url
15487 : wuffs_base__base_64__encode_std;
15488 wuffs_base__transform__output o;
15489 uint8_t* d_ptr = dst.ptr;
15490 size_t d_len = dst.len;
15491 const uint8_t* s_ptr = src.ptr;
15492 size_t s_len = src.len;
15493
15494 do {
15495 while (s_len >= 3) {
15496 if (d_len < 4) {
15497 o.status.repr = wuffs_base__suspension__short_write;
15498 goto done;
15499 }
15500 uint32_t s = wuffs_base__peek_u24be__no_bounds_check(s_ptr);
15501 s_ptr += 3;
15502 s_len -= 3;
15503 *d_ptr++ = alphabet[0x3F & (s >> 18)];
15504 *d_ptr++ = alphabet[0x3F & (s >> 12)];
15505 *d_ptr++ = alphabet[0x3F & (s >> 6)];
15506 *d_ptr++ = alphabet[0x3F & (s >> 0)];
15507 d_len -= 4;
15508 }
15509
15510 if (!src_closed) {
15511 o.status.repr = wuffs_base__suspension__short_read;
15512 goto done;
15513 }
15514
15515 if (s_len == 2) {
15516 if (d_len <
15517 ((options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) ? 4 : 3)) {
15518 o.status.repr = wuffs_base__suspension__short_write;
15519 goto done;
15520 }
15521 uint32_t s = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(s_ptr)))
15522 << 8;
15523 s_ptr += 2;
15524 *d_ptr++ = alphabet[0x3F & (s >> 18)];
15525 *d_ptr++ = alphabet[0x3F & (s >> 12)];
15526 *d_ptr++ = alphabet[0x3F & (s >> 6)];
15527 if (options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) {
15528 *d_ptr++ = '=';
15529 }
15530 o.status.repr = NULL;
15531 goto done;
15532
15533 } else if (s_len == 1) {
15534 if (d_len <
15535 ((options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) ? 4 : 2)) {
15536 o.status.repr = wuffs_base__suspension__short_write;
15537 goto done;
15538 }
15539 uint32_t s = ((uint32_t)(wuffs_base__peek_u8__no_bounds_check(s_ptr)))
15540 << 16;
15541 s_ptr += 1;
15542 *d_ptr++ = alphabet[0x3F & (s >> 18)];
15543 *d_ptr++ = alphabet[0x3F & (s >> 12)];
15544 if (options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) {
15545 *d_ptr++ = '=';
15546 *d_ptr++ = '=';
15547 }
15548 o.status.repr = NULL;
15549 goto done;
15550
15551 } else {
15552 o.status.repr = NULL;
15553 goto done;
15554 }
15555 } while (0);
15556
15557done:
15558 o.num_dst = (size_t)(d_ptr - dst.ptr);
15559 o.num_src = (size_t)(s_ptr - src.ptr);
15560 return o;
15561}
15562
15563#endif // !defined(WUFFS_CONFIG__MODULES) ||
15564 // defined(WUFFS_CONFIG__MODULE__BASE) ||
15565 // defined(WUFFS_CONFIG__MODULE__BASE__INTCONV)
15566
15567#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
15568 defined(WUFFS_CONFIG__MODULE__BASE__MAGIC)
15569
15570// ---------------- Magic Numbers
15571
15572WUFFS_BASE__MAYBE_STATIC int32_t //
15573wuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix) {
15574 // table holds the 'magic numbers' (which are actually variable length
15575 // strings). The strings may contain NUL bytes, so the "const char* magic"
15576 // value starts with the length-minus-1 of the 'magic number'.
15577 //
15578 // Keep it sorted by magic[1], then magic[0] descending and finally by
15579 // magic[2:]. When multiple entries match, the longest one wins.
Nigel Taobf9dab32021-11-18 19:19:55 +110015580 //
15581 // The fourcc field might be negated, in which case there's further
15582 // specialization (see § below).
Nigel Taoe360a532021-04-05 22:47:03 +100015583 static struct {
15584 int32_t fourcc;
15585 const char* magic;
15586 } table[] = {
Nigel Taobf9dab32021-11-18 19:19:55 +110015587 {-0x30302020, "\x01\x00\x00"}, // '00 'be
15588 {+0x424D5020, "\x01\x42\x4D"}, // BMP
15589 {+0x47494620, "\x03\x47\x49\x46\x38"}, // GIF
15590 {+0x54494646, "\x03\x49\x49\x2A\x00"}, // TIFF (little-endian)
15591 {+0x54494646, "\x03\x4D\x4D\x00\x2A"}, // TIFF (big-endian)
15592 {-0x52494646, "\x03\x52\x49\x46\x46"}, // RIFF
15593 {+0x4E494520, "\x02\x6E\xC3\xAF"}, // NIE
15594 {+0x504E4720, "\x03\x89\x50\x4E\x47"}, // PNG
15595 {+0x4A504547, "\x01\xFF\xD8"}, // JPEG
Nigel Taoe360a532021-04-05 22:47:03 +100015596 };
15597 static const size_t table_len = sizeof(table) / sizeof(table[0]);
15598
15599 if (prefix.len == 0) {
15600 return -1;
15601 }
15602 uint8_t pre_first_byte = prefix.ptr[0];
15603
15604 int32_t fourcc = 0;
15605 size_t i;
15606 for (i = 0; i < table_len; i++) {
15607 uint8_t mag_first_byte = ((uint8_t)(table[i].magic[1]));
15608 if (pre_first_byte < mag_first_byte) {
15609 break;
15610 } else if (pre_first_byte > mag_first_byte) {
15611 continue;
15612 }
15613 fourcc = table[i].fourcc;
15614
15615 uint8_t mag_remaining_len = ((uint8_t)(table[i].magic[0]));
15616 if (mag_remaining_len == 0) {
15617 goto match;
15618 }
15619
15620 const char* mag_remaining_ptr = table[i].magic + 2;
15621 uint8_t* pre_remaining_ptr = prefix.ptr + 1;
15622 size_t pre_remaining_len = prefix.len - 1;
15623 if (pre_remaining_len < mag_remaining_len) {
15624 if (!memcmp(pre_remaining_ptr, mag_remaining_ptr, pre_remaining_len)) {
15625 return -1;
15626 }
15627 } else {
15628 if (!memcmp(pre_remaining_ptr, mag_remaining_ptr, mag_remaining_len)) {
15629 goto match;
15630 }
15631 }
15632 }
15633 return 0;
15634
15635match:
Nigel Taobf9dab32021-11-18 19:19:55 +110015636 // Negative FourCC values (see § above) are further specialized.
15637 if (fourcc < 0) {
15638 fourcc = -fourcc;
15639
15640 if (fourcc == 0x52494646) { // 'RIFF'be
15641 if (prefix.len < 16) {
15642 return -1;
Nigel Taoe360a532021-04-05 22:47:03 +100015643 }
Nigel Taobf9dab32021-11-18 19:19:55 +110015644 uint32_t x = wuffs_base__peek_u32be__no_bounds_check(prefix.ptr + 8);
15645 if (x == 0x57454250) { // 'WEBP'be
15646 uint32_t y = wuffs_base__peek_u32be__no_bounds_check(prefix.ptr + 12);
15647 if (y == 0x56503820) { // 'VP8 'be
15648 return 0x57503820; // 'WP8 'be
15649 } else if (y == 0x5650384C) { // 'VP8L'be
15650 return 0x5750384C; // 'WP8L'be
15651 }
15652 }
15653
15654 } else if (fourcc == 0x30302020) { // '00 'be
15655 // Binary data starting with multiple 0x00 NUL bytes is quite common.
15656 if (prefix.len < 4) {
15657 return -1;
15658 } else if ((prefix.ptr[2] != 0x00) &&
15659 ((prefix.ptr[2] >= 0x80) || (prefix.ptr[3] != 0x00))) {
15660 // Roughly speaking, this could be a non-degenerate (non-0-width and
15661 // non-0-height) WBMP image.
15662 return 0x57424D50; // 'WBMP'be
15663 } else if (((prefix.ptr[2] == 0x01) || (prefix.ptr[2] == 0x02)) &&
15664 (prefix.ptr[3] == 0x00)) {
15665 return 0x49434F20; // 'ICO 'be
15666 }
15667 return 0;
Nigel Taoe360a532021-04-05 22:47:03 +100015668 }
15669 }
15670 return fourcc;
15671}
15672
15673#endif // !defined(WUFFS_CONFIG__MODULES) ||
15674 // defined(WUFFS_CONFIG__MODULE__BASE) ||
15675 // defined(WUFFS_CONFIG__MODULE__BASE__MAGIC)
15676
15677#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
15678 defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV)
15679
15680// ---------------- Pixel Swizzler
15681
15682static inline uint32_t //
15683wuffs_base__swap_u32_argb_abgr(uint32_t u) {
15684 uint32_t o = u & 0xFF00FF00ul;
15685 uint32_t r = u & 0x00FF0000ul;
15686 uint32_t b = u & 0x000000FFul;
15687 return o | (r >> 16) | (b << 16);
15688}
15689
15690static inline uint64_t //
15691wuffs_base__swap_u64_argb_abgr(uint64_t u) {
15692 uint64_t o = u & 0xFFFF0000FFFF0000ull;
15693 uint64_t r = u & 0x0000FFFF00000000ull;
15694 uint64_t b = u & 0x000000000000FFFFull;
15695 return o | (r >> 32) | (b << 32);
15696}
15697
15698static inline uint32_t //
15699wuffs_base__color_u64__as__color_u32__swap_u32_argb_abgr(uint64_t c) {
15700 uint32_t a = ((uint32_t)(0xFF & (c >> 56)));
15701 uint32_t r = ((uint32_t)(0xFF & (c >> 40)));
15702 uint32_t g = ((uint32_t)(0xFF & (c >> 24)));
15703 uint32_t b = ((uint32_t)(0xFF & (c >> 8)));
15704 return (a << 24) | (b << 16) | (g << 8) | (r << 0);
15705}
15706
15707// --------
15708
15709WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //
15710wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,
15711 uint32_t x,
15712 uint32_t y) {
15713 if (!pb || (x >= pb->pixcfg.private_impl.width) ||
15714 (y >= pb->pixcfg.private_impl.height)) {
15715 return 0;
15716 }
15717
15718 if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
15719 // TODO: support planar formats.
15720 return 0;
15721 }
15722
15723 size_t stride = pb->private_impl.planes[0].stride;
15724 const uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
15725
15726 switch (pb->pixcfg.private_impl.pixfmt.repr) {
15727 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
15728 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
15729 return wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)));
15730
15731 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
15732 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {
15733 uint8_t* palette = pb->private_impl.planes[3].ptr;
15734 return wuffs_base__peek_u32le__no_bounds_check(palette +
15735 (4 * ((size_t)row[x])));
15736 }
15737
15738 // Common formats above. Rarer formats below.
15739
15740 case WUFFS_BASE__PIXEL_FORMAT__Y:
15741 return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x])));
15742 case WUFFS_BASE__PIXEL_FORMAT__Y_16LE:
15743 return 0xFF000000 | (0x00010101 * ((uint32_t)(row[(2 * x) + 1])));
15744 case WUFFS_BASE__PIXEL_FORMAT__Y_16BE:
15745 return 0xFF000000 | (0x00010101 * ((uint32_t)(row[(2 * x) + 0])));
15746
15747 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: {
15748 uint8_t* palette = pb->private_impl.planes[3].ptr;
15749 return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
15750 wuffs_base__peek_u32le__no_bounds_check(palette +
15751 (4 * ((size_t)row[x]))));
15752 }
15753
15754 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
15755 return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
15756 wuffs_base__peek_u16le__no_bounds_check(row + (2 * ((size_t)x))));
15757 case WUFFS_BASE__PIXEL_FORMAT__BGR:
15758 return 0xFF000000 |
15759 wuffs_base__peek_u24le__no_bounds_check(row + (3 * ((size_t)x)));
15760 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
15761 return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
15762 wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))));
15763 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
15764 return wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
15765 wuffs_base__peek_u64le__no_bounds_check(row + (8 * ((size_t)x))));
15766 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
15767 return 0xFF000000 |
15768 wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)));
15769
15770 case WUFFS_BASE__PIXEL_FORMAT__RGB:
15771 return wuffs_base__swap_u32_argb_abgr(
15772 0xFF000000 |
15773 wuffs_base__peek_u24le__no_bounds_check(row + (3 * ((size_t)x))));
15774 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
15775 return wuffs_base__swap_u32_argb_abgr(
15776 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
15777 wuffs_base__peek_u32le__no_bounds_check(row +
15778 (4 * ((size_t)x)))));
15779 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
15780 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
15781 return wuffs_base__swap_u32_argb_abgr(
15782 wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))));
15783 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
15784 return wuffs_base__swap_u32_argb_abgr(
15785 0xFF000000 |
15786 wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))));
15787
15788 default:
15789 // TODO: support more formats.
15790 break;
15791 }
15792
15793 return 0;
15794}
15795
15796// --------
15797
15798WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
15799wuffs_base__pixel_buffer__set_color_u32_at(
15800 wuffs_base__pixel_buffer* pb,
15801 uint32_t x,
15802 uint32_t y,
15803 wuffs_base__color_u32_argb_premul color) {
15804 if (!pb) {
15805 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
15806 }
15807 if ((x >= pb->pixcfg.private_impl.width) ||
15808 (y >= pb->pixcfg.private_impl.height)) {
15809 return wuffs_base__make_status(wuffs_base__error__bad_argument);
15810 }
15811
15812 if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
15813 // TODO: support planar formats.
15814 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
15815 }
15816
15817 size_t stride = pb->private_impl.planes[0].stride;
15818 uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
15819
15820 switch (pb->pixcfg.private_impl.pixfmt.repr) {
15821 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
15822 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
15823 wuffs_base__poke_u32le__no_bounds_check(row + (4 * ((size_t)x)), color);
15824 break;
15825
15826 // Common formats above. Rarer formats below.
15827
15828 case WUFFS_BASE__PIXEL_FORMAT__Y:
15829 wuffs_base__poke_u8__no_bounds_check(
15830 row + ((size_t)x),
15831 wuffs_base__color_u32_argb_premul__as__color_u8_gray(color));
15832 break;
15833 case WUFFS_BASE__PIXEL_FORMAT__Y_16LE:
15834 wuffs_base__poke_u16le__no_bounds_check(
15835 row + (2 * ((size_t)x)),
15836 wuffs_base__color_u32_argb_premul__as__color_u16_gray(color));
15837 break;
15838 case WUFFS_BASE__PIXEL_FORMAT__Y_16BE:
15839 wuffs_base__poke_u16be__no_bounds_check(
15840 row + (2 * ((size_t)x)),
15841 wuffs_base__color_u32_argb_premul__as__color_u16_gray(color));
15842 break;
15843
15844 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
15845 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
15846 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
15847 wuffs_base__poke_u8__no_bounds_check(
15848 row + ((size_t)x), wuffs_base__pixel_palette__closest_element(
15849 wuffs_base__pixel_buffer__palette(pb),
15850 pb->pixcfg.private_impl.pixfmt, color));
15851 break;
15852
15853 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
15854 wuffs_base__poke_u16le__no_bounds_check(
15855 row + (2 * ((size_t)x)),
15856 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
15857 break;
15858 case WUFFS_BASE__PIXEL_FORMAT__BGR:
15859 wuffs_base__poke_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);
15860 break;
15861 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
15862 wuffs_base__poke_u32le__no_bounds_check(
15863 row + (4 * ((size_t)x)),
15864 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
15865 color));
15866 break;
15867 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
15868 wuffs_base__poke_u64le__no_bounds_check(
15869 row + (8 * ((size_t)x)),
15870 wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(
15871 color));
15872 break;
15873
15874 case WUFFS_BASE__PIXEL_FORMAT__RGB:
15875 wuffs_base__poke_u24le__no_bounds_check(
15876 row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
15877 break;
15878 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
15879 wuffs_base__poke_u32le__no_bounds_check(
15880 row + (4 * ((size_t)x)),
15881 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
15882 wuffs_base__swap_u32_argb_abgr(color)));
15883 break;
15884 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
15885 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
15886 wuffs_base__poke_u32le__no_bounds_check(
15887 row + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
15888 break;
15889
15890 default:
15891 // TODO: support more formats.
15892 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
15893 }
15894
15895 return wuffs_base__make_status(NULL);
15896}
15897
15898// --------
15899
15900static inline void //
15901wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(
15902 wuffs_base__pixel_buffer* pb,
15903 wuffs_base__rect_ie_u32 rect,
15904 uint16_t color) {
15905 size_t stride = pb->private_impl.planes[0].stride;
15906 uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
15907 if ((stride == (2 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
15908 uint8_t* ptr =
15909 pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
15910 uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
15911 size_t n;
15912 for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
15913 wuffs_base__poke_u16le__no_bounds_check(ptr, color);
15914 ptr += 2;
15915 }
15916 return;
15917 }
15918
15919 uint32_t y;
15920 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
15921 uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
15922 (2 * ((size_t)rect.min_incl_x));
15923 uint32_t n;
15924 for (n = width; n > 0; n--) {
15925 wuffs_base__poke_u16le__no_bounds_check(ptr, color);
15926 ptr += 2;
15927 }
15928 }
15929}
15930
15931static inline void //
15932wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(
15933 wuffs_base__pixel_buffer* pb,
15934 wuffs_base__rect_ie_u32 rect,
15935 uint32_t color) {
15936 size_t stride = pb->private_impl.planes[0].stride;
15937 uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
15938 if ((stride == (3 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
15939 uint8_t* ptr =
15940 pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
15941 uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
15942 size_t n;
15943 for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
15944 wuffs_base__poke_u24le__no_bounds_check(ptr, color);
15945 ptr += 3;
15946 }
15947 return;
15948 }
15949
15950 uint32_t y;
15951 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
15952 uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
15953 (3 * ((size_t)rect.min_incl_x));
15954 uint32_t n;
15955 for (n = width; n > 0; n--) {
15956 wuffs_base__poke_u24le__no_bounds_check(ptr, color);
15957 ptr += 3;
15958 }
15959 }
15960}
15961
15962static inline void //
15963wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
15964 wuffs_base__pixel_buffer* pb,
15965 wuffs_base__rect_ie_u32 rect,
15966 uint32_t color) {
15967 size_t stride = pb->private_impl.planes[0].stride;
15968 uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
15969 if ((stride == (4 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
15970 uint8_t* ptr =
15971 pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
15972 uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
15973 size_t n;
15974 for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
15975 wuffs_base__poke_u32le__no_bounds_check(ptr, color);
15976 ptr += 4;
15977 }
15978 return;
15979 }
15980
15981 uint32_t y;
15982 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
15983 uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
15984 (4 * ((size_t)rect.min_incl_x));
15985 uint32_t n;
15986 for (n = width; n > 0; n--) {
15987 wuffs_base__poke_u32le__no_bounds_check(ptr, color);
15988 ptr += 4;
15989 }
15990 }
15991}
15992
15993static inline void //
15994wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(
15995 wuffs_base__pixel_buffer* pb,
15996 wuffs_base__rect_ie_u32 rect,
15997 uint64_t color) {
15998 size_t stride = pb->private_impl.planes[0].stride;
15999 uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
16000 if ((stride == (8 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
16001 uint8_t* ptr =
16002 pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
16003 uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
16004 size_t n;
16005 for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
16006 wuffs_base__poke_u64le__no_bounds_check(ptr, color);
16007 ptr += 8;
16008 }
16009 return;
16010 }
16011
16012 uint32_t y;
16013 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
16014 uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
16015 (8 * ((size_t)rect.min_incl_x));
16016 uint32_t n;
16017 for (n = width; n > 0; n--) {
16018 wuffs_base__poke_u64le__no_bounds_check(ptr, color);
16019 ptr += 8;
16020 }
16021 }
16022}
16023
16024WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
16025wuffs_base__pixel_buffer__set_color_u32_fill_rect(
16026 wuffs_base__pixel_buffer* pb,
16027 wuffs_base__rect_ie_u32 rect,
16028 wuffs_base__color_u32_argb_premul color) {
16029 if (!pb) {
16030 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
16031 } else if (wuffs_base__rect_ie_u32__is_empty(&rect)) {
16032 return wuffs_base__make_status(NULL);
16033 }
16034 wuffs_base__rect_ie_u32 bounds =
16035 wuffs_base__pixel_config__bounds(&pb->pixcfg);
16036 if (!wuffs_base__rect_ie_u32__contains_rect(&bounds, rect)) {
16037 return wuffs_base__make_status(wuffs_base__error__bad_argument);
16038 }
16039
16040 if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
16041 // TODO: support planar formats.
16042 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
16043 }
16044
16045 switch (pb->pixcfg.private_impl.pixfmt.repr) {
16046 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
16047 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
16048 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, color);
16049 return wuffs_base__make_status(NULL);
16050
16051 // Common formats above. Rarer formats below.
16052
16053 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
16054 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(
16055 pb, rect,
16056 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
16057 return wuffs_base__make_status(NULL);
16058
16059 case WUFFS_BASE__PIXEL_FORMAT__BGR:
16060 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(pb, rect, color);
16061 return wuffs_base__make_status(NULL);
16062
16063 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
16064 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
16065 pb, rect,
16066 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
16067 color));
16068 return wuffs_base__make_status(NULL);
16069
16070 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
16071 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(
16072 pb, rect,
16073 wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(
16074 color));
16075 return wuffs_base__make_status(NULL);
16076
16077 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
16078 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
16079 pb, rect,
16080 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
16081 wuffs_base__swap_u32_argb_abgr(color)));
16082 return wuffs_base__make_status(NULL);
16083
16084 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
16085 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
16086 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
16087 pb, rect, wuffs_base__swap_u32_argb_abgr(color));
16088 return wuffs_base__make_status(NULL);
16089 }
16090
16091 uint32_t y;
16092 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
16093 uint32_t x;
16094 for (x = rect.min_incl_x; x < rect.max_excl_x; x++) {
16095 wuffs_base__pixel_buffer__set_color_u32_at(pb, x, y, color);
16096 }
16097 }
16098 return wuffs_base__make_status(NULL);
16099}
16100
16101// --------
16102
16103WUFFS_BASE__MAYBE_STATIC uint8_t //
16104wuffs_base__pixel_palette__closest_element(
16105 wuffs_base__slice_u8 palette_slice,
16106 wuffs_base__pixel_format palette_format,
16107 wuffs_base__color_u32_argb_premul c) {
16108 size_t n = palette_slice.len / 4;
16109 if (n > (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
16110 n = (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4);
16111 }
16112 size_t best_index = 0;
16113 uint64_t best_score = 0xFFFFFFFFFFFFFFFF;
16114
16115 // Work in 16-bit color.
16116 uint32_t ca = 0x101 * (0xFF & (c >> 24));
16117 uint32_t cr = 0x101 * (0xFF & (c >> 16));
16118 uint32_t cg = 0x101 * (0xFF & (c >> 8));
16119 uint32_t cb = 0x101 * (0xFF & (c >> 0));
16120
16121 switch (palette_format.repr) {
16122 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
16123 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
16124 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {
16125 bool nonpremul = palette_format.repr ==
16126 WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;
16127
16128 size_t i;
16129 for (i = 0; i < n; i++) {
16130 // Work in 16-bit color.
16131 uint32_t pb = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 0]));
16132 uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));
16133 uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));
16134 uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));
16135
16136 // Convert to premultiplied alpha.
16137 if (nonpremul && (pa != 0xFFFF)) {
16138 pb = (pb * pa) / 0xFFFF;
16139 pg = (pg * pa) / 0xFFFF;
16140 pr = (pr * pa) / 0xFFFF;
16141 }
16142
16143 // These deltas are conceptually int32_t (signed) but after squaring,
16144 // it's equivalent to work in uint32_t (unsigned).
16145 pb -= cb;
16146 pg -= cg;
16147 pr -= cr;
16148 pa -= ca;
16149 uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +
16150 ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));
16151 if (best_score > score) {
16152 best_score = score;
16153 best_index = i;
16154 }
16155 }
16156 break;
16157 }
16158 }
16159
16160 return (uint8_t)best_index;
16161}
16162
16163// --------
16164
16165static inline uint32_t //
16166wuffs_base__composite_nonpremul_nonpremul_u32_axxx(uint32_t dst_nonpremul,
16167 uint32_t src_nonpremul) {
16168 // Extract 16-bit color components.
16169 uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24));
16170 uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16));
16171 uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8));
16172 uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0));
16173 uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24));
16174 uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16));
16175 uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8));
16176 uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0));
16177
16178 // Convert dst from nonpremul to premul.
16179 dr = (dr * da) / 0xFFFF;
16180 dg = (dg * da) / 0xFFFF;
16181 db = (db * da) / 0xFFFF;
16182
16183 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16184 uint32_t ia = 0xFFFF - sa;
16185
16186 // Composite src (nonpremul) over dst (premul).
16187 da = sa + ((da * ia) / 0xFFFF);
16188 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
16189 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
16190 db = ((sb * sa) + (db * ia)) / 0xFFFF;
16191
16192 // Convert dst from premul to nonpremul.
16193 if (da != 0) {
16194 dr = (dr * 0xFFFF) / da;
16195 dg = (dg * 0xFFFF) / da;
16196 db = (db * 0xFFFF) / da;
16197 }
16198
16199 // Convert from 16-bit color to 8-bit color.
16200 da >>= 8;
16201 dr >>= 8;
16202 dg >>= 8;
16203 db >>= 8;
16204
16205 // Combine components.
16206 return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);
16207}
16208
16209static inline uint64_t //
16210wuffs_base__composite_nonpremul_nonpremul_u64_axxx(uint64_t dst_nonpremul,
16211 uint64_t src_nonpremul) {
16212 // Extract components.
16213 uint64_t sa = 0xFFFF & (src_nonpremul >> 48);
16214 uint64_t sr = 0xFFFF & (src_nonpremul >> 32);
16215 uint64_t sg = 0xFFFF & (src_nonpremul >> 16);
16216 uint64_t sb = 0xFFFF & (src_nonpremul >> 0);
16217 uint64_t da = 0xFFFF & (dst_nonpremul >> 48);
16218 uint64_t dr = 0xFFFF & (dst_nonpremul >> 32);
16219 uint64_t dg = 0xFFFF & (dst_nonpremul >> 16);
16220 uint64_t db = 0xFFFF & (dst_nonpremul >> 0);
16221
16222 // Convert dst from nonpremul to premul.
16223 dr = (dr * da) / 0xFFFF;
16224 dg = (dg * da) / 0xFFFF;
16225 db = (db * da) / 0xFFFF;
16226
16227 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16228 uint64_t ia = 0xFFFF - sa;
16229
16230 // Composite src (nonpremul) over dst (premul).
16231 da = sa + ((da * ia) / 0xFFFF);
16232 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
16233 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
16234 db = ((sb * sa) + (db * ia)) / 0xFFFF;
16235
16236 // Convert dst from premul to nonpremul.
16237 if (da != 0) {
16238 dr = (dr * 0xFFFF) / da;
16239 dg = (dg * 0xFFFF) / da;
16240 db = (db * 0xFFFF) / da;
16241 }
16242
16243 // Combine components.
16244 return (db << 0) | (dg << 16) | (dr << 32) | (da << 48);
16245}
16246
16247static inline uint32_t //
16248wuffs_base__composite_nonpremul_premul_u32_axxx(uint32_t dst_nonpremul,
16249 uint32_t src_premul) {
16250 // Extract 16-bit color components.
16251 uint32_t sa = 0x101 * (0xFF & (src_premul >> 24));
16252 uint32_t sr = 0x101 * (0xFF & (src_premul >> 16));
16253 uint32_t sg = 0x101 * (0xFF & (src_premul >> 8));
16254 uint32_t sb = 0x101 * (0xFF & (src_premul >> 0));
16255 uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24));
16256 uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16));
16257 uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8));
16258 uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0));
16259
16260 // Convert dst from nonpremul to premul.
16261 dr = (dr * da) / 0xFFFF;
16262 dg = (dg * da) / 0xFFFF;
16263 db = (db * da) / 0xFFFF;
16264
16265 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16266 uint32_t ia = 0xFFFF - sa;
16267
16268 // Composite src (premul) over dst (premul).
16269 da = sa + ((da * ia) / 0xFFFF);
16270 dr = sr + ((dr * ia) / 0xFFFF);
16271 dg = sg + ((dg * ia) / 0xFFFF);
16272 db = sb + ((db * ia) / 0xFFFF);
16273
16274 // Convert dst from premul to nonpremul.
16275 if (da != 0) {
16276 dr = (dr * 0xFFFF) / da;
16277 dg = (dg * 0xFFFF) / da;
16278 db = (db * 0xFFFF) / da;
16279 }
16280
16281 // Convert from 16-bit color to 8-bit color.
16282 da >>= 8;
16283 dr >>= 8;
16284 dg >>= 8;
16285 db >>= 8;
16286
16287 // Combine components.
16288 return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);
16289}
16290
16291static inline uint64_t //
16292wuffs_base__composite_nonpremul_premul_u64_axxx(uint64_t dst_nonpremul,
16293 uint64_t src_premul) {
16294 // Extract components.
16295 uint64_t sa = 0xFFFF & (src_premul >> 48);
16296 uint64_t sr = 0xFFFF & (src_premul >> 32);
16297 uint64_t sg = 0xFFFF & (src_premul >> 16);
16298 uint64_t sb = 0xFFFF & (src_premul >> 0);
16299 uint64_t da = 0xFFFF & (dst_nonpremul >> 48);
16300 uint64_t dr = 0xFFFF & (dst_nonpremul >> 32);
16301 uint64_t dg = 0xFFFF & (dst_nonpremul >> 16);
16302 uint64_t db = 0xFFFF & (dst_nonpremul >> 0);
16303
16304 // Convert dst from nonpremul to premul.
16305 dr = (dr * da) / 0xFFFF;
16306 dg = (dg * da) / 0xFFFF;
16307 db = (db * da) / 0xFFFF;
16308
16309 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16310 uint64_t ia = 0xFFFF - sa;
16311
16312 // Composite src (premul) over dst (premul).
16313 da = sa + ((da * ia) / 0xFFFF);
16314 dr = sr + ((dr * ia) / 0xFFFF);
16315 dg = sg + ((dg * ia) / 0xFFFF);
16316 db = sb + ((db * ia) / 0xFFFF);
16317
16318 // Convert dst from premul to nonpremul.
16319 if (da != 0) {
16320 dr = (dr * 0xFFFF) / da;
16321 dg = (dg * 0xFFFF) / da;
16322 db = (db * 0xFFFF) / da;
16323 }
16324
16325 // Combine components.
16326 return (db << 0) | (dg << 16) | (dr << 32) | (da << 48);
16327}
16328
16329static inline uint32_t //
16330wuffs_base__composite_premul_nonpremul_u32_axxx(uint32_t dst_premul,
16331 uint32_t src_nonpremul) {
16332 // Extract 16-bit color components.
16333 uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24));
16334 uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16));
16335 uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8));
16336 uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0));
16337 uint32_t da = 0x101 * (0xFF & (dst_premul >> 24));
16338 uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16));
16339 uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8));
16340 uint32_t db = 0x101 * (0xFF & (dst_premul >> 0));
16341
16342 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16343 uint32_t ia = 0xFFFF - sa;
16344
16345 // Composite src (nonpremul) over dst (premul).
16346 da = sa + ((da * ia) / 0xFFFF);
16347 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
16348 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
16349 db = ((sb * sa) + (db * ia)) / 0xFFFF;
16350
16351 // Convert from 16-bit color to 8-bit color.
16352 da >>= 8;
16353 dr >>= 8;
16354 dg >>= 8;
16355 db >>= 8;
16356
16357 // Combine components.
16358 return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);
16359}
16360
16361static inline uint64_t //
16362wuffs_base__composite_premul_nonpremul_u64_axxx(uint64_t dst_premul,
16363 uint64_t src_nonpremul) {
16364 // Extract components.
16365 uint64_t sa = 0xFFFF & (src_nonpremul >> 48);
16366 uint64_t sr = 0xFFFF & (src_nonpremul >> 32);
16367 uint64_t sg = 0xFFFF & (src_nonpremul >> 16);
16368 uint64_t sb = 0xFFFF & (src_nonpremul >> 0);
16369 uint64_t da = 0xFFFF & (dst_premul >> 48);
16370 uint64_t dr = 0xFFFF & (dst_premul >> 32);
16371 uint64_t dg = 0xFFFF & (dst_premul >> 16);
16372 uint64_t db = 0xFFFF & (dst_premul >> 0);
16373
16374 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16375 uint64_t ia = 0xFFFF - sa;
16376
16377 // Composite src (nonpremul) over dst (premul).
16378 da = sa + ((da * ia) / 0xFFFF);
16379 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
16380 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
16381 db = ((sb * sa) + (db * ia)) / 0xFFFF;
16382
16383 // Combine components.
16384 return (db << 0) | (dg << 16) | (dr << 32) | (da << 48);
16385}
16386
16387static inline uint32_t //
16388wuffs_base__composite_premul_premul_u32_axxx(uint32_t dst_premul,
16389 uint32_t src_premul) {
16390 // Extract 16-bit color components.
16391 uint32_t sa = 0x101 * (0xFF & (src_premul >> 24));
16392 uint32_t sr = 0x101 * (0xFF & (src_premul >> 16));
16393 uint32_t sg = 0x101 * (0xFF & (src_premul >> 8));
16394 uint32_t sb = 0x101 * (0xFF & (src_premul >> 0));
16395 uint32_t da = 0x101 * (0xFF & (dst_premul >> 24));
16396 uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16));
16397 uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8));
16398 uint32_t db = 0x101 * (0xFF & (dst_premul >> 0));
16399
16400 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16401 uint32_t ia = 0xFFFF - sa;
16402
16403 // Composite src (premul) over dst (premul).
16404 da = sa + ((da * ia) / 0xFFFF);
16405 dr = sr + ((dr * ia) / 0xFFFF);
16406 dg = sg + ((dg * ia) / 0xFFFF);
16407 db = sb + ((db * ia) / 0xFFFF);
16408
16409 // Convert from 16-bit color to 8-bit color.
16410 da >>= 8;
16411 dr >>= 8;
16412 dg >>= 8;
16413 db >>= 8;
16414
16415 // Combine components.
16416 return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);
16417}
16418
16419// --------
16420
16421static uint64_t //
16422wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888(uint8_t* dst_ptr,
16423 size_t dst_len,
16424 const uint8_t* src_ptr,
16425 size_t src_len,
16426 bool nonpremul) {
16427 size_t len = (dst_len < src_len ? dst_len : src_len) / 4;
16428 uint8_t* d = dst_ptr;
16429 const uint8_t* s = src_ptr;
16430
16431 size_t n = len;
16432 while (n--) {
16433 uint32_t argb = wuffs_base__peek_u32le__no_bounds_check(s);
16434 if (nonpremul) {
16435 argb =
16436 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(argb);
16437 }
16438 uint32_t b5 = 0x1F & (argb >> (8 - 5));
16439 uint32_t g6 = 0x3F & (argb >> (16 - 6));
16440 uint32_t r5 = 0x1F & (argb >> (24 - 5));
16441 uint32_t alpha = argb & 0xFF000000;
16442 wuffs_base__poke_u32le__no_bounds_check(
16443 d, alpha | (r5 << 11) | (g6 << 5) | (b5 << 0));
16444 s += 4;
16445 d += 4;
16446 }
16447 return len;
16448}
16449
16450// --------
16451
16452static uint64_t //
16453wuffs_base__pixel_swizzler__swap_rgb_bgr(uint8_t* dst_ptr,
16454 size_t dst_len,
16455 uint8_t* dst_palette_ptr,
16456 size_t dst_palette_len,
16457 const uint8_t* src_ptr,
16458 size_t src_len) {
16459 size_t len = (dst_len < src_len ? dst_len : src_len) / 3;
16460 uint8_t* d = dst_ptr;
16461 const uint8_t* s = src_ptr;
16462
16463 size_t n = len;
16464 while (n--) {
16465 uint8_t s0 = s[0];
16466 uint8_t s1 = s[1];
16467 uint8_t s2 = s[2];
16468 d[0] = s2;
16469 d[1] = s1;
16470 d[2] = s0;
16471 s += 3;
16472 d += 3;
16473 }
16474 return len;
16475}
16476
16477// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
Nigel Tao7804ffe2021-10-07 21:58:26 +110016478#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100016479WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
16480static uint64_t //
16481wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42(uint8_t* dst_ptr,
16482 size_t dst_len,
16483 uint8_t* dst_palette_ptr,
16484 size_t dst_palette_len,
16485 const uint8_t* src_ptr,
16486 size_t src_len) {
16487 size_t len = (dst_len < src_len ? dst_len : src_len) / 4;
16488 uint8_t* d = dst_ptr;
16489 const uint8_t* s = src_ptr;
16490 size_t n = len;
16491
16492 __m128i shuffle = _mm_set_epi8(+0x0F, +0x0C, +0x0D, +0x0E, //
16493 +0x0B, +0x08, +0x09, +0x0A, //
16494 +0x07, +0x04, +0x05, +0x06, //
16495 +0x03, +0x00, +0x01, +0x02);
16496
16497 while (n >= 4) {
16498 __m128i x;
16499 x = _mm_lddqu_si128((const __m128i*)(const void*)s);
16500 x = _mm_shuffle_epi8(x, shuffle);
16501 _mm_storeu_si128((__m128i*)(void*)d, x);
16502
16503 s += 4 * 4;
16504 d += 4 * 4;
16505 n -= 4;
16506 }
16507
16508 while (n--) {
16509 uint8_t s0 = s[0];
16510 uint8_t s1 = s[1];
16511 uint8_t s2 = s[2];
16512 uint8_t s3 = s[3];
16513 d[0] = s2;
16514 d[1] = s1;
16515 d[2] = s0;
16516 d[3] = s3;
16517 s += 4;
16518 d += 4;
16519 }
16520 return len;
16521}
Nigel Tao7804ffe2021-10-07 21:58:26 +110016522#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100016523// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
16524
16525static uint64_t //
16526wuffs_base__pixel_swizzler__swap_rgbx_bgrx(uint8_t* dst_ptr,
16527 size_t dst_len,
16528 uint8_t* dst_palette_ptr,
16529 size_t dst_palette_len,
16530 const uint8_t* src_ptr,
16531 size_t src_len) {
16532 size_t len = (dst_len < src_len ? dst_len : src_len) / 4;
16533 uint8_t* d = dst_ptr;
16534 const uint8_t* s = src_ptr;
16535
16536 size_t n = len;
16537 while (n--) {
16538 uint8_t s0 = s[0];
16539 uint8_t s1 = s[1];
16540 uint8_t s2 = s[2];
16541 uint8_t s3 = s[3];
16542 d[0] = s2;
16543 d[1] = s1;
16544 d[2] = s0;
16545 d[3] = s3;
16546 s += 4;
16547 d += 4;
16548 }
16549 return len;
16550}
16551
16552// --------
16553
16554static uint64_t //
16555wuffs_base__pixel_swizzler__copy_1_1(uint8_t* dst_ptr,
16556 size_t dst_len,
16557 uint8_t* dst_palette_ptr,
16558 size_t dst_palette_len,
16559 const uint8_t* src_ptr,
16560 size_t src_len) {
16561 size_t len = (dst_len < src_len) ? dst_len : src_len;
16562 if (len > 0) {
16563 memmove(dst_ptr, src_ptr, len);
16564 }
16565 return len;
16566}
16567
16568static uint64_t //
16569wuffs_base__pixel_swizzler__copy_2_2(uint8_t* dst_ptr,
16570 size_t dst_len,
16571 uint8_t* dst_palette_ptr,
16572 size_t dst_palette_len,
16573 const uint8_t* src_ptr,
16574 size_t src_len) {
16575 size_t dst_len2 = dst_len / 2;
16576 size_t src_len2 = src_len / 2;
16577 size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2;
16578 if (len > 0) {
16579 memmove(dst_ptr, src_ptr, len * 2);
16580 }
16581 return len;
16582}
16583
16584static uint64_t //
16585wuffs_base__pixel_swizzler__copy_3_3(uint8_t* dst_ptr,
16586 size_t dst_len,
16587 uint8_t* dst_palette_ptr,
16588 size_t dst_palette_len,
16589 const uint8_t* src_ptr,
16590 size_t src_len) {
16591 size_t dst_len3 = dst_len / 3;
16592 size_t src_len3 = src_len / 3;
16593 size_t len = (dst_len3 < src_len3) ? dst_len3 : src_len3;
16594 if (len > 0) {
16595 memmove(dst_ptr, src_ptr, len * 3);
16596 }
16597 return len;
16598}
16599
16600static uint64_t //
16601wuffs_base__pixel_swizzler__copy_4_4(uint8_t* dst_ptr,
16602 size_t dst_len,
16603 uint8_t* dst_palette_ptr,
16604 size_t dst_palette_len,
16605 const uint8_t* src_ptr,
16606 size_t src_len) {
16607 size_t dst_len4 = dst_len / 4;
16608 size_t src_len4 = src_len / 4;
16609 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
16610 if (len > 0) {
16611 memmove(dst_ptr, src_ptr, len * 4);
16612 }
16613 return len;
16614}
16615
16616static uint64_t //
16617wuffs_base__pixel_swizzler__copy_8_8(uint8_t* dst_ptr,
16618 size_t dst_len,
16619 uint8_t* dst_palette_ptr,
16620 size_t dst_palette_len,
16621 const uint8_t* src_ptr,
16622 size_t src_len) {
16623 size_t dst_len8 = dst_len / 8;
16624 size_t src_len8 = src_len / 8;
16625 size_t len = (dst_len8 < src_len8) ? dst_len8 : src_len8;
16626 if (len > 0) {
16627 memmove(dst_ptr, src_ptr, len * 8);
16628 }
16629 return len;
16630}
16631
16632// --------
16633
16634static uint64_t //
16635wuffs_base__pixel_swizzler__bgr_565__bgr(uint8_t* dst_ptr,
16636 size_t dst_len,
16637 uint8_t* dst_palette_ptr,
16638 size_t dst_palette_len,
16639 const uint8_t* src_ptr,
16640 size_t src_len) {
16641 size_t dst_len2 = dst_len / 2;
16642 size_t src_len3 = src_len / 3;
16643 size_t len = (dst_len2 < src_len3) ? dst_len2 : src_len3;
16644 uint8_t* d = dst_ptr;
16645 const uint8_t* s = src_ptr;
16646 size_t n = len;
16647
16648 // TODO: unroll.
16649
16650 while (n >= 1) {
16651 uint32_t b5 = s[0] >> 3;
16652 uint32_t g6 = s[1] >> 2;
16653 uint32_t r5 = s[2] >> 3;
16654 uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0);
16655 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
16656
16657 s += 1 * 3;
16658 d += 1 * 2;
16659 n -= 1;
16660 }
16661
16662 return len;
16663}
16664
16665static uint64_t //
16666wuffs_base__pixel_swizzler__bgr_565__bgrx(uint8_t* dst_ptr,
16667 size_t dst_len,
16668 uint8_t* dst_palette_ptr,
16669 size_t dst_palette_len,
16670 const uint8_t* src_ptr,
16671 size_t src_len) {
16672 size_t dst_len2 = dst_len / 2;
16673 size_t src_len4 = src_len / 4;
16674 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
16675 uint8_t* d = dst_ptr;
16676 const uint8_t* s = src_ptr;
16677 size_t n = len;
16678
16679 // TODO: unroll.
16680
16681 while (n >= 1) {
16682 uint32_t b5 = s[0] >> 3;
16683 uint32_t g6 = s[1] >> 2;
16684 uint32_t r5 = s[2] >> 3;
16685 uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0);
16686 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
16687
16688 s += 1 * 4;
16689 d += 1 * 2;
16690 n -= 1;
16691 }
16692
16693 return len;
16694}
16695
16696static uint64_t //
16697wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src(
16698 uint8_t* dst_ptr,
16699 size_t dst_len,
16700 uint8_t* dst_palette_ptr,
16701 size_t dst_palette_len,
16702 const uint8_t* src_ptr,
16703 size_t src_len) {
16704 size_t dst_len2 = dst_len / 2;
16705 size_t src_len4 = src_len / 4;
16706 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
16707 uint8_t* d = dst_ptr;
16708 const uint8_t* s = src_ptr;
16709 size_t n = len;
16710
16711 // TODO: unroll.
16712
16713 while (n >= 1) {
16714 wuffs_base__poke_u16le__no_bounds_check(
16715 d + (0 * 2),
16716 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
16717 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
16718 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))));
16719
16720 s += 1 * 4;
16721 d += 1 * 2;
16722 n -= 1;
16723 }
16724
16725 return len;
16726}
16727
16728static uint64_t //
16729wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src(
16730 uint8_t* dst_ptr,
16731 size_t dst_len,
16732 uint8_t* dst_palette_ptr,
16733 size_t dst_palette_len,
16734 const uint8_t* src_ptr,
16735 size_t src_len) {
16736 size_t dst_len2 = dst_len / 2;
16737 size_t src_len8 = src_len / 8;
16738 size_t len = (dst_len2 < src_len8) ? dst_len2 : src_len8;
16739 uint8_t* d = dst_ptr;
16740 const uint8_t* s = src_ptr;
16741 size_t n = len;
16742
16743 // TODO: unroll.
16744
16745 while (n >= 1) {
16746 wuffs_base__poke_u16le__no_bounds_check(
16747 d + (0 * 2),
16748 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
16749 wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
16750 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)))));
16751
16752 s += 1 * 8;
16753 d += 1 * 2;
16754 n -= 1;
16755 }
16756
16757 return len;
16758}
16759
16760static uint64_t //
16761wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src_over(
16762 uint8_t* dst_ptr,
16763 size_t dst_len,
16764 uint8_t* dst_palette_ptr,
16765 size_t dst_palette_len,
16766 const uint8_t* src_ptr,
16767 size_t src_len) {
16768 size_t dst_len2 = dst_len / 2;
16769 size_t src_len4 = src_len / 4;
16770 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
16771 uint8_t* d = dst_ptr;
16772 const uint8_t* s = src_ptr;
16773 size_t n = len;
16774
16775 // TODO: unroll.
16776
16777 while (n >= 1) {
16778 // Extract 16-bit color components.
16779 uint32_t sa = 0x101 * ((uint32_t)s[3]);
16780 uint32_t sr = 0x101 * ((uint32_t)s[2]);
16781 uint32_t sg = 0x101 * ((uint32_t)s[1]);
16782 uint32_t sb = 0x101 * ((uint32_t)s[0]);
16783
16784 // Convert from 565 color to 16-bit color.
16785 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
16786 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
16787 uint32_t dr = (0x8421 * old_r5) >> 4;
16788 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
16789 uint32_t dg = (0x1041 * old_g6) >> 2;
16790 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
16791 uint32_t db = (0x8421 * old_b5) >> 4;
16792
16793 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16794 uint32_t ia = 0xFFFF - sa;
16795
16796 // Composite src (nonpremul) over dst (premul).
16797 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
16798 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
16799 db = ((sb * sa) + (db * ia)) / 0xFFFF;
16800
16801 // Convert from 16-bit color to 565 color and combine the components.
16802 uint32_t new_r5 = 0x1F & (dr >> 11);
16803 uint32_t new_g6 = 0x3F & (dg >> 10);
16804 uint32_t new_b5 = 0x1F & (db >> 11);
16805 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
16806 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
16807
16808 s += 1 * 4;
16809 d += 1 * 2;
16810 n -= 1;
16811 }
16812
16813 return len;
16814}
16815
16816static uint64_t //
16817wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src_over(
16818 uint8_t* dst_ptr,
16819 size_t dst_len,
16820 uint8_t* dst_palette_ptr,
16821 size_t dst_palette_len,
16822 const uint8_t* src_ptr,
16823 size_t src_len) {
16824 size_t dst_len2 = dst_len / 2;
16825 size_t src_len8 = src_len / 8;
16826 size_t len = (dst_len2 < src_len8) ? dst_len2 : src_len8;
16827 uint8_t* d = dst_ptr;
16828 const uint8_t* s = src_ptr;
16829 size_t n = len;
16830
16831 // TODO: unroll.
16832
16833 while (n >= 1) {
16834 // Extract 16-bit color components.
16835 uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6));
16836 uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4));
16837 uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2));
16838 uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0));
16839
16840 // Convert from 565 color to 16-bit color.
16841 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
16842 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
16843 uint32_t dr = (0x8421 * old_r5) >> 4;
16844 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
16845 uint32_t dg = (0x1041 * old_g6) >> 2;
16846 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
16847 uint32_t db = (0x8421 * old_b5) >> 4;
16848
16849 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16850 uint32_t ia = 0xFFFF - sa;
16851
16852 // Composite src (nonpremul) over dst (premul).
16853 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
16854 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
16855 db = ((sb * sa) + (db * ia)) / 0xFFFF;
16856
16857 // Convert from 16-bit color to 565 color and combine the components.
16858 uint32_t new_r5 = 0x1F & (dr >> 11);
16859 uint32_t new_g6 = 0x3F & (dg >> 10);
16860 uint32_t new_b5 = 0x1F & (db >> 11);
16861 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
16862 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
16863
16864 s += 1 * 8;
16865 d += 1 * 2;
16866 n -= 1;
16867 }
16868
16869 return len;
16870}
16871
16872static uint64_t //
16873wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src(uint8_t* dst_ptr,
16874 size_t dst_len,
16875 uint8_t* dst_palette_ptr,
16876 size_t dst_palette_len,
16877 const uint8_t* src_ptr,
16878 size_t src_len) {
16879 size_t dst_len2 = dst_len / 2;
16880 size_t src_len4 = src_len / 4;
16881 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
16882 uint8_t* d = dst_ptr;
16883 const uint8_t* s = src_ptr;
16884 size_t n = len;
16885
16886 // TODO: unroll.
16887
16888 while (n >= 1) {
16889 wuffs_base__poke_u16le__no_bounds_check(
16890 d + (0 * 2), wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
16891 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
16892
16893 s += 1 * 4;
16894 d += 1 * 2;
16895 n -= 1;
16896 }
16897
16898 return len;
16899}
16900
16901static uint64_t //
16902wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src_over(
16903 uint8_t* dst_ptr,
16904 size_t dst_len,
16905 uint8_t* dst_palette_ptr,
16906 size_t dst_palette_len,
16907 const uint8_t* src_ptr,
16908 size_t src_len) {
16909 size_t dst_len2 = dst_len / 2;
16910 size_t src_len4 = src_len / 4;
16911 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
16912 uint8_t* d = dst_ptr;
16913 const uint8_t* s = src_ptr;
16914 size_t n = len;
16915
16916 // TODO: unroll.
16917
16918 while (n >= 1) {
16919 // Extract 16-bit color components.
16920 uint32_t sa = 0x101 * ((uint32_t)s[3]);
16921 uint32_t sr = 0x101 * ((uint32_t)s[2]);
16922 uint32_t sg = 0x101 * ((uint32_t)s[1]);
16923 uint32_t sb = 0x101 * ((uint32_t)s[0]);
16924
16925 // Convert from 565 color to 16-bit color.
16926 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
16927 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
16928 uint32_t dr = (0x8421 * old_r5) >> 4;
16929 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
16930 uint32_t dg = (0x1041 * old_g6) >> 2;
16931 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
16932 uint32_t db = (0x8421 * old_b5) >> 4;
16933
16934 // Calculate the inverse of the src-alpha: how much of the dst to keep.
16935 uint32_t ia = 0xFFFF - sa;
16936
16937 // Composite src (premul) over dst (premul).
16938 dr = sr + ((dr * ia) / 0xFFFF);
16939 dg = sg + ((dg * ia) / 0xFFFF);
16940 db = sb + ((db * ia) / 0xFFFF);
16941
16942 // Convert from 16-bit color to 565 color and combine the components.
16943 uint32_t new_r5 = 0x1F & (dr >> 11);
16944 uint32_t new_g6 = 0x3F & (dg >> 10);
16945 uint32_t new_b5 = 0x1F & (db >> 11);
16946 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
16947 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
16948
16949 s += 1 * 4;
16950 d += 1 * 2;
16951 n -= 1;
16952 }
16953
16954 return len;
16955}
16956
16957static uint64_t //
16958wuffs_base__pixel_swizzler__bgr_565__rgb(uint8_t* dst_ptr,
16959 size_t dst_len,
16960 uint8_t* dst_palette_ptr,
16961 size_t dst_palette_len,
16962 const uint8_t* src_ptr,
16963 size_t src_len) {
16964 size_t dst_len2 = dst_len / 2;
16965 size_t src_len3 = src_len / 3;
16966 size_t len = (dst_len2 < src_len3) ? dst_len2 : src_len3;
16967 uint8_t* d = dst_ptr;
16968 const uint8_t* s = src_ptr;
16969 size_t n = len;
16970
16971 // TODO: unroll.
16972
16973 while (n >= 1) {
16974 uint32_t r5 = s[0] >> 3;
16975 uint32_t g6 = s[1] >> 2;
16976 uint32_t b5 = s[2] >> 3;
16977 uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0);
16978 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
16979
16980 s += 1 * 3;
16981 d += 1 * 2;
16982 n -= 1;
16983 }
16984
16985 return len;
16986}
16987
16988static uint64_t //
16989wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src(
16990 uint8_t* dst_ptr,
16991 size_t dst_len,
16992 uint8_t* dst_palette_ptr,
16993 size_t dst_palette_len,
16994 const uint8_t* src_ptr,
16995 size_t src_len) {
16996 size_t dst_len2 = dst_len / 2;
16997 size_t src_len4 = src_len / 4;
16998 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
16999 uint8_t* d = dst_ptr;
17000 const uint8_t* s = src_ptr;
17001 size_t n = len;
17002
17003 // TODO: unroll.
17004
17005 while (n >= 1) {
17006 wuffs_base__poke_u16le__no_bounds_check(
17007 d + (0 * 2),
17008 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
17009 wuffs_base__swap_u32_argb_abgr(
17010 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
17011 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))))));
17012
17013 s += 1 * 4;
17014 d += 1 * 2;
17015 n -= 1;
17016 }
17017
17018 return len;
17019}
17020
17021static uint64_t //
17022wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src_over(
17023 uint8_t* dst_ptr,
17024 size_t dst_len,
17025 uint8_t* dst_palette_ptr,
17026 size_t dst_palette_len,
17027 const uint8_t* src_ptr,
17028 size_t src_len) {
17029 size_t dst_len2 = dst_len / 2;
17030 size_t src_len4 = src_len / 4;
17031 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17032 uint8_t* d = dst_ptr;
17033 const uint8_t* s = src_ptr;
17034 size_t n = len;
17035
17036 // TODO: unroll.
17037
17038 while (n >= 1) {
17039 // Extract 16-bit color components.
17040 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17041 uint32_t sb = 0x101 * ((uint32_t)s[2]);
17042 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17043 uint32_t sr = 0x101 * ((uint32_t)s[0]);
17044
17045 // Convert from 565 color to 16-bit color.
17046 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
17047 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
17048 uint32_t dr = (0x8421 * old_r5) >> 4;
17049 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
17050 uint32_t dg = (0x1041 * old_g6) >> 2;
17051 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
17052 uint32_t db = (0x8421 * old_b5) >> 4;
17053
17054 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17055 uint32_t ia = 0xFFFF - sa;
17056
17057 // Composite src (nonpremul) over dst (premul).
17058 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17059 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17060 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17061
17062 // Convert from 16-bit color to 565 color and combine the components.
17063 uint32_t new_r5 = 0x1F & (dr >> 11);
17064 uint32_t new_g6 = 0x3F & (dg >> 10);
17065 uint32_t new_b5 = 0x1F & (db >> 11);
17066 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
17067 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
17068
17069 s += 1 * 4;
17070 d += 1 * 2;
17071 n -= 1;
17072 }
17073
17074 return len;
17075}
17076
17077static uint64_t //
17078wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src(uint8_t* dst_ptr,
17079 size_t dst_len,
17080 uint8_t* dst_palette_ptr,
17081 size_t dst_palette_len,
17082 const uint8_t* src_ptr,
17083 size_t src_len) {
17084 size_t dst_len2 = dst_len / 2;
17085 size_t src_len4 = src_len / 4;
17086 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17087 uint8_t* d = dst_ptr;
17088 const uint8_t* s = src_ptr;
17089 size_t n = len;
17090
17091 // TODO: unroll.
17092
17093 while (n >= 1) {
17094 wuffs_base__poke_u16le__no_bounds_check(
17095 d + (0 * 2),
17096 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
17097 wuffs_base__swap_u32_argb_abgr(
17098 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))));
17099
17100 s += 1 * 4;
17101 d += 1 * 2;
17102 n -= 1;
17103 }
17104
17105 return len;
17106}
17107
17108static uint64_t //
17109wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src_over(
17110 uint8_t* dst_ptr,
17111 size_t dst_len,
17112 uint8_t* dst_palette_ptr,
17113 size_t dst_palette_len,
17114 const uint8_t* src_ptr,
17115 size_t src_len) {
17116 size_t dst_len2 = dst_len / 2;
17117 size_t src_len4 = src_len / 4;
17118 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17119 uint8_t* d = dst_ptr;
17120 const uint8_t* s = src_ptr;
17121 size_t n = len;
17122
17123 // TODO: unroll.
17124
17125 while (n >= 1) {
17126 // Extract 16-bit color components.
17127 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17128 uint32_t sb = 0x101 * ((uint32_t)s[2]);
17129 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17130 uint32_t sr = 0x101 * ((uint32_t)s[0]);
17131
17132 // Convert from 565 color to 16-bit color.
17133 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
17134 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
17135 uint32_t dr = (0x8421 * old_r5) >> 4;
17136 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
17137 uint32_t dg = (0x1041 * old_g6) >> 2;
17138 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
17139 uint32_t db = (0x8421 * old_b5) >> 4;
17140
17141 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17142 uint32_t ia = 0xFFFF - sa;
17143
17144 // Composite src (premul) over dst (premul).
17145 dr = sr + ((dr * ia) / 0xFFFF);
17146 dg = sg + ((dg * ia) / 0xFFFF);
17147 db = sb + ((db * ia) / 0xFFFF);
17148
17149 // Convert from 16-bit color to 565 color and combine the components.
17150 uint32_t new_r5 = 0x1F & (dr >> 11);
17151 uint32_t new_g6 = 0x3F & (dg >> 10);
17152 uint32_t new_b5 = 0x1F & (db >> 11);
17153 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
17154 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
17155
17156 s += 1 * 4;
17157 d += 1 * 2;
17158 n -= 1;
17159 }
17160
17161 return len;
17162}
17163
17164static uint64_t //
17165wuffs_base__pixel_swizzler__bgr_565__y(uint8_t* dst_ptr,
17166 size_t dst_len,
17167 uint8_t* dst_palette_ptr,
17168 size_t dst_palette_len,
17169 const uint8_t* src_ptr,
17170 size_t src_len) {
17171 size_t dst_len2 = dst_len / 2;
17172 size_t len = (dst_len2 < src_len) ? dst_len2 : src_len;
17173 uint8_t* d = dst_ptr;
17174 const uint8_t* s = src_ptr;
17175 size_t n = len;
17176
17177 // TODO: unroll.
17178
17179 while (n >= 1) {
17180 uint32_t y5 = s[0] >> 3;
17181 uint32_t y6 = s[0] >> 2;
17182 uint32_t rgb_565 = (y5 << 11) | (y6 << 5) | (y5 << 0);
17183 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
17184
17185 s += 1 * 1;
17186 d += 1 * 2;
17187 n -= 1;
17188 }
17189
17190 return len;
17191}
17192
17193static uint64_t //
17194wuffs_base__pixel_swizzler__bgr_565__y_16be(uint8_t* dst_ptr,
17195 size_t dst_len,
17196 uint8_t* dst_palette_ptr,
17197 size_t dst_palette_len,
17198 const uint8_t* src_ptr,
17199 size_t src_len) {
17200 size_t dst_len2 = dst_len / 2;
17201 size_t src_len2 = src_len / 2;
17202 size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2;
17203 uint8_t* d = dst_ptr;
17204 const uint8_t* s = src_ptr;
17205 size_t n = len;
17206
17207 // TODO: unroll.
17208
17209 while (n >= 1) {
17210 uint32_t y5 = s[0] >> 3;
17211 uint32_t y6 = s[0] >> 2;
17212 uint32_t rgb_565 = (y5 << 11) | (y6 << 5) | (y5 << 0);
17213 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
17214
17215 s += 1 * 2;
17216 d += 1 * 2;
17217 n -= 1;
17218 }
17219
17220 return len;
17221}
17222
17223static uint64_t //
17224wuffs_base__pixel_swizzler__bgr_565__index__src(uint8_t* dst_ptr,
17225 size_t dst_len,
17226 uint8_t* dst_palette_ptr,
17227 size_t dst_palette_len,
17228 const uint8_t* src_ptr,
17229 size_t src_len) {
17230 if (dst_palette_len !=
17231 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
17232 return 0;
17233 }
17234 size_t dst_len2 = dst_len / 2;
17235 size_t len = (dst_len2 < src_len) ? dst_len2 : src_len;
17236 uint8_t* d = dst_ptr;
17237 const uint8_t* s = src_ptr;
17238 size_t n = len;
17239
17240 const size_t loop_unroll_count = 4;
17241
17242 while (n >= loop_unroll_count) {
17243 wuffs_base__poke_u16le__no_bounds_check(
17244 d + (0 * 2), wuffs_base__peek_u16le__no_bounds_check(
17245 dst_palette_ptr + ((size_t)s[0] * 4)));
17246 wuffs_base__poke_u16le__no_bounds_check(
17247 d + (1 * 2), wuffs_base__peek_u16le__no_bounds_check(
17248 dst_palette_ptr + ((size_t)s[1] * 4)));
17249 wuffs_base__poke_u16le__no_bounds_check(
17250 d + (2 * 2), wuffs_base__peek_u16le__no_bounds_check(
17251 dst_palette_ptr + ((size_t)s[2] * 4)));
17252 wuffs_base__poke_u16le__no_bounds_check(
17253 d + (3 * 2), wuffs_base__peek_u16le__no_bounds_check(
17254 dst_palette_ptr + ((size_t)s[3] * 4)));
17255
17256 s += loop_unroll_count * 1;
17257 d += loop_unroll_count * 2;
17258 n -= loop_unroll_count;
17259 }
17260
17261 while (n >= 1) {
17262 wuffs_base__poke_u16le__no_bounds_check(
17263 d + (0 * 2), wuffs_base__peek_u16le__no_bounds_check(
17264 dst_palette_ptr + ((size_t)s[0] * 4)));
17265
17266 s += 1 * 1;
17267 d += 1 * 2;
17268 n -= 1;
17269 }
17270
17271 return len;
17272}
17273
17274static uint64_t //
17275wuffs_base__pixel_swizzler__bgr_565__index_bgra_nonpremul__src_over(
17276 uint8_t* dst_ptr,
17277 size_t dst_len,
17278 uint8_t* dst_palette_ptr,
17279 size_t dst_palette_len,
17280 const uint8_t* src_ptr,
17281 size_t src_len) {
17282 if (dst_palette_len !=
17283 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
17284 return 0;
17285 }
17286 size_t dst_len2 = dst_len / 2;
17287 size_t len = (dst_len2 < src_len) ? dst_len2 : src_len;
17288 uint8_t* d = dst_ptr;
17289 const uint8_t* s = src_ptr;
17290 size_t n = len;
17291
17292 // TODO: unroll.
17293
17294 while (n >= 1) {
17295 uint32_t d0 = wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
17296 wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)));
17297 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
17298 ((size_t)s[0] * 4));
17299 wuffs_base__poke_u16le__no_bounds_check(
17300 d + (0 * 2),
17301 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
17302 wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0)));
17303
17304 s += 1 * 1;
17305 d += 1 * 2;
17306 n -= 1;
17307 }
17308
17309 return len;
17310}
17311
17312static uint64_t //
17313wuffs_base__pixel_swizzler__bgr_565__index_binary_alpha__src_over(
17314 uint8_t* dst_ptr,
17315 size_t dst_len,
17316 uint8_t* dst_palette_ptr,
17317 size_t dst_palette_len,
17318 const uint8_t* src_ptr,
17319 size_t src_len) {
17320 if (dst_palette_len !=
17321 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
17322 return 0;
17323 }
17324 size_t dst_len2 = dst_len / 2;
17325 size_t len = (dst_len2 < src_len) ? dst_len2 : src_len;
17326 uint8_t* d = dst_ptr;
17327 const uint8_t* s = src_ptr;
17328 size_t n = len;
17329
17330 // TODO: unroll.
17331
17332 while (n >= 1) {
17333 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
17334 ((size_t)s[0] * 4));
17335 if (s0) {
17336 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)s0);
17337 }
17338
17339 s += 1 * 1;
17340 d += 1 * 2;
17341 n -= 1;
17342 }
17343
17344 return len;
17345}
17346
17347// --------
17348
17349static uint64_t //
17350wuffs_base__pixel_swizzler__bgr__bgr_565(uint8_t* dst_ptr,
17351 size_t dst_len,
17352 uint8_t* dst_palette_ptr,
17353 size_t dst_palette_len,
17354 const uint8_t* src_ptr,
17355 size_t src_len) {
17356 size_t dst_len3 = dst_len / 3;
17357 size_t src_len2 = src_len / 2;
17358 size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2;
17359 uint8_t* d = dst_ptr;
17360 const uint8_t* s = src_ptr;
17361 size_t n = len;
17362
17363 // TODO: unroll.
17364
17365 while (n >= 1) {
17366 uint32_t s0 = wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
17367 wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2)));
17368 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
17369
17370 s += 1 * 2;
17371 d += 1 * 3;
17372 n -= 1;
17373 }
17374
17375 return len;
17376}
17377
17378static uint64_t //
17379wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src(uint8_t* dst_ptr,
17380 size_t dst_len,
17381 uint8_t* dst_palette_ptr,
17382 size_t dst_palette_len,
17383 const uint8_t* src_ptr,
17384 size_t src_len) {
17385 size_t dst_len3 = dst_len / 3;
17386 size_t src_len4 = src_len / 4;
17387 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
17388 uint8_t* d = dst_ptr;
17389 const uint8_t* s = src_ptr;
17390 size_t n = len;
17391
17392 // TODO: unroll.
17393
17394 while (n >= 1) {
17395 uint32_t s0 =
17396 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
17397 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
17398 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
17399
17400 s += 1 * 4;
17401 d += 1 * 3;
17402 n -= 1;
17403 }
17404
17405 return len;
17406}
17407
17408static uint64_t //
17409wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src(
17410 uint8_t* dst_ptr,
17411 size_t dst_len,
17412 uint8_t* dst_palette_ptr,
17413 size_t dst_palette_len,
17414 const uint8_t* src_ptr,
17415 size_t src_len) {
17416 size_t dst_len3 = dst_len / 3;
17417 size_t src_len8 = src_len / 8;
17418 size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8;
17419 uint8_t* d = dst_ptr;
17420 const uint8_t* s = src_ptr;
17421 size_t n = len;
17422
17423 // TODO: unroll.
17424
17425 while (n >= 1) {
17426 uint32_t s0 =
17427 wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
17428 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)));
17429 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
17430
17431 s += 1 * 8;
17432 d += 1 * 3;
17433 n -= 1;
17434 }
17435
17436 return len;
17437}
17438
17439static uint64_t //
17440wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src_over(
17441 uint8_t* dst_ptr,
17442 size_t dst_len,
17443 uint8_t* dst_palette_ptr,
17444 size_t dst_palette_len,
17445 const uint8_t* src_ptr,
17446 size_t src_len) {
17447 size_t dst_len3 = dst_len / 3;
17448 size_t src_len4 = src_len / 4;
17449 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
17450 uint8_t* d = dst_ptr;
17451 const uint8_t* s = src_ptr;
17452 size_t n = len;
17453
17454 // TODO: unroll.
17455
17456 while (n >= 1) {
17457 // Extract 16-bit color components.
17458 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17459 uint32_t sr = 0x101 * ((uint32_t)s[2]);
17460 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17461 uint32_t sb = 0x101 * ((uint32_t)s[0]);
17462 uint32_t dr = 0x101 * ((uint32_t)d[2]);
17463 uint32_t dg = 0x101 * ((uint32_t)d[1]);
17464 uint32_t db = 0x101 * ((uint32_t)d[0]);
17465
17466 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17467 uint32_t ia = 0xFFFF - sa;
17468
17469 // Composite src (nonpremul) over dst (premul).
17470 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17471 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17472 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17473
17474 // Convert from 16-bit color to 8-bit color.
17475 d[0] = (uint8_t)(db >> 8);
17476 d[1] = (uint8_t)(dg >> 8);
17477 d[2] = (uint8_t)(dr >> 8);
17478
17479 s += 1 * 4;
17480 d += 1 * 3;
17481 n -= 1;
17482 }
17483
17484 return len;
17485}
17486
17487static uint64_t //
17488wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src_over(
17489 uint8_t* dst_ptr,
17490 size_t dst_len,
17491 uint8_t* dst_palette_ptr,
17492 size_t dst_palette_len,
17493 const uint8_t* src_ptr,
17494 size_t src_len) {
17495 size_t dst_len3 = dst_len / 3;
17496 size_t src_len8 = src_len / 8;
17497 size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8;
17498 uint8_t* d = dst_ptr;
17499 const uint8_t* s = src_ptr;
17500 size_t n = len;
17501
17502 // TODO: unroll.
17503
17504 while (n >= 1) {
17505 // Extract 16-bit color components.
17506 uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6));
17507 uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4));
17508 uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2));
17509 uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0));
17510 uint32_t dr = 0x101 * ((uint32_t)d[2]);
17511 uint32_t dg = 0x101 * ((uint32_t)d[1]);
17512 uint32_t db = 0x101 * ((uint32_t)d[0]);
17513
17514 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17515 uint32_t ia = 0xFFFF - sa;
17516
17517 // Composite src (nonpremul) over dst (premul).
17518 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17519 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17520 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17521
17522 // Convert from 16-bit color to 8-bit color.
17523 d[0] = (uint8_t)(db >> 8);
17524 d[1] = (uint8_t)(dg >> 8);
17525 d[2] = (uint8_t)(dr >> 8);
17526
17527 s += 1 * 8;
17528 d += 1 * 3;
17529 n -= 1;
17530 }
17531
17532 return len;
17533}
17534
17535static uint64_t //
17536wuffs_base__pixel_swizzler__bgr__bgra_premul__src(uint8_t* dst_ptr,
17537 size_t dst_len,
17538 uint8_t* dst_palette_ptr,
17539 size_t dst_palette_len,
17540 const uint8_t* src_ptr,
17541 size_t src_len) {
17542 size_t dst_len3 = dst_len / 3;
17543 size_t src_len4 = src_len / 4;
17544 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
17545 uint8_t* d = dst_ptr;
17546 const uint8_t* s = src_ptr;
17547 size_t n = len;
17548
17549 while (n >= 1) {
17550 uint8_t s0 = s[0];
17551 uint8_t s1 = s[1];
17552 uint8_t s2 = s[2];
17553 d[0] = s0;
17554 d[1] = s1;
17555 d[2] = s2;
17556
17557 s += 1 * 4;
17558 d += 1 * 3;
17559 n -= 1;
17560 }
17561
17562 return len;
17563}
17564
17565static uint64_t //
17566wuffs_base__pixel_swizzler__bgr__bgra_premul__src_over(uint8_t* dst_ptr,
17567 size_t dst_len,
17568 uint8_t* dst_palette_ptr,
17569 size_t dst_palette_len,
17570 const uint8_t* src_ptr,
17571 size_t src_len) {
17572 size_t dst_len3 = dst_len / 3;
17573 size_t src_len4 = src_len / 4;
17574 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
17575 uint8_t* d = dst_ptr;
17576 const uint8_t* s = src_ptr;
17577 size_t n = len;
17578
17579 while (n >= 1) {
17580 // Extract 16-bit color components.
17581 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17582 uint32_t sr = 0x101 * ((uint32_t)s[2]);
17583 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17584 uint32_t sb = 0x101 * ((uint32_t)s[0]);
17585 uint32_t dr = 0x101 * ((uint32_t)d[2]);
17586 uint32_t dg = 0x101 * ((uint32_t)d[1]);
17587 uint32_t db = 0x101 * ((uint32_t)d[0]);
17588
17589 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17590 uint32_t ia = 0xFFFF - sa;
17591
17592 // Composite src (premul) over dst (premul).
17593 dr = sr + ((dr * ia) / 0xFFFF);
17594 dg = sg + ((dg * ia) / 0xFFFF);
17595 db = sb + ((db * ia) / 0xFFFF);
17596
17597 // Convert from 16-bit color to 8-bit color.
17598 d[0] = (uint8_t)(db >> 8);
17599 d[1] = (uint8_t)(dg >> 8);
17600 d[2] = (uint8_t)(dr >> 8);
17601
17602 s += 1 * 4;
17603 d += 1 * 3;
17604 n -= 1;
17605 }
17606
17607 return len;
17608}
17609
17610static uint64_t //
17611wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src(uint8_t* dst_ptr,
17612 size_t dst_len,
17613 uint8_t* dst_palette_ptr,
17614 size_t dst_palette_len,
17615 const uint8_t* src_ptr,
17616 size_t src_len) {
17617 size_t dst_len3 = dst_len / 3;
17618 size_t src_len4 = src_len / 4;
17619 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
17620 uint8_t* d = dst_ptr;
17621 const uint8_t* s = src_ptr;
17622 size_t n = len;
17623
17624 // TODO: unroll.
17625
17626 while (n >= 1) {
17627 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
17628 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
17629 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
17630 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
17631
17632 s += 1 * 4;
17633 d += 1 * 3;
17634 n -= 1;
17635 }
17636
17637 return len;
17638}
17639
17640static uint64_t //
17641wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src_over(
17642 uint8_t* dst_ptr,
17643 size_t dst_len,
17644 uint8_t* dst_palette_ptr,
17645 size_t dst_palette_len,
17646 const uint8_t* src_ptr,
17647 size_t src_len) {
17648 size_t dst_len3 = dst_len / 3;
17649 size_t src_len4 = src_len / 4;
17650 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
17651 uint8_t* d = dst_ptr;
17652 const uint8_t* s = src_ptr;
17653 size_t n = len;
17654
17655 // TODO: unroll.
17656
17657 while (n >= 1) {
17658 // Extract 16-bit color components.
17659 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17660 uint32_t sb = 0x101 * ((uint32_t)s[2]);
17661 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17662 uint32_t sr = 0x101 * ((uint32_t)s[0]);
17663 uint32_t dr = 0x101 * ((uint32_t)d[2]);
17664 uint32_t dg = 0x101 * ((uint32_t)d[1]);
17665 uint32_t db = 0x101 * ((uint32_t)d[0]);
17666
17667 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17668 uint32_t ia = 0xFFFF - sa;
17669
17670 // Composite src (nonpremul) over dst (premul).
17671 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17672 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17673 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17674
17675 // Convert from 16-bit color to 8-bit color.
17676 d[0] = (uint8_t)(db >> 8);
17677 d[1] = (uint8_t)(dg >> 8);
17678 d[2] = (uint8_t)(dr >> 8);
17679
17680 s += 1 * 4;
17681 d += 1 * 3;
17682 n -= 1;
17683 }
17684
17685 return len;
17686}
17687
17688static uint64_t //
17689wuffs_base__pixel_swizzler__bgr__rgba_premul__src(uint8_t* dst_ptr,
17690 size_t dst_len,
17691 uint8_t* dst_palette_ptr,
17692 size_t dst_palette_len,
17693 const uint8_t* src_ptr,
17694 size_t src_len) {
17695 size_t dst_len3 = dst_len / 3;
17696 size_t src_len4 = src_len / 4;
17697 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
17698 uint8_t* d = dst_ptr;
17699 const uint8_t* s = src_ptr;
17700 size_t n = len;
17701
17702 while (n >= 1) {
17703 uint8_t s0 = s[0];
17704 uint8_t s1 = s[1];
17705 uint8_t s2 = s[2];
17706 d[0] = s2;
17707 d[1] = s1;
17708 d[2] = s0;
17709
17710 s += 1 * 4;
17711 d += 1 * 3;
17712 n -= 1;
17713 }
17714
17715 return len;
17716}
17717
17718static uint64_t //
17719wuffs_base__pixel_swizzler__bgr__rgba_premul__src_over(uint8_t* dst_ptr,
17720 size_t dst_len,
17721 uint8_t* dst_palette_ptr,
17722 size_t dst_palette_len,
17723 const uint8_t* src_ptr,
17724 size_t src_len) {
17725 size_t dst_len3 = dst_len / 3;
17726 size_t src_len4 = src_len / 4;
17727 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
17728 uint8_t* d = dst_ptr;
17729 const uint8_t* s = src_ptr;
17730 size_t n = len;
17731
17732 while (n >= 1) {
17733 // Extract 16-bit color components.
17734 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17735 uint32_t sb = 0x101 * ((uint32_t)s[2]);
17736 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17737 uint32_t sr = 0x101 * ((uint32_t)s[0]);
17738 uint32_t dr = 0x101 * ((uint32_t)d[2]);
17739 uint32_t dg = 0x101 * ((uint32_t)d[1]);
17740 uint32_t db = 0x101 * ((uint32_t)d[0]);
17741
17742 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17743 uint32_t ia = 0xFFFF - sa;
17744
17745 // Composite src (premul) over dst (premul).
17746 dr = sr + ((dr * ia) / 0xFFFF);
17747 dg = sg + ((dg * ia) / 0xFFFF);
17748 db = sb + ((db * ia) / 0xFFFF);
17749
17750 // Convert from 16-bit color to 8-bit color.
17751 d[0] = (uint8_t)(db >> 8);
17752 d[1] = (uint8_t)(dg >> 8);
17753 d[2] = (uint8_t)(dr >> 8);
17754
17755 s += 1 * 4;
17756 d += 1 * 3;
17757 n -= 1;
17758 }
17759
17760 return len;
17761}
17762
17763// --------
17764
17765static uint64_t //
17766wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over(
17767 uint8_t* dst_ptr,
17768 size_t dst_len,
17769 uint8_t* dst_palette_ptr,
17770 size_t dst_palette_len,
17771 const uint8_t* src_ptr,
17772 size_t src_len) {
17773 size_t dst_len4 = dst_len / 4;
17774 size_t src_len4 = src_len / 4;
17775 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
17776 uint8_t* d = dst_ptr;
17777 const uint8_t* s = src_ptr;
17778 size_t n = len;
17779
17780 while (n >= 1) {
17781 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
17782 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
17783 wuffs_base__poke_u32le__no_bounds_check(
17784 d + (0 * 4),
17785 wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0));
17786
17787 s += 1 * 4;
17788 d += 1 * 4;
17789 n -= 1;
17790 }
17791
17792 return len;
17793}
17794
17795static uint64_t //
17796wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src(
17797 uint8_t* dst_ptr,
17798 size_t dst_len,
17799 uint8_t* dst_palette_ptr,
17800 size_t dst_palette_len,
17801 const uint8_t* src_ptr,
17802 size_t src_len) {
17803 size_t dst_len4 = dst_len / 4;
17804 size_t src_len8 = src_len / 8;
17805 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
17806 uint8_t* d = dst_ptr;
17807 const uint8_t* s = src_ptr;
17808
17809 size_t n = len;
17810 while (n >= 1) {
17811 wuffs_base__poke_u32le__no_bounds_check(
17812 d + (0 * 4), wuffs_base__color_u64__as__color_u32(
17813 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))));
17814
17815 s += 1 * 8;
17816 d += 1 * 4;
17817 n -= 1;
17818 }
17819 return len;
17820}
17821
17822static uint64_t //
17823wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src_over(
17824 uint8_t* dst_ptr,
17825 size_t dst_len,
17826 uint8_t* dst_palette_ptr,
17827 size_t dst_palette_len,
17828 const uint8_t* src_ptr,
17829 size_t src_len) {
17830 size_t dst_len4 = dst_len / 4;
17831 size_t src_len8 = src_len / 8;
17832 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
17833 uint8_t* d = dst_ptr;
17834 const uint8_t* s = src_ptr;
17835 size_t n = len;
17836
17837 while (n >= 1) {
17838 uint64_t d0 = wuffs_base__color_u32__as__color_u64(
17839 wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)));
17840 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
17841 wuffs_base__poke_u32le__no_bounds_check(
17842 d + (0 * 4),
17843 wuffs_base__color_u64__as__color_u32(
17844 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0)));
17845
17846 s += 1 * 8;
17847 d += 1 * 4;
17848 n -= 1;
17849 }
17850
17851 return len;
17852}
17853
17854static uint64_t //
17855wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src(
17856 uint8_t* dst_ptr,
17857 size_t dst_len,
17858 uint8_t* dst_palette_ptr,
17859 size_t dst_palette_len,
17860 const uint8_t* src_ptr,
17861 size_t src_len) {
17862 size_t dst_len4 = dst_len / 4;
17863 size_t src_len4 = src_len / 4;
17864 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
17865 uint8_t* d = dst_ptr;
17866 const uint8_t* s = src_ptr;
17867 size_t n = len;
17868
17869 while (n >= 1) {
17870 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
17871 wuffs_base__poke_u32le__no_bounds_check(
17872 d + (0 * 4),
17873 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(s0));
17874
17875 s += 1 * 4;
17876 d += 1 * 4;
17877 n -= 1;
17878 }
17879
17880 return len;
17881}
17882
17883static uint64_t //
17884wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over(
17885 uint8_t* dst_ptr,
17886 size_t dst_len,
17887 uint8_t* dst_palette_ptr,
17888 size_t dst_palette_len,
17889 const uint8_t* src_ptr,
17890 size_t src_len) {
17891 size_t dst_len4 = dst_len / 4;
17892 size_t src_len4 = src_len / 4;
17893 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
17894 uint8_t* d = dst_ptr;
17895 const uint8_t* s = src_ptr;
17896 size_t n = len;
17897
17898 while (n >= 1) {
17899 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
17900 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
17901 wuffs_base__poke_u32le__no_bounds_check(
17902 d + (0 * 4), wuffs_base__composite_nonpremul_premul_u32_axxx(d0, s0));
17903
17904 s += 1 * 4;
17905 d += 1 * 4;
17906 n -= 1;
17907 }
17908
17909 return len;
17910}
17911
17912static uint64_t //
17913wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over(
17914 uint8_t* dst_ptr,
17915 size_t dst_len,
17916 uint8_t* dst_palette_ptr,
17917 size_t dst_palette_len,
17918 const uint8_t* src_ptr,
17919 size_t src_len) {
17920 if (dst_palette_len !=
17921 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
17922 return 0;
17923 }
17924 size_t dst_len4 = dst_len / 4;
17925 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
17926 uint8_t* d = dst_ptr;
17927 const uint8_t* s = src_ptr;
17928 size_t n = len;
17929
17930 // TODO: unroll.
17931
17932 while (n >= 1) {
17933 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
17934 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
17935 ((size_t)s[0] * 4));
17936 wuffs_base__poke_u32le__no_bounds_check(
17937 d + (0 * 4),
17938 wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0));
17939
17940 s += 1 * 1;
17941 d += 1 * 4;
17942 n -= 1;
17943 }
17944
17945 return len;
17946}
17947
17948static uint64_t //
17949wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over(
17950 uint8_t* dst_ptr,
17951 size_t dst_len,
17952 uint8_t* dst_palette_ptr,
17953 size_t dst_palette_len,
17954 const uint8_t* src_ptr,
17955 size_t src_len) {
17956 size_t dst_len4 = dst_len / 4;
17957 size_t src_len4 = src_len / 4;
17958 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
17959 uint8_t* d = dst_ptr;
17960 const uint8_t* s = src_ptr;
17961 size_t n = len;
17962
17963 while (n >= 1) {
17964 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
17965 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
17966 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
17967 wuffs_base__poke_u32le__no_bounds_check(
17968 d + (0 * 4),
17969 wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0));
17970
17971 s += 1 * 4;
17972 d += 1 * 4;
17973 n -= 1;
17974 }
17975
17976 return len;
17977}
17978
17979static uint64_t //
17980wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src(
17981 uint8_t* dst_ptr,
17982 size_t dst_len,
17983 uint8_t* dst_palette_ptr,
17984 size_t dst_palette_len,
17985 const uint8_t* src_ptr,
17986 size_t src_len) {
17987 size_t dst_len4 = dst_len / 4;
17988 size_t src_len4 = src_len / 4;
17989 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
17990 uint8_t* d = dst_ptr;
17991 const uint8_t* s = src_ptr;
17992 size_t n = len;
17993
17994 while (n >= 1) {
17995 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
17996 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
17997 wuffs_base__poke_u32le__no_bounds_check(
17998 d + (0 * 4),
17999 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(s0));
18000
18001 s += 1 * 4;
18002 d += 1 * 4;
18003 n -= 1;
18004 }
18005
18006 return len;
18007}
18008
18009static uint64_t //
18010wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over(
18011 uint8_t* dst_ptr,
18012 size_t dst_len,
18013 uint8_t* dst_palette_ptr,
18014 size_t dst_palette_len,
18015 const uint8_t* src_ptr,
18016 size_t src_len) {
18017 size_t dst_len4 = dst_len / 4;
18018 size_t src_len4 = src_len / 4;
18019 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18020 uint8_t* d = dst_ptr;
18021 const uint8_t* s = src_ptr;
18022 size_t n = len;
18023
18024 while (n >= 1) {
18025 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18026 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
18027 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18028 wuffs_base__poke_u32le__no_bounds_check(
18029 d + (0 * 4), wuffs_base__composite_nonpremul_premul_u32_axxx(d0, s0));
18030
18031 s += 1 * 4;
18032 d += 1 * 4;
18033 n -= 1;
18034 }
18035
18036 return len;
18037}
18038
18039// --------
18040
18041static uint64_t //
18042wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src(
18043 uint8_t* dst_ptr,
18044 size_t dst_len,
18045 uint8_t* dst_palette_ptr,
18046 size_t dst_palette_len,
18047 const uint8_t* src_ptr,
18048 size_t src_len) {
18049 size_t dst_len8 = dst_len / 8;
18050 size_t src_len4 = src_len / 4;
18051 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18052 uint8_t* d = dst_ptr;
18053 const uint8_t* s = src_ptr;
18054
18055 size_t n = len;
18056 while (n >= 1) {
18057 uint8_t s0 = s[0];
18058 uint8_t s1 = s[1];
18059 uint8_t s2 = s[2];
18060 uint8_t s3 = s[3];
18061 d[0] = s0;
18062 d[1] = s0;
18063 d[2] = s1;
18064 d[3] = s1;
18065 d[4] = s2;
18066 d[5] = s2;
18067 d[6] = s3;
18068 d[7] = s3;
18069
18070 s += 1 * 4;
18071 d += 1 * 8;
18072 n -= 1;
18073 }
18074 return len;
18075}
18076
18077static uint64_t //
18078wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src_over(
18079 uint8_t* dst_ptr,
18080 size_t dst_len,
18081 uint8_t* dst_palette_ptr,
18082 size_t dst_palette_len,
18083 const uint8_t* src_ptr,
18084 size_t src_len) {
18085 size_t dst_len8 = dst_len / 8;
18086 size_t src_len4 = src_len / 4;
18087 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18088 uint8_t* d = dst_ptr;
18089 const uint8_t* s = src_ptr;
18090
18091 size_t n = len;
18092 while (n >= 1) {
18093 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
18094 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
18095 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18096 wuffs_base__poke_u64le__no_bounds_check(
18097 d + (0 * 8),
18098 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0));
18099
18100 s += 1 * 4;
18101 d += 1 * 8;
18102 n -= 1;
18103 }
18104 return len;
18105}
18106
18107static uint64_t //
18108wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul_4x16le__src_over(
18109 uint8_t* dst_ptr,
18110 size_t dst_len,
18111 uint8_t* dst_palette_ptr,
18112 size_t dst_palette_len,
18113 const uint8_t* src_ptr,
18114 size_t src_len) {
18115 size_t dst_len8 = dst_len / 8;
18116 size_t src_len8 = src_len / 8;
18117 size_t len = (dst_len8 < src_len8) ? dst_len8 : src_len8;
18118 uint8_t* d = dst_ptr;
18119 const uint8_t* s = src_ptr;
18120
18121 size_t n = len;
18122 while (n >= 1) {
18123 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
18124 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
18125 wuffs_base__poke_u64le__no_bounds_check(
18126 d + (0 * 8),
18127 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0));
18128
18129 s += 1 * 8;
18130 d += 1 * 8;
18131 n -= 1;
18132 }
18133 return len;
18134}
18135
18136static uint64_t //
18137wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src(
18138 uint8_t* dst_ptr,
18139 size_t dst_len,
18140 uint8_t* dst_palette_ptr,
18141 size_t dst_palette_len,
18142 const uint8_t* src_ptr,
18143 size_t src_len) {
18144 size_t dst_len8 = dst_len / 8;
18145 size_t src_len4 = src_len / 4;
18146 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18147 uint8_t* d = dst_ptr;
18148 const uint8_t* s = src_ptr;
18149
18150 size_t n = len;
18151 while (n >= 1) {
18152 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
18153 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
18154 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
18155 wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0);
18156
18157 s += 1 * 4;
18158 d += 1 * 8;
18159 n -= 1;
18160 }
18161 return len;
18162}
18163
18164static uint64_t //
18165wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src_over(
18166 uint8_t* dst_ptr,
18167 size_t dst_len,
18168 uint8_t* dst_palette_ptr,
18169 size_t dst_palette_len,
18170 const uint8_t* src_ptr,
18171 size_t src_len) {
18172 size_t dst_len8 = dst_len / 8;
18173 size_t src_len4 = src_len / 4;
18174 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18175 uint8_t* d = dst_ptr;
18176 const uint8_t* s = src_ptr;
18177
18178 size_t n = len;
18179 while (n >= 1) {
18180 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
18181 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
18182 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18183 wuffs_base__poke_u64le__no_bounds_check(
18184 d + (0 * 8), wuffs_base__composite_nonpremul_premul_u64_axxx(d0, s0));
18185
18186 s += 1 * 4;
18187 d += 1 * 8;
18188 n -= 1;
18189 }
18190 return len;
18191}
18192
18193static uint64_t //
18194wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__index_bgra_nonpremul__src_over(
18195 uint8_t* dst_ptr,
18196 size_t dst_len,
18197 uint8_t* dst_palette_ptr,
18198 size_t dst_palette_len,
18199 const uint8_t* src_ptr,
18200 size_t src_len) {
18201 if (dst_palette_len !=
18202 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
18203 return 0;
18204 }
18205 size_t dst_len8 = dst_len / 8;
18206 size_t len = (dst_len8 < src_len) ? dst_len8 : src_len;
18207 uint8_t* d = dst_ptr;
18208 const uint8_t* s = src_ptr;
18209 size_t n = len;
18210
18211 while (n >= 1) {
18212 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
18213 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
18214 wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
18215 ((size_t)s[0] * 4)));
18216 wuffs_base__poke_u64le__no_bounds_check(
18217 d + (0 * 8),
18218 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0));
18219
18220 s += 1 * 1;
18221 d += 1 * 8;
18222 n -= 1;
18223 }
18224
18225 return len;
18226}
18227
18228static uint64_t //
18229wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src(
18230 uint8_t* dst_ptr,
18231 size_t dst_len,
18232 uint8_t* dst_palette_ptr,
18233 size_t dst_palette_len,
18234 const uint8_t* src_ptr,
18235 size_t src_len) {
18236 size_t dst_len8 = dst_len / 8;
18237 size_t src_len4 = src_len / 4;
18238 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18239 uint8_t* d = dst_ptr;
18240 const uint8_t* s = src_ptr;
18241
18242 size_t n = len;
18243 while (n >= 1) {
18244 uint8_t s0 = s[0];
18245 uint8_t s1 = s[1];
18246 uint8_t s2 = s[2];
18247 uint8_t s3 = s[3];
18248 d[0] = s2;
18249 d[1] = s2;
18250 d[2] = s1;
18251 d[3] = s1;
18252 d[4] = s0;
18253 d[5] = s0;
18254 d[6] = s3;
18255 d[7] = s3;
18256
18257 s += 1 * 4;
18258 d += 1 * 8;
18259 n -= 1;
18260 }
18261 return len;
18262}
18263
18264static uint64_t //
18265wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src_over(
18266 uint8_t* dst_ptr,
18267 size_t dst_len,
18268 uint8_t* dst_palette_ptr,
18269 size_t dst_palette_len,
18270 const uint8_t* src_ptr,
18271 size_t src_len) {
18272 size_t dst_len8 = dst_len / 8;
18273 size_t src_len4 = src_len / 4;
18274 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18275 uint8_t* d = dst_ptr;
18276 const uint8_t* s = src_ptr;
18277
18278 size_t n = len;
18279 while (n >= 1) {
18280 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
18281 uint64_t s0 =
18282 wuffs_base__color_u32__as__color_u64(wuffs_base__swap_u32_argb_abgr(
18283 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
18284 wuffs_base__poke_u64le__no_bounds_check(
18285 d + (0 * 8),
18286 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0));
18287
18288 s += 1 * 4;
18289 d += 1 * 8;
18290 n -= 1;
18291 }
18292 return len;
18293}
18294
18295static uint64_t //
18296wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src(
18297 uint8_t* dst_ptr,
18298 size_t dst_len,
18299 uint8_t* dst_palette_ptr,
18300 size_t dst_palette_len,
18301 const uint8_t* src_ptr,
18302 size_t src_len) {
18303 size_t dst_len8 = dst_len / 8;
18304 size_t src_len4 = src_len / 4;
18305 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18306 uint8_t* d = dst_ptr;
18307 const uint8_t* s = src_ptr;
18308
18309 size_t n = len;
18310 while (n >= 1) {
18311 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
18312 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
18313 wuffs_base__swap_u32_argb_abgr(
18314 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))));
18315 wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0);
18316
18317 s += 1 * 4;
18318 d += 1 * 8;
18319 n -= 1;
18320 }
18321 return len;
18322}
18323
18324static uint64_t //
18325wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src_over(
18326 uint8_t* dst_ptr,
18327 size_t dst_len,
18328 uint8_t* dst_palette_ptr,
18329 size_t dst_palette_len,
18330 const uint8_t* src_ptr,
18331 size_t src_len) {
18332 size_t dst_len8 = dst_len / 8;
18333 size_t src_len4 = src_len / 4;
18334 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18335 uint8_t* d = dst_ptr;
18336 const uint8_t* s = src_ptr;
18337
18338 size_t n = len;
18339 while (n >= 1) {
18340 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
18341 uint64_t s0 =
18342 wuffs_base__color_u32__as__color_u64(wuffs_base__swap_u32_argb_abgr(
18343 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
18344 wuffs_base__poke_u64le__no_bounds_check(
18345 d + (0 * 8), wuffs_base__composite_nonpremul_premul_u64_axxx(d0, s0));
18346
18347 s += 1 * 4;
18348 d += 1 * 8;
18349 n -= 1;
18350 }
18351 return len;
18352}
18353
18354// --------
18355
18356static uint64_t //
18357wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src(
18358 uint8_t* dst_ptr,
18359 size_t dst_len,
18360 uint8_t* dst_palette_ptr,
18361 size_t dst_palette_len,
18362 const uint8_t* src_ptr,
18363 size_t src_len) {
18364 size_t dst_len4 = dst_len / 4;
18365 size_t src_len4 = src_len / 4;
18366 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18367 uint8_t* d = dst_ptr;
18368 const uint8_t* s = src_ptr;
18369 size_t n = len;
18370
18371 // TODO: unroll.
18372
18373 while (n >= 1) {
18374 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
18375 wuffs_base__poke_u32le__no_bounds_check(
18376 d + (0 * 4),
18377 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0));
18378
18379 s += 1 * 4;
18380 d += 1 * 4;
18381 n -= 1;
18382 }
18383
18384 return len;
18385}
18386
18387static uint64_t //
18388wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src(
18389 uint8_t* dst_ptr,
18390 size_t dst_len,
18391 uint8_t* dst_palette_ptr,
18392 size_t dst_palette_len,
18393 const uint8_t* src_ptr,
18394 size_t src_len) {
18395 size_t dst_len4 = dst_len / 4;
18396 size_t src_len8 = src_len / 8;
18397 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
18398 uint8_t* d = dst_ptr;
18399 const uint8_t* s = src_ptr;
18400 size_t n = len;
18401
18402 // TODO: unroll.
18403
18404 while (n >= 1) {
18405 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
18406 wuffs_base__poke_u32le__no_bounds_check(
18407 d + (0 * 4),
18408 wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(s0));
18409
18410 s += 1 * 8;
18411 d += 1 * 4;
18412 n -= 1;
18413 }
18414
18415 return len;
18416}
18417
18418static uint64_t //
18419wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over(
18420 uint8_t* dst_ptr,
18421 size_t dst_len,
18422 uint8_t* dst_palette_ptr,
18423 size_t dst_palette_len,
18424 const uint8_t* src_ptr,
18425 size_t src_len) {
18426 size_t dst_len4 = dst_len / 4;
18427 size_t src_len4 = src_len / 4;
18428 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18429 uint8_t* d = dst_ptr;
18430 const uint8_t* s = src_ptr;
18431 size_t n = len;
18432
18433 // TODO: unroll.
18434
18435 while (n >= 1) {
18436 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18437 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
18438 wuffs_base__poke_u32le__no_bounds_check(
18439 d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0));
18440
18441 s += 1 * 4;
18442 d += 1 * 4;
18443 n -= 1;
18444 }
18445
18446 return len;
18447}
18448
18449static uint64_t //
18450wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src_over(
18451 uint8_t* dst_ptr,
18452 size_t dst_len,
18453 uint8_t* dst_palette_ptr,
18454 size_t dst_palette_len,
18455 const uint8_t* src_ptr,
18456 size_t src_len) {
18457 size_t dst_len4 = dst_len / 4;
18458 size_t src_len8 = src_len / 8;
18459 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
18460 uint8_t* d = dst_ptr;
18461 const uint8_t* s = src_ptr;
18462 size_t n = len;
18463
18464 // TODO: unroll.
18465
18466 while (n >= 1) {
18467 uint64_t d0 = wuffs_base__color_u32__as__color_u64(
18468 wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)));
18469 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
18470 wuffs_base__poke_u32le__no_bounds_check(
18471 d + (0 * 4),
18472 wuffs_base__color_u64__as__color_u32(
18473 wuffs_base__composite_premul_nonpremul_u64_axxx(d0, s0)));
18474
18475 s += 1 * 8;
18476 d += 1 * 4;
18477 n -= 1;
18478 }
18479
18480 return len;
18481}
18482
18483static uint64_t //
18484wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over(
18485 uint8_t* dst_ptr,
18486 size_t dst_len,
18487 uint8_t* dst_palette_ptr,
18488 size_t dst_palette_len,
18489 const uint8_t* src_ptr,
18490 size_t src_len) {
18491 size_t dst_len4 = dst_len / 4;
18492 size_t src_len4 = src_len / 4;
18493 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18494 uint8_t* d = dst_ptr;
18495 const uint8_t* s = src_ptr;
18496 size_t n = len;
18497
18498 // TODO: unroll.
18499
18500 while (n >= 1) {
18501 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18502 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
18503 wuffs_base__poke_u32le__no_bounds_check(
18504 d + (0 * 4), wuffs_base__composite_premul_premul_u32_axxx(d0, s0));
18505
18506 s += 1 * 4;
18507 d += 1 * 4;
18508 n -= 1;
18509 }
18510
18511 return len;
18512}
18513
18514static uint64_t //
18515wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over(
18516 uint8_t* dst_ptr,
18517 size_t dst_len,
18518 uint8_t* dst_palette_ptr,
18519 size_t dst_palette_len,
18520 const uint8_t* src_ptr,
18521 size_t src_len) {
18522 if (dst_palette_len !=
18523 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
18524 return 0;
18525 }
18526 size_t dst_len4 = dst_len / 4;
18527 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
18528 uint8_t* d = dst_ptr;
18529 const uint8_t* s = src_ptr;
18530 size_t n = len;
18531
18532 // TODO: unroll.
18533
18534 while (n >= 1) {
18535 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18536 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
18537 ((size_t)s[0] * 4));
18538 wuffs_base__poke_u32le__no_bounds_check(
18539 d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0));
18540
18541 s += 1 * 1;
18542 d += 1 * 4;
18543 n -= 1;
18544 }
18545
18546 return len;
18547}
18548
18549static uint64_t //
18550wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src(
18551 uint8_t* dst_ptr,
18552 size_t dst_len,
18553 uint8_t* dst_palette_ptr,
18554 size_t dst_palette_len,
18555 const uint8_t* src_ptr,
18556 size_t src_len) {
18557 size_t dst_len4 = dst_len / 4;
18558 size_t src_len4 = src_len / 4;
18559 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18560 uint8_t* d = dst_ptr;
18561 const uint8_t* s = src_ptr;
18562 size_t n = len;
18563
18564 // TODO: unroll.
18565
18566 while (n >= 1) {
18567 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
18568 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18569 wuffs_base__poke_u32le__no_bounds_check(
18570 d + (0 * 4),
18571 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0));
18572
18573 s += 1 * 4;
18574 d += 1 * 4;
18575 n -= 1;
18576 }
18577
18578 return len;
18579}
18580
18581static uint64_t //
18582wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over(
18583 uint8_t* dst_ptr,
18584 size_t dst_len,
18585 uint8_t* dst_palette_ptr,
18586 size_t dst_palette_len,
18587 const uint8_t* src_ptr,
18588 size_t src_len) {
18589 size_t dst_len4 = dst_len / 4;
18590 size_t src_len4 = src_len / 4;
18591 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18592 uint8_t* d = dst_ptr;
18593 const uint8_t* s = src_ptr;
18594 size_t n = len;
18595
18596 // TODO: unroll.
18597
18598 while (n >= 1) {
18599 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18600 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
18601 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18602 wuffs_base__poke_u32le__no_bounds_check(
18603 d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0));
18604
18605 s += 1 * 4;
18606 d += 1 * 4;
18607 n -= 1;
18608 }
18609
18610 return len;
18611}
18612
18613static uint64_t //
18614wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src(
18615 uint8_t* dst_ptr,
18616 size_t dst_len,
18617 uint8_t* dst_palette_ptr,
18618 size_t dst_palette_len,
18619 const uint8_t* src_ptr,
18620 size_t src_len) {
18621 size_t dst_len4 = dst_len / 4;
18622 size_t src_len8 = src_len / 8;
18623 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
18624 uint8_t* d = dst_ptr;
18625 const uint8_t* s = src_ptr;
18626 size_t n = len;
18627
18628 // TODO: unroll.
18629
18630 while (n >= 1) {
18631 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
18632 wuffs_base__poke_u32le__no_bounds_check(
18633 d + (0 * 4),
18634 wuffs_base__swap_u32_argb_abgr(
18635 wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
18636 s0)));
18637
18638 s += 1 * 8;
18639 d += 1 * 4;
18640 n -= 1;
18641 }
18642
18643 return len;
18644}
18645
18646static uint64_t //
18647wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src_over(
18648 uint8_t* dst_ptr,
18649 size_t dst_len,
18650 uint8_t* dst_palette_ptr,
18651 size_t dst_palette_len,
18652 const uint8_t* src_ptr,
18653 size_t src_len) {
18654 size_t dst_len4 = dst_len / 4;
18655 size_t src_len8 = src_len / 8;
18656 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
18657 uint8_t* d = dst_ptr;
18658 const uint8_t* s = src_ptr;
18659 size_t n = len;
18660
18661 // TODO: unroll.
18662
18663 while (n >= 1) {
18664 uint64_t d0 = wuffs_base__color_u32__as__color_u64(
18665 wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)));
18666 uint64_t s0 = wuffs_base__swap_u64_argb_abgr(
18667 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)));
18668 wuffs_base__poke_u32le__no_bounds_check(
18669 d + (0 * 4),
18670 wuffs_base__color_u64__as__color_u32(
18671 wuffs_base__composite_premul_nonpremul_u64_axxx(d0, s0)));
18672
18673 s += 1 * 8;
18674 d += 1 * 4;
18675 n -= 1;
18676 }
18677
18678 return len;
18679}
18680
18681static uint64_t //
18682wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over(
18683 uint8_t* dst_ptr,
18684 size_t dst_len,
18685 uint8_t* dst_palette_ptr,
18686 size_t dst_palette_len,
18687 const uint8_t* src_ptr,
18688 size_t src_len) {
18689 size_t dst_len4 = dst_len / 4;
18690 size_t src_len4 = src_len / 4;
18691 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18692 uint8_t* d = dst_ptr;
18693 const uint8_t* s = src_ptr;
18694 size_t n = len;
18695
18696 while (n >= 1) {
18697 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18698 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
18699 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18700 wuffs_base__poke_u32le__no_bounds_check(
18701 d + (0 * 4), wuffs_base__composite_premul_premul_u32_axxx(d0, s0));
18702
18703 s += 1 * 4;
18704 d += 1 * 4;
18705 n -= 1;
18706 }
18707
18708 return len;
18709}
18710
18711// --------
18712
18713static uint64_t //
18714wuffs_base__pixel_swizzler__bgrw__bgr(uint8_t* dst_ptr,
18715 size_t dst_len,
18716 uint8_t* dst_palette_ptr,
18717 size_t dst_palette_len,
18718 const uint8_t* src_ptr,
18719 size_t src_len) {
18720 size_t dst_len4 = dst_len / 4;
18721 size_t src_len3 = src_len / 3;
18722 size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3;
18723 uint8_t* d = dst_ptr;
18724 const uint8_t* s = src_ptr;
18725 size_t n = len;
18726
18727 // TODO: unroll.
18728
18729 while (n >= 1) {
18730 wuffs_base__poke_u32le__no_bounds_check(
18731 d + (0 * 4),
18732 0xFF000000 | wuffs_base__peek_u24le__no_bounds_check(s + (0 * 3)));
18733
18734 s += 1 * 3;
18735 d += 1 * 4;
18736 n -= 1;
18737 }
18738
18739 return len;
18740}
18741
18742static uint64_t //
18743wuffs_base__pixel_swizzler__bgrw__bgr_565(uint8_t* dst_ptr,
18744 size_t dst_len,
18745 uint8_t* dst_palette_ptr,
18746 size_t dst_palette_len,
18747 const uint8_t* src_ptr,
18748 size_t src_len) {
18749 size_t dst_len4 = dst_len / 4;
18750 size_t src_len2 = src_len / 2;
18751 size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2;
18752 uint8_t* d = dst_ptr;
18753 const uint8_t* s = src_ptr;
18754 size_t n = len;
18755
18756 // TODO: unroll.
18757
18758 while (n >= 1) {
18759 wuffs_base__poke_u32le__no_bounds_check(
18760 d + (0 * 4), wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
18761 wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))));
18762
18763 s += 1 * 2;
18764 d += 1 * 4;
18765 n -= 1;
18766 }
18767
18768 return len;
18769}
18770
18771static uint64_t //
18772wuffs_base__pixel_swizzler__bgrw__bgrx(uint8_t* dst_ptr,
18773 size_t dst_len,
18774 uint8_t* dst_palette_ptr,
18775 size_t dst_palette_len,
18776 const uint8_t* src_ptr,
18777 size_t src_len) {
18778 size_t dst_len4 = dst_len / 4;
18779 size_t src_len4 = src_len / 4;
18780 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18781 uint8_t* d = dst_ptr;
18782 const uint8_t* s = src_ptr;
18783 size_t n = len;
18784
18785 // TODO: unroll.
18786
18787 while (n >= 1) {
18788 wuffs_base__poke_u32le__no_bounds_check(
18789 d + (0 * 4),
18790 0xFF000000 | wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18791
18792 s += 1 * 4;
18793 d += 1 * 4;
18794 n -= 1;
18795 }
18796
18797 return len;
18798}
18799
18800// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
Nigel Tao7804ffe2021-10-07 21:58:26 +110018801#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100018802WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
18803static uint64_t //
18804wuffs_base__pixel_swizzler__bgrw__rgb__sse42(uint8_t* dst_ptr,
18805 size_t dst_len,
18806 uint8_t* dst_palette_ptr,
18807 size_t dst_palette_len,
18808 const uint8_t* src_ptr,
18809 size_t src_len) {
18810 size_t dst_len4 = dst_len / 4;
18811 size_t src_len3 = src_len / 3;
18812 size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3;
18813 uint8_t* d = dst_ptr;
18814 const uint8_t* s = src_ptr;
18815 size_t n = len;
18816
18817 __m128i shuffle = _mm_set_epi8(+0x00, +0x09, +0x0A, +0x0B, //
18818 +0x00, +0x06, +0x07, +0x08, //
18819 +0x00, +0x03, +0x04, +0x05, //
18820 +0x00, +0x00, +0x01, +0x02);
18821 __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, //
18822 -0x01, +0x00, +0x00, +0x00, //
18823 -0x01, +0x00, +0x00, +0x00, //
18824 -0x01, +0x00, +0x00, +0x00);
18825
18826 while (n >= 6) {
18827 __m128i x;
18828 x = _mm_lddqu_si128((const __m128i*)(const void*)s);
18829 x = _mm_shuffle_epi8(x, shuffle);
18830 x = _mm_or_si128(x, or_ff);
18831 _mm_storeu_si128((__m128i*)(void*)d, x);
18832
18833 s += 4 * 3;
18834 d += 4 * 4;
18835 n -= 4;
18836 }
18837
18838 while (n >= 1) {
18839 uint8_t b0 = s[0];
18840 uint8_t b1 = s[1];
18841 uint8_t b2 = s[2];
18842 d[0] = b2;
18843 d[1] = b1;
18844 d[2] = b0;
18845 d[3] = 0xFF;
18846
18847 s += 1 * 3;
18848 d += 1 * 4;
18849 n -= 1;
18850 }
18851
18852 return len;
18853}
Nigel Tao7804ffe2021-10-07 21:58:26 +110018854#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100018855// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
18856
18857static uint64_t //
18858wuffs_base__pixel_swizzler__bgrw__rgb(uint8_t* dst_ptr,
18859 size_t dst_len,
18860 uint8_t* dst_palette_ptr,
18861 size_t dst_palette_len,
18862 const uint8_t* src_ptr,
18863 size_t src_len) {
18864 size_t dst_len4 = dst_len / 4;
18865 size_t src_len3 = src_len / 3;
18866 size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3;
18867 uint8_t* d = dst_ptr;
18868 const uint8_t* s = src_ptr;
18869 size_t n = len;
18870
18871 while (n >= 1) {
18872 uint8_t b0 = s[0];
18873 uint8_t b1 = s[1];
18874 uint8_t b2 = s[2];
18875 d[0] = b2;
18876 d[1] = b1;
18877 d[2] = b0;
18878 d[3] = 0xFF;
18879
18880 s += 1 * 3;
18881 d += 1 * 4;
18882 n -= 1;
18883 }
18884
18885 return len;
18886}
18887
18888static uint64_t //
18889wuffs_base__pixel_swizzler__bgrw__rgbx(uint8_t* dst_ptr,
18890 size_t dst_len,
18891 uint8_t* dst_palette_ptr,
18892 size_t dst_palette_len,
18893 const uint8_t* src_ptr,
18894 size_t src_len) {
18895 size_t dst_len4 = dst_len / 4;
18896 size_t src_len4 = src_len / 4;
18897 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18898 uint8_t* d = dst_ptr;
18899 const uint8_t* s = src_ptr;
18900 size_t n = len;
18901
18902 // TODO: unroll.
18903
18904 while (n >= 1) {
18905 uint8_t b0 = s[0];
18906 uint8_t b1 = s[1];
18907 uint8_t b2 = s[2];
18908 d[0] = b2;
18909 d[1] = b1;
18910 d[2] = b0;
18911 d[3] = 0xFF;
18912
18913 s += 1 * 4;
18914 d += 1 * 4;
18915 n -= 1;
18916 }
18917
18918 return len;
18919}
18920
18921// --------
18922
18923static uint64_t //
18924wuffs_base__pixel_swizzler__bgrw_4x16le__bgr(uint8_t* dst_ptr,
18925 size_t dst_len,
18926 uint8_t* dst_palette_ptr,
18927 size_t dst_palette_len,
18928 const uint8_t* src_ptr,
18929 size_t src_len) {
18930 size_t dst_len8 = dst_len / 8;
18931 size_t src_len3 = src_len / 3;
18932 size_t len = (dst_len8 < src_len3) ? dst_len8 : src_len3;
18933 uint8_t* d = dst_ptr;
18934 const uint8_t* s = src_ptr;
18935 size_t n = len;
18936
18937 while (n >= 1) {
18938 uint8_t s0 = s[0];
18939 uint8_t s1 = s[1];
18940 uint8_t s2 = s[2];
18941 d[0] = s0;
18942 d[1] = s0;
18943 d[2] = s1;
18944 d[3] = s1;
18945 d[4] = s2;
18946 d[5] = s2;
18947 d[6] = 0xFF;
18948 d[7] = 0xFF;
18949
18950 s += 1 * 3;
18951 d += 1 * 8;
18952 n -= 1;
18953 }
18954
18955 return len;
18956}
18957
18958static uint64_t //
18959wuffs_base__pixel_swizzler__bgrw_4x16le__bgr_565(uint8_t* dst_ptr,
18960 size_t dst_len,
18961 uint8_t* dst_palette_ptr,
18962 size_t dst_palette_len,
18963 const uint8_t* src_ptr,
18964 size_t src_len) {
18965 size_t dst_len8 = dst_len / 8;
18966 size_t src_len2 = src_len / 2;
18967 size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2;
18968 uint8_t* d = dst_ptr;
18969 const uint8_t* s = src_ptr;
18970 size_t n = len;
18971
18972 while (n >= 1) {
18973 wuffs_base__poke_u64le__no_bounds_check(
18974 d + (0 * 8),
18975 wuffs_base__color_u32__as__color_u64(
18976 wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
18977 wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2)))));
18978
18979 s += 1 * 2;
18980 d += 1 * 8;
18981 n -= 1;
18982 }
18983
18984 return len;
18985}
18986
18987static uint64_t //
18988wuffs_base__pixel_swizzler__bgrw_4x16le__bgrx(uint8_t* dst_ptr,
18989 size_t dst_len,
18990 uint8_t* dst_palette_ptr,
18991 size_t dst_palette_len,
18992 const uint8_t* src_ptr,
18993 size_t src_len) {
18994 size_t dst_len8 = dst_len / 8;
18995 size_t src_len4 = src_len / 4;
18996 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18997 uint8_t* d = dst_ptr;
18998 const uint8_t* s = src_ptr;
18999 size_t n = len;
19000
19001 while (n >= 1) {
19002 uint8_t s0 = s[0];
19003 uint8_t s1 = s[1];
19004 uint8_t s2 = s[2];
19005 d[0] = s0;
19006 d[1] = s0;
19007 d[2] = s1;
19008 d[3] = s1;
19009 d[4] = s2;
19010 d[5] = s2;
19011 d[6] = 0xFF;
19012 d[7] = 0xFF;
19013
19014 s += 1 * 4;
19015 d += 1 * 8;
19016 n -= 1;
19017 }
19018
19019 return len;
19020}
19021
19022static uint64_t //
19023wuffs_base__pixel_swizzler__bgrw_4x16le__rgb(uint8_t* dst_ptr,
19024 size_t dst_len,
19025 uint8_t* dst_palette_ptr,
19026 size_t dst_palette_len,
19027 const uint8_t* src_ptr,
19028 size_t src_len) {
19029 size_t dst_len8 = dst_len / 8;
19030 size_t src_len3 = src_len / 3;
19031 size_t len = (dst_len8 < src_len3) ? dst_len8 : src_len3;
19032 uint8_t* d = dst_ptr;
19033 const uint8_t* s = src_ptr;
19034 size_t n = len;
19035
19036 while (n >= 1) {
19037 uint8_t s0 = s[0];
19038 uint8_t s1 = s[1];
19039 uint8_t s2 = s[2];
19040 d[0] = s2;
19041 d[1] = s2;
19042 d[2] = s1;
19043 d[3] = s1;
19044 d[4] = s0;
19045 d[5] = s0;
19046 d[6] = 0xFF;
19047 d[7] = 0xFF;
19048
19049 s += 1 * 3;
19050 d += 1 * 8;
19051 n -= 1;
19052 }
19053
19054 return len;
19055}
19056
19057// --------
19058
19059static uint64_t //
19060wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src(
19061 uint8_t* dst_ptr,
19062 size_t dst_len,
19063 uint8_t* dst_palette_ptr,
19064 size_t dst_palette_len,
19065 const uint8_t* src_ptr,
19066 size_t src_len) {
19067 size_t dst_len4 = dst_len / 4;
19068 size_t src_len8 = src_len / 8;
19069 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
19070 uint8_t* d = dst_ptr;
19071 const uint8_t* s = src_ptr;
19072
19073 size_t n = len;
19074 while (n >= 1) {
19075 wuffs_base__poke_u32le__no_bounds_check(
19076 d + (0 * 4), wuffs_base__color_u64__as__color_u32__swap_u32_argb_abgr(
19077 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))));
19078
19079 s += 1 * 8;
19080 d += 1 * 4;
19081 n -= 1;
19082 }
19083 return len;
19084}
19085
19086static uint64_t //
19087wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src_over(
19088 uint8_t* dst_ptr,
19089 size_t dst_len,
19090 uint8_t* dst_palette_ptr,
19091 size_t dst_palette_len,
19092 const uint8_t* src_ptr,
19093 size_t src_len) {
19094 size_t dst_len4 = dst_len / 4;
19095 size_t src_len8 = src_len / 8;
19096 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
19097 uint8_t* d = dst_ptr;
19098 const uint8_t* s = src_ptr;
19099 size_t n = len;
19100
19101 while (n >= 1) {
19102 uint64_t d0 = wuffs_base__color_u32__as__color_u64(
19103 wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)));
19104 uint64_t s0 = wuffs_base__swap_u64_argb_abgr(
19105 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)));
19106 wuffs_base__poke_u32le__no_bounds_check(
19107 d + (0 * 4),
19108 wuffs_base__color_u64__as__color_u32(
19109 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0)));
19110
19111 s += 1 * 8;
19112 d += 1 * 4;
19113 n -= 1;
19114 }
19115
19116 return len;
19117}
19118
19119// --------
19120
19121static uint64_t //
19122wuffs_base__pixel_swizzler__rgbw__bgr_565(uint8_t* dst_ptr,
19123 size_t dst_len,
19124 uint8_t* dst_palette_ptr,
19125 size_t dst_palette_len,
19126 const uint8_t* src_ptr,
19127 size_t src_len) {
19128 size_t dst_len4 = dst_len / 4;
19129 size_t src_len2 = src_len / 2;
19130 size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2;
19131 uint8_t* d = dst_ptr;
19132 const uint8_t* s = src_ptr;
19133 size_t n = len;
19134
19135 // TODO: unroll.
19136
19137 while (n >= 1) {
19138 wuffs_base__poke_u32le__no_bounds_check(
19139 d + (0 * 4),
19140 wuffs_base__swap_u32_argb_abgr(
19141 wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
19142 wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2)))));
19143
19144 s += 1 * 2;
19145 d += 1 * 4;
19146 n -= 1;
19147 }
19148
19149 return len;
19150}
19151
19152// --------
19153
19154static uint64_t //
19155wuffs_base__pixel_swizzler__xxx__index__src(uint8_t* dst_ptr,
19156 size_t dst_len,
19157 uint8_t* dst_palette_ptr,
19158 size_t dst_palette_len,
19159 const uint8_t* src_ptr,
19160 size_t src_len) {
19161 if (dst_palette_len !=
19162 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19163 return 0;
19164 }
19165 size_t dst_len3 = dst_len / 3;
19166 size_t len = (dst_len3 < src_len) ? dst_len3 : src_len;
19167 uint8_t* d = dst_ptr;
19168 const uint8_t* s = src_ptr;
19169 size_t n = len;
19170
19171 const size_t loop_unroll_count = 4;
19172
19173 // The comparison in the while condition is ">", not ">=", because with
19174 // ">=", the last 4-byte store could write past the end of the dst slice.
19175 //
19176 // Each 4-byte store writes one too many bytes, but a subsequent store
19177 // will overwrite that with the correct byte. There is always another
19178 // store, whether a 4-byte store in this loop or a 1-byte store in the
19179 // next loop.
19180 while (n > loop_unroll_count) {
19181 wuffs_base__poke_u32le__no_bounds_check(
19182 d + (0 * 3), wuffs_base__peek_u32le__no_bounds_check(
19183 dst_palette_ptr + ((size_t)s[0] * 4)));
19184 wuffs_base__poke_u32le__no_bounds_check(
19185 d + (1 * 3), wuffs_base__peek_u32le__no_bounds_check(
19186 dst_palette_ptr + ((size_t)s[1] * 4)));
19187 wuffs_base__poke_u32le__no_bounds_check(
19188 d + (2 * 3), wuffs_base__peek_u32le__no_bounds_check(
19189 dst_palette_ptr + ((size_t)s[2] * 4)));
19190 wuffs_base__poke_u32le__no_bounds_check(
19191 d + (3 * 3), wuffs_base__peek_u32le__no_bounds_check(
19192 dst_palette_ptr + ((size_t)s[3] * 4)));
19193
19194 s += loop_unroll_count * 1;
19195 d += loop_unroll_count * 3;
19196 n -= loop_unroll_count;
19197 }
19198
19199 while (n >= 1) {
19200 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19201 ((size_t)s[0] * 4));
19202 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
19203
19204 s += 1 * 1;
19205 d += 1 * 3;
19206 n -= 1;
19207 }
19208
19209 return len;
19210}
19211
19212static uint64_t //
19213wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over(
19214 uint8_t* dst_ptr,
19215 size_t dst_len,
19216 uint8_t* dst_palette_ptr,
19217 size_t dst_palette_len,
19218 const uint8_t* src_ptr,
19219 size_t src_len) {
19220 if (dst_palette_len !=
19221 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19222 return 0;
19223 }
19224 size_t dst_len3 = dst_len / 3;
19225 size_t len = (dst_len3 < src_len) ? dst_len3 : src_len;
19226 uint8_t* d = dst_ptr;
19227 const uint8_t* s = src_ptr;
19228 size_t n = len;
19229
19230 // TODO: unroll.
19231
19232 while (n >= 1) {
19233 uint32_t d0 =
19234 wuffs_base__peek_u24le__no_bounds_check(d + (0 * 3)) | 0xFF000000;
19235 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19236 ((size_t)s[0] * 4));
19237 wuffs_base__poke_u24le__no_bounds_check(
19238 d + (0 * 3), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0));
19239
19240 s += 1 * 1;
19241 d += 1 * 3;
19242 n -= 1;
19243 }
19244
19245 return len;
19246}
19247
19248static uint64_t //
19249wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over(
19250 uint8_t* dst_ptr,
19251 size_t dst_len,
19252 uint8_t* dst_palette_ptr,
19253 size_t dst_palette_len,
19254 const uint8_t* src_ptr,
19255 size_t src_len) {
19256 if (dst_palette_len !=
19257 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19258 return 0;
19259 }
19260 size_t dst_len3 = dst_len / 3;
19261 size_t len = (dst_len3 < src_len) ? dst_len3 : src_len;
19262 uint8_t* d = dst_ptr;
19263 const uint8_t* s = src_ptr;
19264 size_t n = len;
19265
19266 const size_t loop_unroll_count = 4;
19267
19268 while (n >= loop_unroll_count) {
19269 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19270 ((size_t)s[0] * 4));
19271 if (s0) {
19272 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
19273 }
19274 uint32_t s1 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19275 ((size_t)s[1] * 4));
19276 if (s1) {
19277 wuffs_base__poke_u24le__no_bounds_check(d + (1 * 3), s1);
19278 }
19279 uint32_t s2 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19280 ((size_t)s[2] * 4));
19281 if (s2) {
19282 wuffs_base__poke_u24le__no_bounds_check(d + (2 * 3), s2);
19283 }
19284 uint32_t s3 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19285 ((size_t)s[3] * 4));
19286 if (s3) {
19287 wuffs_base__poke_u24le__no_bounds_check(d + (3 * 3), s3);
19288 }
19289
19290 s += loop_unroll_count * 1;
19291 d += loop_unroll_count * 3;
19292 n -= loop_unroll_count;
19293 }
19294
19295 while (n >= 1) {
19296 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19297 ((size_t)s[0] * 4));
19298 if (s0) {
19299 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
19300 }
19301
19302 s += 1 * 1;
19303 d += 1 * 3;
19304 n -= 1;
19305 }
19306
19307 return len;
19308}
19309
19310static uint64_t //
19311wuffs_base__pixel_swizzler__xxx__xxxx(uint8_t* dst_ptr,
19312 size_t dst_len,
19313 uint8_t* dst_palette_ptr,
19314 size_t dst_palette_len,
19315 const uint8_t* src_ptr,
19316 size_t src_len) {
19317 size_t dst_len3 = dst_len / 3;
19318 size_t src_len4 = src_len / 4;
19319 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
19320 uint8_t* d = dst_ptr;
19321 const uint8_t* s = src_ptr;
19322 size_t n = len;
19323
19324 // TODO: unroll.
19325
19326 while (n >= 1) {
19327 wuffs_base__poke_u24le__no_bounds_check(
19328 d + (0 * 3), wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
19329
19330 s += 1 * 4;
19331 d += 1 * 3;
19332 n -= 1;
19333 }
19334
19335 return len;
19336}
19337
19338static uint64_t //
19339wuffs_base__pixel_swizzler__xxx__y(uint8_t* dst_ptr,
19340 size_t dst_len,
19341 uint8_t* dst_palette_ptr,
19342 size_t dst_palette_len,
19343 const uint8_t* src_ptr,
19344 size_t src_len) {
19345 size_t dst_len3 = dst_len / 3;
19346 size_t len = (dst_len3 < src_len) ? dst_len3 : src_len;
19347 uint8_t* d = dst_ptr;
19348 const uint8_t* s = src_ptr;
19349 size_t n = len;
19350
19351 // TODO: unroll.
19352
19353 while (n >= 1) {
19354 uint8_t s0 = s[0];
19355 d[0] = s0;
19356 d[1] = s0;
19357 d[2] = s0;
19358
19359 s += 1 * 1;
19360 d += 1 * 3;
19361 n -= 1;
19362 }
19363
19364 return len;
19365}
19366
19367static uint64_t //
19368wuffs_base__pixel_swizzler__xxx__y_16be(uint8_t* dst_ptr,
19369 size_t dst_len,
19370 uint8_t* dst_palette_ptr,
19371 size_t dst_palette_len,
19372 const uint8_t* src_ptr,
19373 size_t src_len) {
19374 size_t dst_len3 = dst_len / 3;
19375 size_t src_len2 = src_len / 2;
19376 size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2;
19377 uint8_t* d = dst_ptr;
19378 const uint8_t* s = src_ptr;
19379 size_t n = len;
19380
19381 // TODO: unroll.
19382
19383 while (n >= 1) {
19384 uint8_t s0 = s[0];
19385 d[0] = s0;
19386 d[1] = s0;
19387 d[2] = s0;
19388
19389 s += 1 * 2;
19390 d += 1 * 3;
19391 n -= 1;
19392 }
19393
19394 return len;
19395}
19396
19397// --------
19398
19399static uint64_t //
19400wuffs_base__pixel_swizzler__xxxx__index__src(uint8_t* dst_ptr,
19401 size_t dst_len,
19402 uint8_t* dst_palette_ptr,
19403 size_t dst_palette_len,
19404 const uint8_t* src_ptr,
19405 size_t src_len) {
19406 if (dst_palette_len !=
19407 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19408 return 0;
19409 }
19410 size_t dst_len4 = dst_len / 4;
19411 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
19412 uint8_t* d = dst_ptr;
19413 const uint8_t* s = src_ptr;
19414 size_t n = len;
19415
19416 const size_t loop_unroll_count = 4;
19417
19418 while (n >= loop_unroll_count) {
19419 wuffs_base__poke_u32le__no_bounds_check(
19420 d + (0 * 4), wuffs_base__peek_u32le__no_bounds_check(
19421 dst_palette_ptr + ((size_t)s[0] * 4)));
19422 wuffs_base__poke_u32le__no_bounds_check(
19423 d + (1 * 4), wuffs_base__peek_u32le__no_bounds_check(
19424 dst_palette_ptr + ((size_t)s[1] * 4)));
19425 wuffs_base__poke_u32le__no_bounds_check(
19426 d + (2 * 4), wuffs_base__peek_u32le__no_bounds_check(
19427 dst_palette_ptr + ((size_t)s[2] * 4)));
19428 wuffs_base__poke_u32le__no_bounds_check(
19429 d + (3 * 4), wuffs_base__peek_u32le__no_bounds_check(
19430 dst_palette_ptr + ((size_t)s[3] * 4)));
19431
19432 s += loop_unroll_count * 1;
19433 d += loop_unroll_count * 4;
19434 n -= loop_unroll_count;
19435 }
19436
19437 while (n >= 1) {
19438 wuffs_base__poke_u32le__no_bounds_check(
19439 d + (0 * 4), wuffs_base__peek_u32le__no_bounds_check(
19440 dst_palette_ptr + ((size_t)s[0] * 4)));
19441
19442 s += 1 * 1;
19443 d += 1 * 4;
19444 n -= 1;
19445 }
19446
19447 return len;
19448}
19449
19450static uint64_t //
19451wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over(
19452 uint8_t* dst_ptr,
19453 size_t dst_len,
19454 uint8_t* dst_palette_ptr,
19455 size_t dst_palette_len,
19456 const uint8_t* src_ptr,
19457 size_t src_len) {
19458 if (dst_palette_len !=
19459 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19460 return 0;
19461 }
19462 size_t dst_len4 = dst_len / 4;
19463 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
19464 uint8_t* d = dst_ptr;
19465 const uint8_t* s = src_ptr;
19466 size_t n = len;
19467
19468 const size_t loop_unroll_count = 4;
19469
19470 while (n >= loop_unroll_count) {
19471 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19472 ((size_t)s[0] * 4));
19473 if (s0) {
19474 wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0);
19475 }
19476 uint32_t s1 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19477 ((size_t)s[1] * 4));
19478 if (s1) {
19479 wuffs_base__poke_u32le__no_bounds_check(d + (1 * 4), s1);
19480 }
19481 uint32_t s2 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19482 ((size_t)s[2] * 4));
19483 if (s2) {
19484 wuffs_base__poke_u32le__no_bounds_check(d + (2 * 4), s2);
19485 }
19486 uint32_t s3 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19487 ((size_t)s[3] * 4));
19488 if (s3) {
19489 wuffs_base__poke_u32le__no_bounds_check(d + (3 * 4), s3);
19490 }
19491
19492 s += loop_unroll_count * 1;
19493 d += loop_unroll_count * 4;
19494 n -= loop_unroll_count;
19495 }
19496
19497 while (n >= 1) {
19498 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19499 ((size_t)s[0] * 4));
19500 if (s0) {
19501 wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0);
19502 }
19503
19504 s += 1 * 1;
19505 d += 1 * 4;
19506 n -= 1;
19507 }
19508
19509 return len;
19510}
19511
19512// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
Nigel Tao7804ffe2021-10-07 21:58:26 +110019513#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100019514WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
19515static uint64_t //
19516wuffs_base__pixel_swizzler__xxxx__y__sse42(uint8_t* dst_ptr,
19517 size_t dst_len,
19518 uint8_t* dst_palette_ptr,
19519 size_t dst_palette_len,
19520 const uint8_t* src_ptr,
19521 size_t src_len) {
19522 size_t dst_len4 = dst_len / 4;
19523 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
19524 uint8_t* d = dst_ptr;
19525 const uint8_t* s = src_ptr;
19526 size_t n = len;
19527
19528 __m128i shuffle = _mm_set_epi8(+0x03, +0x03, +0x03, +0x03, //
19529 +0x02, +0x02, +0x02, +0x02, //
19530 +0x01, +0x01, +0x01, +0x01, //
19531 +0x00, +0x00, +0x00, +0x00);
19532 __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, //
19533 -0x01, +0x00, +0x00, +0x00, //
19534 -0x01, +0x00, +0x00, +0x00, //
19535 -0x01, +0x00, +0x00, +0x00);
19536
19537 while (n >= 4) {
19538 __m128i x;
19539 x = _mm_cvtsi32_si128((int)(wuffs_base__peek_u32le__no_bounds_check(s)));
19540 x = _mm_shuffle_epi8(x, shuffle);
19541 x = _mm_or_si128(x, or_ff);
19542 _mm_storeu_si128((__m128i*)(void*)d, x);
19543
19544 s += 4 * 1;
19545 d += 4 * 4;
19546 n -= 4;
19547 }
19548
19549 while (n >= 1) {
19550 wuffs_base__poke_u32le__no_bounds_check(
19551 d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0]));
19552
19553 s += 1 * 1;
19554 d += 1 * 4;
19555 n -= 1;
19556 }
19557
19558 return len;
19559}
Nigel Tao7804ffe2021-10-07 21:58:26 +110019560#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100019561// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
19562
19563static uint64_t //
19564wuffs_base__pixel_swizzler__xxxx__y(uint8_t* dst_ptr,
19565 size_t dst_len,
19566 uint8_t* dst_palette_ptr,
19567 size_t dst_palette_len,
19568 const uint8_t* src_ptr,
19569 size_t src_len) {
19570 size_t dst_len4 = dst_len / 4;
19571 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
19572 uint8_t* d = dst_ptr;
19573 const uint8_t* s = src_ptr;
19574 size_t n = len;
19575
19576 while (n >= 1) {
19577 wuffs_base__poke_u32le__no_bounds_check(
19578 d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0]));
19579
19580 s += 1 * 1;
19581 d += 1 * 4;
19582 n -= 1;
19583 }
19584
19585 return len;
19586}
19587
19588static uint64_t //
19589wuffs_base__pixel_swizzler__xxxx__y_16be(uint8_t* dst_ptr,
19590 size_t dst_len,
19591 uint8_t* dst_palette_ptr,
19592 size_t dst_palette_len,
19593 const uint8_t* src_ptr,
19594 size_t src_len) {
19595 size_t dst_len4 = dst_len / 4;
19596 size_t src_len2 = src_len / 2;
19597 size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2;
19598 uint8_t* d = dst_ptr;
19599 const uint8_t* s = src_ptr;
19600 size_t n = len;
19601
19602 while (n >= 1) {
19603 wuffs_base__poke_u32le__no_bounds_check(
19604 d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0]));
19605
19606 s += 1 * 2;
19607 d += 1 * 4;
19608 n -= 1;
19609 }
19610
19611 return len;
19612}
19613
19614// --------
19615
19616static uint64_t //
19617wuffs_base__pixel_swizzler__xxxxxxxx__index__src(uint8_t* dst_ptr,
19618 size_t dst_len,
19619 uint8_t* dst_palette_ptr,
19620 size_t dst_palette_len,
19621 const uint8_t* src_ptr,
19622 size_t src_len) {
19623 if (dst_palette_len !=
19624 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19625 return 0;
19626 }
19627 size_t dst_len8 = dst_len / 8;
19628 size_t len = (dst_len8 < src_len) ? dst_len8 : src_len;
19629 uint8_t* d = dst_ptr;
19630 const uint8_t* s = src_ptr;
19631 size_t n = len;
19632
19633 while (n >= 1) {
19634 wuffs_base__poke_u64le__no_bounds_check(
19635 d + (0 * 8), wuffs_base__color_u32__as__color_u64(
19636 wuffs_base__peek_u32le__no_bounds_check(
19637 dst_palette_ptr + ((size_t)s[0] * 4))));
19638
19639 s += 1 * 1;
19640 d += 1 * 8;
19641 n -= 1;
19642 }
19643
19644 return len;
19645}
19646
19647static uint64_t //
19648wuffs_base__pixel_swizzler__xxxxxxxx__index_binary_alpha__src_over(
19649 uint8_t* dst_ptr,
19650 size_t dst_len,
19651 uint8_t* dst_palette_ptr,
19652 size_t dst_palette_len,
19653 const uint8_t* src_ptr,
19654 size_t src_len) {
19655 if (dst_palette_len !=
19656 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19657 return 0;
19658 }
19659 size_t dst_len8 = dst_len / 8;
19660 size_t len = (dst_len8 < src_len) ? dst_len8 : src_len;
19661 uint8_t* d = dst_ptr;
19662 const uint8_t* s = src_ptr;
19663 size_t n = len;
19664
19665 while (n >= 1) {
19666 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19667 ((size_t)s[0] * 4));
19668 if (s0) {
19669 wuffs_base__poke_u64le__no_bounds_check(
19670 d + (0 * 8), wuffs_base__color_u32__as__color_u64(s0));
19671 }
19672
19673 s += 1 * 1;
19674 d += 1 * 8;
19675 n -= 1;
19676 }
19677
19678 return len;
19679}
19680
19681static uint64_t //
19682wuffs_base__pixel_swizzler__xxxxxxxx__y(uint8_t* dst_ptr,
19683 size_t dst_len,
19684 uint8_t* dst_palette_ptr,
19685 size_t dst_palette_len,
19686 const uint8_t* src_ptr,
19687 size_t src_len) {
19688 size_t dst_len8 = dst_len / 8;
19689 size_t len = (dst_len8 < src_len) ? dst_len8 : src_len;
19690 uint8_t* d = dst_ptr;
19691 const uint8_t* s = src_ptr;
19692 size_t n = len;
19693
19694 while (n >= 1) {
19695 wuffs_base__poke_u64le__no_bounds_check(
19696 d + (0 * 8), 0xFFFF000000000000 | (0x010101010101 * (uint64_t)s[0]));
19697
19698 s += 1 * 1;
19699 d += 1 * 8;
19700 n -= 1;
19701 }
19702
19703 return len;
19704}
19705
19706static uint64_t //
19707wuffs_base__pixel_swizzler__xxxxxxxx__y_16be(uint8_t* dst_ptr,
19708 size_t dst_len,
19709 uint8_t* dst_palette_ptr,
19710 size_t dst_palette_len,
19711 const uint8_t* src_ptr,
19712 size_t src_len) {
19713 size_t dst_len8 = dst_len / 8;
19714 size_t src_len2 = src_len / 2;
19715 size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2;
19716 uint8_t* d = dst_ptr;
19717 const uint8_t* s = src_ptr;
19718 size_t n = len;
19719
19720 while (n >= 1) {
19721 uint64_t s0 =
19722 ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(s + (0 * 2))));
19723 wuffs_base__poke_u64le__no_bounds_check(
19724 d + (0 * 8), 0xFFFF000000000000 | (0x000100010001 * s0));
19725
19726 s += 1 * 2;
19727 d += 1 * 8;
19728 n -= 1;
19729 }
19730
19731 return len;
19732}
19733
19734// --------
19735
19736static uint64_t //
19737wuffs_base__pixel_swizzler__y__y_16be(uint8_t* dst_ptr,
19738 size_t dst_len,
19739 uint8_t* dst_palette_ptr,
19740 size_t dst_palette_len,
19741 const uint8_t* src_ptr,
19742 size_t src_len) {
19743 size_t src_len2 = src_len / 2;
19744 size_t len = (dst_len < src_len2) ? dst_len : src_len2;
19745 uint8_t* d = dst_ptr;
19746 const uint8_t* s = src_ptr;
19747 size_t n = len;
19748
19749 while (n >= 1) {
19750 d[0] = s[0];
19751
19752 s += 1 * 2;
19753 d += 1 * 1;
19754 n -= 1;
19755 }
19756
19757 return len;
19758}
19759
Nigel Tao5571bfe2021-06-24 22:44:29 +100019760static uint64_t //
19761wuffs_base__pixel_swizzler__y_16le__y_16be(uint8_t* dst_ptr,
19762 size_t dst_len,
19763 uint8_t* dst_palette_ptr,
19764 size_t dst_palette_len,
19765 const uint8_t* src_ptr,
19766 size_t src_len) {
19767 size_t dst_len2 = dst_len / 2;
19768 size_t src_len2 = src_len / 2;
19769 size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2;
19770 uint8_t* d = dst_ptr;
19771 const uint8_t* s = src_ptr;
19772 size_t n = len;
19773
19774 while (n >= 1) {
19775 uint8_t s0 = s[0];
19776 uint8_t s1 = s[1];
19777 d[0] = s1;
19778 d[1] = s0;
19779
19780 s += 1 * 2;
19781 d += 1 * 2;
19782 n -= 1;
19783 }
19784
19785 return len;
19786}
19787
Nigel Taoe360a532021-04-05 22:47:03 +100019788// --------
19789
19790static uint64_t //
19791wuffs_base__pixel_swizzler__transparent_black_src(
19792 uint8_t* dst_ptr,
19793 size_t dst_len,
19794 uint8_t* dst_palette_ptr,
19795 size_t dst_palette_len,
19796 uint64_t num_pixels,
19797 uint32_t dst_pixfmt_bytes_per_pixel) {
19798 uint64_t n = ((uint64_t)dst_len) / dst_pixfmt_bytes_per_pixel;
19799 if (n > num_pixels) {
19800 n = num_pixels;
19801 }
19802 memset(dst_ptr, 0, ((size_t)(n * dst_pixfmt_bytes_per_pixel)));
19803 return n;
19804}
19805
19806static uint64_t //
19807wuffs_base__pixel_swizzler__transparent_black_src_over(
19808 uint8_t* dst_ptr,
19809 size_t dst_len,
19810 uint8_t* dst_palette_ptr,
19811 size_t dst_palette_len,
19812 uint64_t num_pixels,
19813 uint32_t dst_pixfmt_bytes_per_pixel) {
19814 uint64_t n = ((uint64_t)dst_len) / dst_pixfmt_bytes_per_pixel;
19815 if (n > num_pixels) {
19816 n = num_pixels;
19817 }
19818 return n;
19819}
19820
19821// --------
19822
19823static wuffs_base__pixel_swizzler__func //
19824wuffs_base__pixel_swizzler__prepare__y(wuffs_base__pixel_swizzler* p,
19825 wuffs_base__pixel_format dst_pixfmt,
19826 wuffs_base__slice_u8 dst_palette,
19827 wuffs_base__slice_u8 src_palette,
19828 wuffs_base__pixel_blend blend) {
19829 switch (dst_pixfmt.repr) {
19830 case WUFFS_BASE__PIXEL_FORMAT__Y:
19831 return wuffs_base__pixel_swizzler__copy_1_1;
19832
19833 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
19834 return wuffs_base__pixel_swizzler__bgr_565__y;
19835
19836 case WUFFS_BASE__PIXEL_FORMAT__BGR:
19837 case WUFFS_BASE__PIXEL_FORMAT__RGB:
19838 return wuffs_base__pixel_swizzler__xxx__y;
19839
19840 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
19841 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
19842 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
19843 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
19844 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
19845 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
19846 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
19847 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
Nigel Tao7804ffe2021-10-07 21:58:26 +110019848#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100019849 if (wuffs_base__cpu_arch__have_x86_sse42()) {
19850 return wuffs_base__pixel_swizzler__xxxx__y__sse42;
19851 }
19852#endif
19853 return wuffs_base__pixel_swizzler__xxxx__y;
19854
19855 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
19856 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
19857 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE:
19858 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE:
19859 return wuffs_base__pixel_swizzler__xxxxxxxx__y;
19860 }
19861 return NULL;
19862}
19863
19864static wuffs_base__pixel_swizzler__func //
19865wuffs_base__pixel_swizzler__prepare__y_16be(wuffs_base__pixel_swizzler* p,
19866 wuffs_base__pixel_format dst_pixfmt,
19867 wuffs_base__slice_u8 dst_palette,
19868 wuffs_base__slice_u8 src_palette,
19869 wuffs_base__pixel_blend blend) {
19870 switch (dst_pixfmt.repr) {
19871 case WUFFS_BASE__PIXEL_FORMAT__Y:
19872 return wuffs_base__pixel_swizzler__y__y_16be;
19873
Nigel Tao5571bfe2021-06-24 22:44:29 +100019874 case WUFFS_BASE__PIXEL_FORMAT__Y_16LE:
19875 return wuffs_base__pixel_swizzler__y_16le__y_16be;
19876
19877 case WUFFS_BASE__PIXEL_FORMAT__Y_16BE:
19878 return wuffs_base__pixel_swizzler__copy_2_2;
19879
Nigel Taoe360a532021-04-05 22:47:03 +100019880 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
19881 return wuffs_base__pixel_swizzler__bgr_565__y_16be;
19882
19883 case WUFFS_BASE__PIXEL_FORMAT__BGR:
19884 case WUFFS_BASE__PIXEL_FORMAT__RGB:
19885 return wuffs_base__pixel_swizzler__xxx__y_16be;
Nigel Taoe360a532021-04-05 22:47:03 +100019886
19887 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
19888 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
19889 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
19890 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
19891 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
19892 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
19893 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
19894 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
19895 return wuffs_base__pixel_swizzler__xxxx__y_16be;
19896
19897 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
19898 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
19899 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE:
19900 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE:
19901 return wuffs_base__pixel_swizzler__xxxxxxxx__y_16be;
19902 }
19903 return NULL;
19904}
19905
19906static wuffs_base__pixel_swizzler__func //
19907wuffs_base__pixel_swizzler__prepare__indexed__bgra_nonpremul(
19908 wuffs_base__pixel_swizzler* p,
19909 wuffs_base__pixel_format dst_pixfmt,
19910 wuffs_base__slice_u8 dst_palette,
19911 wuffs_base__slice_u8 src_palette,
19912 wuffs_base__pixel_blend blend) {
19913 switch (dst_pixfmt.repr) {
19914 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
19915 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
19916 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19917 return NULL;
19918 }
19919 switch (blend) {
19920 case WUFFS_BASE__PIXEL_BLEND__SRC:
19921 return wuffs_base__pixel_swizzler__copy_1_1;
19922 }
19923 return NULL;
19924
19925 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
19926 switch (blend) {
19927 case WUFFS_BASE__PIXEL_BLEND__SRC:
19928 if (wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888(
19929 dst_palette.ptr, dst_palette.len, src_palette.ptr,
19930 src_palette.len, true) !=
19931 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
19932 return NULL;
19933 }
19934 return wuffs_base__pixel_swizzler__bgr_565__index__src;
19935 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
19936 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
19937 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19938 return NULL;
19939 }
19940 return wuffs_base__pixel_swizzler__bgr_565__index_bgra_nonpremul__src_over;
19941 }
19942 return NULL;
19943
19944 case WUFFS_BASE__PIXEL_FORMAT__BGR:
19945 switch (blend) {
19946 case WUFFS_BASE__PIXEL_BLEND__SRC:
19947 if (wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src(
19948 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
19949 src_palette.len) !=
19950 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
19951 return NULL;
19952 }
19953 return wuffs_base__pixel_swizzler__xxx__index__src;
19954 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
19955 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
19956 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19957 return NULL;
19958 }
19959 return wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over;
19960 }
19961 return NULL;
19962
19963 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
19964 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
19965 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19966 return NULL;
19967 }
19968 switch (blend) {
19969 case WUFFS_BASE__PIXEL_BLEND__SRC:
19970 return wuffs_base__pixel_swizzler__xxxx__index__src;
19971 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
19972 return wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over;
19973 }
19974 return NULL;
19975
19976 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
19977 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
19978 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19979 return NULL;
19980 }
19981 switch (blend) {
19982 case WUFFS_BASE__PIXEL_BLEND__SRC:
19983 return wuffs_base__pixel_swizzler__xxxxxxxx__index__src;
19984 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
19985 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__index_bgra_nonpremul__src_over;
19986 }
19987 return NULL;
19988
19989 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
19990 switch (blend) {
19991 case WUFFS_BASE__PIXEL_BLEND__SRC:
19992 if (wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src(
19993 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
19994 src_palette.len) !=
19995 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
19996 return NULL;
19997 }
19998 return wuffs_base__pixel_swizzler__xxxx__index__src;
19999 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20000 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20001 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20002 return NULL;
20003 }
20004 return wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over;
20005 }
20006 return NULL;
20007
20008 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20009 // TODO.
20010 break;
20011
20012 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20013 if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(
20014 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20015 src_palette.len) !=
20016 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20017 return NULL;
20018 }
20019 switch (blend) {
20020 case WUFFS_BASE__PIXEL_BLEND__SRC:
20021 return wuffs_base__pixel_swizzler__xxxx__index__src;
20022 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20023 return wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over;
20024 }
20025 return NULL;
20026
20027 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20028 switch (blend) {
20029 case WUFFS_BASE__PIXEL_BLEND__SRC:
20030 if (wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src(
20031 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20032 src_palette.len) !=
20033 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20034 return NULL;
20035 }
20036 return wuffs_base__pixel_swizzler__xxxx__index__src;
20037 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20038 if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(
20039 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20040 src_palette.len) !=
20041 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20042 return NULL;
20043 }
20044 return wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over;
20045 }
20046 return NULL;
20047
20048 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20049 // TODO.
20050 break;
20051 }
20052 return NULL;
20053}
20054
20055static wuffs_base__pixel_swizzler__func //
20056wuffs_base__pixel_swizzler__prepare__indexed__bgra_binary(
20057 wuffs_base__pixel_swizzler* p,
20058 wuffs_base__pixel_format dst_pixfmt,
20059 wuffs_base__slice_u8 dst_palette,
20060 wuffs_base__slice_u8 src_palette,
20061 wuffs_base__pixel_blend blend) {
20062 switch (dst_pixfmt.repr) {
20063 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
20064 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
20065 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
20066 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20067 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20068 return NULL;
20069 }
20070 switch (blend) {
20071 case WUFFS_BASE__PIXEL_BLEND__SRC:
20072 return wuffs_base__pixel_swizzler__copy_1_1;
20073 }
20074 return NULL;
20075
20076 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20077 if (wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888(
20078 dst_palette.ptr, dst_palette.len, src_palette.ptr,
20079 src_palette.len, false) !=
20080 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20081 return NULL;
20082 }
20083 switch (blend) {
20084 case WUFFS_BASE__PIXEL_BLEND__SRC:
20085 return wuffs_base__pixel_swizzler__bgr_565__index__src;
20086 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20087 return wuffs_base__pixel_swizzler__bgr_565__index_binary_alpha__src_over;
20088 }
20089 return NULL;
20090
20091 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20092 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20093 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20094 return NULL;
20095 }
20096 switch (blend) {
20097 case WUFFS_BASE__PIXEL_BLEND__SRC:
20098 return wuffs_base__pixel_swizzler__xxx__index__src;
20099 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20100 return wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over;
20101 }
20102 return NULL;
20103
20104 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20105 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20106 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20107 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20108 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20109 return NULL;
20110 }
20111 switch (blend) {
20112 case WUFFS_BASE__PIXEL_BLEND__SRC:
20113 return wuffs_base__pixel_swizzler__xxxx__index__src;
20114 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20115 return wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over;
20116 }
20117 return NULL;
20118
20119 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20120 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
20121 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20122 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20123 return NULL;
20124 }
20125 switch (blend) {
20126 case WUFFS_BASE__PIXEL_BLEND__SRC:
20127 return wuffs_base__pixel_swizzler__xxxxxxxx__index__src;
20128 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20129 return wuffs_base__pixel_swizzler__xxxxxxxx__index_binary_alpha__src_over;
20130 }
20131 return NULL;
20132
20133 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20134 if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(
20135 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20136 src_palette.len) !=
20137 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20138 return NULL;
20139 }
20140 switch (blend) {
20141 case WUFFS_BASE__PIXEL_BLEND__SRC:
20142 return wuffs_base__pixel_swizzler__xxx__index__src;
20143 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20144 return wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over;
20145 }
20146 return NULL;
20147
20148 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20149 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20150 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20151 if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(
20152 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20153 src_palette.len) !=
20154 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20155 return NULL;
20156 }
20157 switch (blend) {
20158 case WUFFS_BASE__PIXEL_BLEND__SRC:
20159 return wuffs_base__pixel_swizzler__xxxx__index__src;
20160 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20161 return wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over;
20162 }
20163 return NULL;
20164 }
20165 return NULL;
20166}
20167
20168static wuffs_base__pixel_swizzler__func //
20169wuffs_base__pixel_swizzler__prepare__bgr_565(
20170 wuffs_base__pixel_swizzler* p,
20171 wuffs_base__pixel_format dst_pixfmt,
20172 wuffs_base__slice_u8 dst_palette,
20173 wuffs_base__slice_u8 src_palette,
20174 wuffs_base__pixel_blend blend) {
20175 switch (dst_pixfmt.repr) {
20176 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20177 return wuffs_base__pixel_swizzler__copy_2_2;
20178
20179 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20180 return wuffs_base__pixel_swizzler__bgr__bgr_565;
20181
20182 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20183 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20184 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20185 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20186 return wuffs_base__pixel_swizzler__bgrw__bgr_565;
20187
20188 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20189 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
20190 return wuffs_base__pixel_swizzler__bgrw_4x16le__bgr_565;
20191
20192 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20193 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20194 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20195 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20196 return wuffs_base__pixel_swizzler__rgbw__bgr_565;
20197 }
20198 return NULL;
20199}
20200
20201static wuffs_base__pixel_swizzler__func //
20202wuffs_base__pixel_swizzler__prepare__bgr(wuffs_base__pixel_swizzler* p,
20203 wuffs_base__pixel_format dst_pixfmt,
20204 wuffs_base__slice_u8 dst_palette,
20205 wuffs_base__slice_u8 src_palette,
20206 wuffs_base__pixel_blend blend) {
20207 switch (dst_pixfmt.repr) {
20208 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20209 return wuffs_base__pixel_swizzler__bgr_565__bgr;
20210
20211 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20212 return wuffs_base__pixel_swizzler__copy_3_3;
20213
20214 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20215 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20216 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20217 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20218 return wuffs_base__pixel_swizzler__bgrw__bgr;
20219
20220 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20221 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
20222 return wuffs_base__pixel_swizzler__bgrw_4x16le__bgr;
20223
20224 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20225 return wuffs_base__pixel_swizzler__swap_rgb_bgr;
20226
20227 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20228 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20229 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20230 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
Nigel Tao7804ffe2021-10-07 21:58:26 +110020231#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020232 if (wuffs_base__cpu_arch__have_x86_sse42()) {
20233 return wuffs_base__pixel_swizzler__bgrw__rgb__sse42;
20234 }
20235#endif
20236 return wuffs_base__pixel_swizzler__bgrw__rgb;
20237 }
20238 return NULL;
20239}
20240
20241static wuffs_base__pixel_swizzler__func //
20242wuffs_base__pixel_swizzler__prepare__bgra_nonpremul(
20243 wuffs_base__pixel_swizzler* p,
20244 wuffs_base__pixel_format dst_pixfmt,
20245 wuffs_base__slice_u8 dst_palette,
20246 wuffs_base__slice_u8 src_palette,
20247 wuffs_base__pixel_blend blend) {
20248 switch (dst_pixfmt.repr) {
20249 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20250 switch (blend) {
20251 case WUFFS_BASE__PIXEL_BLEND__SRC:
20252 return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src;
20253 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20254 return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src_over;
20255 }
20256 return NULL;
20257
20258 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20259 switch (blend) {
20260 case WUFFS_BASE__PIXEL_BLEND__SRC:
20261 return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src;
20262 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20263 return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src_over;
20264 }
20265 return NULL;
20266
20267 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20268 switch (blend) {
20269 case WUFFS_BASE__PIXEL_BLEND__SRC:
20270 return wuffs_base__pixel_swizzler__copy_4_4;
20271 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20272 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over;
20273 }
20274 return NULL;
20275
20276 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20277 switch (blend) {
20278 case WUFFS_BASE__PIXEL_BLEND__SRC:
20279 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src;
20280 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20281 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src_over;
20282 }
20283 return NULL;
20284
20285 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20286 switch (blend) {
20287 case WUFFS_BASE__PIXEL_BLEND__SRC:
20288 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src;
20289 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20290 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over;
20291 }
20292 return NULL;
20293
20294 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20295 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20296 // TODO.
20297 break;
20298
20299 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20300 // TODO.
20301 break;
20302
20303 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20304 switch (blend) {
20305 case WUFFS_BASE__PIXEL_BLEND__SRC:
Nigel Tao7804ffe2021-10-07 21:58:26 +110020306#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020307 if (wuffs_base__cpu_arch__have_x86_sse42()) {
20308 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42;
20309 }
20310#endif
20311 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx;
20312 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20313 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over;
20314 }
20315 return NULL;
20316
20317 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20318 switch (blend) {
20319 case WUFFS_BASE__PIXEL_BLEND__SRC:
20320 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src;
20321 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20322 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over;
20323 }
20324 return NULL;
20325
20326 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20327 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20328 // TODO.
20329 break;
20330 }
20331 return NULL;
20332}
20333
20334static wuffs_base__pixel_swizzler__func //
20335wuffs_base__pixel_swizzler__prepare__bgra_nonpremul_4x16le(
20336 wuffs_base__pixel_swizzler* p,
20337 wuffs_base__pixel_format dst_pixfmt,
20338 wuffs_base__slice_u8 dst_palette,
20339 wuffs_base__slice_u8 src_palette,
20340 wuffs_base__pixel_blend blend) {
20341 switch (dst_pixfmt.repr) {
20342 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20343 switch (blend) {
20344 case WUFFS_BASE__PIXEL_BLEND__SRC:
20345 return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src;
20346 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20347 return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src_over;
20348 }
20349 return NULL;
20350
20351 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20352 switch (blend) {
20353 case WUFFS_BASE__PIXEL_BLEND__SRC:
20354 return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src;
20355 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20356 return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src_over;
20357 }
20358 return NULL;
20359
20360 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20361 switch (blend) {
20362 case WUFFS_BASE__PIXEL_BLEND__SRC:
20363 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src;
20364 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20365 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src_over;
20366 }
20367 return NULL;
20368
20369 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20370 switch (blend) {
20371 case WUFFS_BASE__PIXEL_BLEND__SRC:
20372 return wuffs_base__pixel_swizzler__copy_8_8;
20373 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20374 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul_4x16le__src_over;
20375 }
20376 return NULL;
20377
20378 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20379 switch (blend) {
20380 case WUFFS_BASE__PIXEL_BLEND__SRC:
20381 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src;
20382 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20383 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src_over;
20384 }
20385 return NULL;
20386
20387 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20388 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20389 // TODO.
20390 break;
20391
20392 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20393 // TODO.
20394 break;
20395
20396 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20397 switch (blend) {
20398 case WUFFS_BASE__PIXEL_BLEND__SRC:
20399 return wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src;
20400 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20401 return wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src_over;
20402 }
20403 break;
20404
20405 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20406 switch (blend) {
20407 case WUFFS_BASE__PIXEL_BLEND__SRC:
20408 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src;
20409 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20410 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src_over;
20411 }
20412 return NULL;
20413
20414 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20415 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20416 // TODO.
20417 break;
20418 }
20419 return NULL;
20420}
20421
20422static wuffs_base__pixel_swizzler__func //
20423wuffs_base__pixel_swizzler__prepare__bgra_premul(
20424 wuffs_base__pixel_swizzler* p,
20425 wuffs_base__pixel_format dst_pixfmt,
20426 wuffs_base__slice_u8 dst_palette,
20427 wuffs_base__slice_u8 src_palette,
20428 wuffs_base__pixel_blend blend) {
20429 switch (dst_pixfmt.repr) {
20430 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20431 switch (blend) {
20432 case WUFFS_BASE__PIXEL_BLEND__SRC:
20433 return wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src;
20434 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20435 return wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src_over;
20436 }
20437 return NULL;
20438
20439 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20440 switch (blend) {
20441 case WUFFS_BASE__PIXEL_BLEND__SRC:
20442 return wuffs_base__pixel_swizzler__bgr__bgra_premul__src;
20443 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20444 return wuffs_base__pixel_swizzler__bgr__bgra_premul__src_over;
20445 }
20446 return NULL;
20447
20448 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20449 switch (blend) {
20450 case WUFFS_BASE__PIXEL_BLEND__SRC:
20451 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src;
20452 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20453 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over;
20454 }
20455 return NULL;
20456
20457 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20458 switch (blend) {
20459 case WUFFS_BASE__PIXEL_BLEND__SRC:
20460 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src;
20461 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20462 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src_over;
20463 }
20464 return NULL;
20465
20466 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20467 switch (blend) {
20468 case WUFFS_BASE__PIXEL_BLEND__SRC:
20469 return wuffs_base__pixel_swizzler__copy_4_4;
20470 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20471 return wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over;
20472 }
20473 return NULL;
20474
20475 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20476 switch (blend) {
20477 case WUFFS_BASE__PIXEL_BLEND__SRC:
20478 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src;
20479 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20480 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over;
20481 }
20482 return NULL;
20483
20484 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20485 switch (blend) {
20486 case WUFFS_BASE__PIXEL_BLEND__SRC:
Nigel Tao7804ffe2021-10-07 21:58:26 +110020487#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020488 if (wuffs_base__cpu_arch__have_x86_sse42()) {
20489 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42;
20490 }
20491#endif
20492 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx;
20493 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20494 return wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over;
20495 }
20496 return NULL;
20497 }
20498 return NULL;
20499}
20500
20501static wuffs_base__pixel_swizzler__func //
20502wuffs_base__pixel_swizzler__prepare__bgrx(wuffs_base__pixel_swizzler* p,
20503 wuffs_base__pixel_format dst_pixfmt,
20504 wuffs_base__slice_u8 dst_palette,
20505 wuffs_base__slice_u8 src_palette,
20506 wuffs_base__pixel_blend blend) {
20507 switch (dst_pixfmt.repr) {
20508 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20509 return wuffs_base__pixel_swizzler__bgr_565__bgrx;
20510
20511 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20512 return wuffs_base__pixel_swizzler__xxx__xxxx;
20513
20514 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20515 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20516 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20517 return wuffs_base__pixel_swizzler__bgrw__bgrx;
20518
20519 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20520 return wuffs_base__pixel_swizzler__bgrw_4x16le__bgrx;
20521
20522 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20523 return wuffs_base__pixel_swizzler__copy_4_4;
20524
20525 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20526 // TODO.
20527 break;
20528
20529 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20530 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20531 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20532 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20533 return wuffs_base__pixel_swizzler__bgrw__rgbx;
20534 }
20535 return NULL;
20536}
20537
20538static wuffs_base__pixel_swizzler__func //
20539wuffs_base__pixel_swizzler__prepare__rgb(wuffs_base__pixel_swizzler* p,
20540 wuffs_base__pixel_format dst_pixfmt,
20541 wuffs_base__slice_u8 dst_palette,
20542 wuffs_base__slice_u8 src_palette,
20543 wuffs_base__pixel_blend blend) {
20544 switch (dst_pixfmt.repr) {
20545 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20546 return wuffs_base__pixel_swizzler__bgr_565__rgb;
20547
20548 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20549 return wuffs_base__pixel_swizzler__swap_rgb_bgr;
20550
20551 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20552 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20553 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20554 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
Nigel Tao7804ffe2021-10-07 21:58:26 +110020555#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020556 if (wuffs_base__cpu_arch__have_x86_sse42()) {
20557 return wuffs_base__pixel_swizzler__bgrw__rgb__sse42;
20558 }
20559#endif
20560 return wuffs_base__pixel_swizzler__bgrw__rgb;
20561
20562 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20563 return wuffs_base__pixel_swizzler__bgrw_4x16le__rgb;
20564
20565 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20566 return wuffs_base__pixel_swizzler__copy_3_3;
20567
20568 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20569 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20570 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20571 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20572 return wuffs_base__pixel_swizzler__bgrw__bgr;
20573 }
20574 return NULL;
20575}
20576
20577static wuffs_base__pixel_swizzler__func //
20578wuffs_base__pixel_swizzler__prepare__rgba_nonpremul(
20579 wuffs_base__pixel_swizzler* p,
20580 wuffs_base__pixel_format dst_pixfmt,
20581 wuffs_base__slice_u8 dst_palette,
20582 wuffs_base__slice_u8 src_palette,
20583 wuffs_base__pixel_blend blend) {
20584 switch (dst_pixfmt.repr) {
20585 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20586 switch (blend) {
20587 case WUFFS_BASE__PIXEL_BLEND__SRC:
20588 return wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src;
20589 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20590 return wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src_over;
20591 }
20592 return NULL;
20593
20594 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20595 switch (blend) {
20596 case WUFFS_BASE__PIXEL_BLEND__SRC:
20597 return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src;
20598 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20599 return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src_over;
20600 }
20601 return NULL;
20602
20603 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20604 switch (blend) {
20605 case WUFFS_BASE__PIXEL_BLEND__SRC:
Nigel Tao7804ffe2021-10-07 21:58:26 +110020606#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020607 if (wuffs_base__cpu_arch__have_x86_sse42()) {
20608 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42;
20609 }
20610#endif
20611 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx;
20612 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20613 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over;
20614 }
20615 return NULL;
20616
20617 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20618 switch (blend) {
20619 case WUFFS_BASE__PIXEL_BLEND__SRC:
20620 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src;
20621 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20622 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src_over;
20623 }
20624 return NULL;
20625
20626 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20627 switch (blend) {
20628 case WUFFS_BASE__PIXEL_BLEND__SRC:
20629 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src;
20630 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20631 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over;
20632 }
20633 return NULL;
20634
20635 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20636 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20637 // TODO.
20638 break;
20639
20640 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20641 // TODO.
20642 break;
20643
20644 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20645 switch (blend) {
20646 case WUFFS_BASE__PIXEL_BLEND__SRC:
20647 return wuffs_base__pixel_swizzler__copy_4_4;
20648 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20649 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over;
20650 }
20651 return NULL;
20652
20653 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20654 switch (blend) {
20655 case WUFFS_BASE__PIXEL_BLEND__SRC:
20656 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src;
20657 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20658 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over;
20659 }
20660 return NULL;
20661
20662 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20663 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20664 // TODO.
20665 break;
20666 }
20667 return NULL;
20668}
20669
20670static wuffs_base__pixel_swizzler__func //
20671wuffs_base__pixel_swizzler__prepare__rgba_premul(
20672 wuffs_base__pixel_swizzler* p,
20673 wuffs_base__pixel_format dst_pixfmt,
20674 wuffs_base__slice_u8 dst_palette,
20675 wuffs_base__slice_u8 src_palette,
20676 wuffs_base__pixel_blend blend) {
20677 switch (dst_pixfmt.repr) {
20678 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20679 switch (blend) {
20680 case WUFFS_BASE__PIXEL_BLEND__SRC:
20681 return wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src;
20682 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20683 return wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src_over;
20684 }
20685 return NULL;
20686
20687 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20688 switch (blend) {
20689 case WUFFS_BASE__PIXEL_BLEND__SRC:
20690 return wuffs_base__pixel_swizzler__bgr__rgba_premul__src;
20691 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20692 return wuffs_base__pixel_swizzler__bgr__rgba_premul__src_over;
20693 }
20694 return NULL;
20695
20696 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20697 switch (blend) {
20698 case WUFFS_BASE__PIXEL_BLEND__SRC:
20699 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src;
20700 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20701 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over;
20702 }
20703 return NULL;
20704
20705 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20706 switch (blend) {
20707 case WUFFS_BASE__PIXEL_BLEND__SRC:
20708 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src;
20709 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20710 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src_over;
20711 }
20712 return NULL;
20713
20714 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20715 switch (blend) {
20716 case WUFFS_BASE__PIXEL_BLEND__SRC:
Nigel Tao7804ffe2021-10-07 21:58:26 +110020717#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020718 if (wuffs_base__cpu_arch__have_x86_sse42()) {
20719 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42;
20720 }
20721#endif
20722 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx;
20723 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20724 return wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over;
20725 }
20726 return NULL;
20727
20728 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20729 switch (blend) {
20730 case WUFFS_BASE__PIXEL_BLEND__SRC:
20731 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src;
20732 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20733 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over;
20734 }
20735 return NULL;
20736
20737 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20738 switch (blend) {
20739 case WUFFS_BASE__PIXEL_BLEND__SRC:
20740 return wuffs_base__pixel_swizzler__copy_4_4;
20741 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20742 return wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over;
20743 }
20744 return NULL;
20745 }
20746 return NULL;
20747}
20748
20749// --------
20750
20751WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
20752wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
20753 wuffs_base__pixel_format dst_pixfmt,
20754 wuffs_base__slice_u8 dst_palette,
20755 wuffs_base__pixel_format src_pixfmt,
20756 wuffs_base__slice_u8 src_palette,
20757 wuffs_base__pixel_blend blend) {
20758 if (!p) {
20759 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
20760 }
20761 p->private_impl.func = NULL;
20762 p->private_impl.transparent_black_func = NULL;
20763 p->private_impl.dst_pixfmt_bytes_per_pixel = 0;
20764 p->private_impl.src_pixfmt_bytes_per_pixel = 0;
20765
20766 wuffs_base__pixel_swizzler__func func = NULL;
20767 wuffs_base__pixel_swizzler__transparent_black_func transparent_black_func =
20768 NULL;
20769
20770 uint32_t dst_pixfmt_bits_per_pixel =
20771 wuffs_base__pixel_format__bits_per_pixel(&dst_pixfmt);
20772 if ((dst_pixfmt_bits_per_pixel == 0) ||
20773 ((dst_pixfmt_bits_per_pixel & 7) != 0)) {
20774 return wuffs_base__make_status(
20775 wuffs_base__error__unsupported_pixel_swizzler_option);
20776 }
20777
20778 uint32_t src_pixfmt_bits_per_pixel =
20779 wuffs_base__pixel_format__bits_per_pixel(&src_pixfmt);
20780 if ((src_pixfmt_bits_per_pixel == 0) ||
20781 ((src_pixfmt_bits_per_pixel & 7) != 0)) {
20782 return wuffs_base__make_status(
20783 wuffs_base__error__unsupported_pixel_swizzler_option);
20784 }
20785
20786 // TODO: support many more formats.
20787
20788 switch (blend) {
20789 case WUFFS_BASE__PIXEL_BLEND__SRC:
20790 transparent_black_func =
20791 wuffs_base__pixel_swizzler__transparent_black_src;
20792 break;
20793
20794 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20795 transparent_black_func =
20796 wuffs_base__pixel_swizzler__transparent_black_src_over;
20797 break;
20798 }
20799
20800 switch (src_pixfmt.repr) {
20801 case WUFFS_BASE__PIXEL_FORMAT__Y:
20802 func = wuffs_base__pixel_swizzler__prepare__y(p, dst_pixfmt, dst_palette,
20803 src_palette, blend);
20804 break;
20805
20806 case WUFFS_BASE__PIXEL_FORMAT__Y_16BE:
20807 func = wuffs_base__pixel_swizzler__prepare__y_16be(
20808 p, dst_pixfmt, dst_palette, src_palette, blend);
20809 break;
20810
20811 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
20812 func = wuffs_base__pixel_swizzler__prepare__indexed__bgra_nonpremul(
20813 p, dst_pixfmt, dst_palette, src_palette, blend);
20814 break;
20815
20816 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
20817 func = wuffs_base__pixel_swizzler__prepare__indexed__bgra_binary(
20818 p, dst_pixfmt, dst_palette, src_palette, blend);
20819 break;
20820
20821 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20822 func = wuffs_base__pixel_swizzler__prepare__bgr_565(
20823 p, dst_pixfmt, dst_palette, src_palette, blend);
20824 break;
20825
20826 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20827 func = wuffs_base__pixel_swizzler__prepare__bgr(
20828 p, dst_pixfmt, dst_palette, src_palette, blend);
20829 break;
20830
20831 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20832 func = wuffs_base__pixel_swizzler__prepare__bgra_nonpremul(
20833 p, dst_pixfmt, dst_palette, src_palette, blend);
20834 break;
20835
20836 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20837 func = wuffs_base__pixel_swizzler__prepare__bgra_nonpremul_4x16le(
20838 p, dst_pixfmt, dst_palette, src_palette, blend);
20839 break;
20840
20841 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20842 func = wuffs_base__pixel_swizzler__prepare__bgra_premul(
20843 p, dst_pixfmt, dst_palette, src_palette, blend);
20844 break;
20845
20846 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20847 func = wuffs_base__pixel_swizzler__prepare__bgrx(
20848 p, dst_pixfmt, dst_palette, src_palette, blend);
20849 break;
20850
20851 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20852 func = wuffs_base__pixel_swizzler__prepare__rgb(
20853 p, dst_pixfmt, dst_palette, src_palette, blend);
20854 break;
20855
20856 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20857 func = wuffs_base__pixel_swizzler__prepare__rgba_nonpremul(
20858 p, dst_pixfmt, dst_palette, src_palette, blend);
20859 break;
20860
20861 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20862 func = wuffs_base__pixel_swizzler__prepare__rgba_premul(
20863 p, dst_pixfmt, dst_palette, src_palette, blend);
20864 break;
20865 }
20866
20867 p->private_impl.func = func;
20868 p->private_impl.transparent_black_func = transparent_black_func;
20869 p->private_impl.dst_pixfmt_bytes_per_pixel = dst_pixfmt_bits_per_pixel / 8;
20870 p->private_impl.src_pixfmt_bytes_per_pixel = src_pixfmt_bits_per_pixel / 8;
20871 return wuffs_base__make_status(
20872 func ? NULL : wuffs_base__error__unsupported_pixel_swizzler_option);
20873}
20874
20875WUFFS_BASE__MAYBE_STATIC uint64_t //
20876wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
20877 const wuffs_base__pixel_swizzler* p,
20878 uint32_t up_to_num_pixels,
20879 wuffs_base__slice_u8 dst,
20880 wuffs_base__slice_u8 dst_palette,
20881 const uint8_t** ptr_iop_r,
20882 const uint8_t* io2_r) {
20883 if (p && p->private_impl.func) {
20884 const uint8_t* iop_r = *ptr_iop_r;
20885 uint64_t src_len = wuffs_base__u64__min(
20886 ((uint64_t)up_to_num_pixels) *
20887 ((uint64_t)p->private_impl.src_pixfmt_bytes_per_pixel),
20888 ((uint64_t)(io2_r - iop_r)));
20889 uint64_t n =
20890 (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
20891 dst_palette.len, iop_r, (size_t)src_len);
20892 *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;
20893 return n;
20894 }
20895 return 0;
20896}
20897
20898WUFFS_BASE__MAYBE_STATIC uint64_t //
20899wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
20900 const wuffs_base__pixel_swizzler* p,
20901 wuffs_base__slice_u8 dst,
20902 wuffs_base__slice_u8 dst_palette,
20903 const uint8_t** ptr_iop_r,
20904 const uint8_t* io2_r) {
20905 if (p && p->private_impl.func) {
20906 const uint8_t* iop_r = *ptr_iop_r;
20907 uint64_t src_len = ((uint64_t)(io2_r - iop_r));
20908 uint64_t n =
20909 (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
20910 dst_palette.len, iop_r, (size_t)src_len);
20911 *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;
20912 return n;
20913 }
20914 return 0;
20915}
20916
20917WUFFS_BASE__MAYBE_STATIC uint64_t //
20918wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(
20919 const wuffs_base__pixel_swizzler* p,
20920 wuffs_base__slice_u8 dst,
20921 wuffs_base__slice_u8 dst_palette,
20922 wuffs_base__slice_u8 src) {
20923 if (p && p->private_impl.func) {
20924 return (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
20925 dst_palette.len, src.ptr, src.len);
20926 }
20927 return 0;
20928}
20929
20930WUFFS_BASE__MAYBE_STATIC uint64_t //
20931wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(
20932 const wuffs_base__pixel_swizzler* p,
20933 wuffs_base__slice_u8 dst,
20934 wuffs_base__slice_u8 dst_palette,
20935 uint64_t num_pixels) {
20936 if (p && p->private_impl.transparent_black_func) {
20937 return (*p->private_impl.transparent_black_func)(
20938 dst.ptr, dst.len, dst_palette.ptr, dst_palette.len, num_pixels,
20939 p->private_impl.dst_pixfmt_bytes_per_pixel);
20940 }
20941 return 0;
20942}
20943
20944#endif // !defined(WUFFS_CONFIG__MODULES) ||
20945 // defined(WUFFS_CONFIG__MODULE__BASE) ||
20946 // defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV)
20947
20948#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
20949 defined(WUFFS_CONFIG__MODULE__BASE__UTF8)
20950
20951// ---------------- Unicode and UTF-8
20952
20953WUFFS_BASE__MAYBE_STATIC size_t //
20954wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point) {
20955 if (code_point <= 0x7F) {
20956 if (dst.len >= 1) {
20957 dst.ptr[0] = (uint8_t)(code_point);
20958 return 1;
20959 }
20960
20961 } else if (code_point <= 0x07FF) {
20962 if (dst.len >= 2) {
20963 dst.ptr[0] = (uint8_t)(0xC0 | ((code_point >> 6)));
20964 dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));
20965 return 2;
20966 }
20967
20968 } else if (code_point <= 0xFFFF) {
20969 if ((dst.len >= 3) && ((code_point < 0xD800) || (0xDFFF < code_point))) {
20970 dst.ptr[0] = (uint8_t)(0xE0 | ((code_point >> 12)));
20971 dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F));
20972 dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));
20973 return 3;
20974 }
20975
20976 } else if (code_point <= 0x10FFFF) {
20977 if (dst.len >= 4) {
20978 dst.ptr[0] = (uint8_t)(0xF0 | ((code_point >> 18)));
20979 dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 12) & 0x3F));
20980 dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F));
20981 dst.ptr[3] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));
20982 return 4;
20983 }
20984 }
20985
20986 return 0;
20987}
20988
20989// wuffs_base__utf_8__byte_length_minus_1 is the byte length (minus 1) of a
20990// UTF-8 encoded code point, based on the encoding's initial byte.
20991// - 0x00 is 1-byte UTF-8 (ASCII).
20992// - 0x01 is the start of 2-byte UTF-8.
20993// - 0x02 is the start of 3-byte UTF-8.
20994// - 0x03 is the start of 4-byte UTF-8.
20995// - 0x40 is a UTF-8 tail byte.
20996// - 0x80 is invalid UTF-8.
20997//
20998// RFC 3629 (UTF-8) gives this grammar for valid UTF-8:
20999// UTF8-1 = %x00-7F
21000// UTF8-2 = %xC2-DF UTF8-tail
21001// UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
21002// %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
21003// UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
21004// %xF4 %x80-8F 2( UTF8-tail )
21005// UTF8-tail = %x80-BF
21006static const uint8_t wuffs_base__utf_8__byte_length_minus_1[256] = {
21007 // 0 1 2 3 4 5 6 7
21008 // 8 9 A B C D E F
21009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07.
21010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F.
21011 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17.
21012 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F.
21013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27.
21014 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F.
21015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 ..= 0x37.
21016 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F.
21017
21018 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 ..= 0x47.
21019 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F.
21020 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57.
21021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F.
21022 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 ..= 0x67.
21023 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F.
21024 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77.
21025 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F.
21026
21027 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x80 ..= 0x87.
21028 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x88 ..= 0x8F.
21029 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x90 ..= 0x97.
21030 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x98 ..= 0x9F.
21031 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xA0 ..= 0xA7.
21032 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xA8 ..= 0xAF.
21033 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xB0 ..= 0xB7.
21034 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xB8 ..= 0xBF.
21035
21036 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xC0 ..= 0xC7.
21037 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xC8 ..= 0xCF.
21038 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xD0 ..= 0xD7.
21039 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xD8 ..= 0xDF.
21040 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xE0 ..= 0xE7.
21041 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xE8 ..= 0xEF.
21042 0x03, 0x03, 0x03, 0x03, 0x03, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7.
21043 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF.
21044 // 0 1 2 3 4 5 6 7
21045 // 8 9 A B C D E F
21046};
21047
21048WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
21049wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len) {
21050 if (s_len == 0) {
21051 return wuffs_base__make_utf_8__next__output(0, 0);
21052 }
21053 uint32_t c = s_ptr[0];
21054 switch (wuffs_base__utf_8__byte_length_minus_1[c & 0xFF]) {
21055 case 0:
21056 return wuffs_base__make_utf_8__next__output(c, 1);
21057
21058 case 1:
21059 if (s_len < 2) {
21060 break;
21061 }
21062 c = wuffs_base__peek_u16le__no_bounds_check(s_ptr);
21063 if ((c & 0xC000) != 0x8000) {
21064 break;
21065 }
21066 c = (0x0007C0 & (c << 6)) | (0x00003F & (c >> 8));
21067 return wuffs_base__make_utf_8__next__output(c, 2);
21068
21069 case 2:
21070 if (s_len < 3) {
21071 break;
21072 }
21073 c = wuffs_base__peek_u24le__no_bounds_check(s_ptr);
21074 if ((c & 0xC0C000) != 0x808000) {
21075 break;
21076 }
21077 c = (0x00F000 & (c << 12)) | (0x000FC0 & (c >> 2)) |
21078 (0x00003F & (c >> 16));
21079 if ((c <= 0x07FF) || ((0xD800 <= c) && (c <= 0xDFFF))) {
21080 break;
21081 }
21082 return wuffs_base__make_utf_8__next__output(c, 3);
21083
21084 case 3:
21085 if (s_len < 4) {
21086 break;
21087 }
21088 c = wuffs_base__peek_u32le__no_bounds_check(s_ptr);
21089 if ((c & 0xC0C0C000) != 0x80808000) {
21090 break;
21091 }
21092 c = (0x1C0000 & (c << 18)) | (0x03F000 & (c << 4)) |
21093 (0x000FC0 & (c >> 10)) | (0x00003F & (c >> 24));
21094 if ((c <= 0xFFFF) || (0x110000 <= c)) {
21095 break;
21096 }
21097 return wuffs_base__make_utf_8__next__output(c, 4);
21098 }
21099
21100 return wuffs_base__make_utf_8__next__output(
21101 WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1);
21102}
21103
21104WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
21105wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len) {
21106 if (s_len == 0) {
21107 return wuffs_base__make_utf_8__next__output(0, 0);
21108 }
21109 const uint8_t* ptr = &s_ptr[s_len - 1];
21110 if (*ptr < 0x80) {
21111 return wuffs_base__make_utf_8__next__output(*ptr, 1);
21112
21113 } else if (*ptr < 0xC0) {
21114 const uint8_t* too_far = &s_ptr[(s_len > 4) ? (s_len - 4) : 0];
21115 uint32_t n = 1;
21116 while (ptr != too_far) {
21117 ptr--;
21118 n++;
21119 if (*ptr < 0x80) {
21120 break;
21121 } else if (*ptr < 0xC0) {
21122 continue;
21123 }
21124 wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(ptr, n);
21125 if (o.byte_length != n) {
21126 break;
21127 }
21128 return o;
21129 }
21130 }
21131
21132 return wuffs_base__make_utf_8__next__output(
21133 WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1);
21134}
21135
21136WUFFS_BASE__MAYBE_STATIC size_t //
21137wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) {
21138 // TODO: possibly optimize the all-ASCII case (4 or 8 bytes at a time).
21139 //
21140 // TODO: possibly optimize this by manually inlining the
21141 // wuffs_base__utf_8__next calls.
21142 size_t original_len = s_len;
21143 while (s_len > 0) {
21144 wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(s_ptr, s_len);
21145 if ((o.code_point > 0x7F) && (o.byte_length == 1)) {
21146 break;
21147 }
21148 s_ptr += o.byte_length;
21149 s_len -= o.byte_length;
21150 }
21151 return original_len - s_len;
21152}
21153
21154WUFFS_BASE__MAYBE_STATIC size_t //
21155wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) {
21156 // TODO: possibly optimize this by checking 4 or 8 bytes at a time.
21157 const uint8_t* original_ptr = s_ptr;
21158 const uint8_t* p = s_ptr;
21159 const uint8_t* q = s_ptr + s_len;
21160 for (; (p != q) && ((*p & 0x80) == 0); p++) {
21161 }
21162 return (size_t)(p - original_ptr);
21163}
21164
21165#endif // !defined(WUFFS_CONFIG__MODULES) ||
21166 // defined(WUFFS_CONFIG__MODULE__BASE) ||
21167 // defined(WUFFS_CONFIG__MODULE__BASE__UTF8)
21168
21169#ifdef __cplusplus
21170} // extern "C"
21171#endif
21172
21173#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32)
21174
21175// ---------------- Status Codes Implementations
21176
21177// ---------------- Private Consts
21178
21179// ---------------- Private Initializer Prototypes
21180
21181// ---------------- Private Function Prototypes
21182
21183static wuffs_base__empty_struct
21184wuffs_adler32__hasher__up(
21185 wuffs_adler32__hasher* self,
21186 wuffs_base__slice_u8 a_x);
21187
21188static wuffs_base__empty_struct
21189wuffs_adler32__hasher__up__choosy_default(
21190 wuffs_adler32__hasher* self,
21191 wuffs_base__slice_u8 a_x);
21192
21193#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
21194static wuffs_base__empty_struct
21195wuffs_adler32__hasher__up_arm_neon(
21196 wuffs_adler32__hasher* self,
21197 wuffs_base__slice_u8 a_x);
21198#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
21199
Nigel Tao7804ffe2021-10-07 21:58:26 +110021200#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021201static wuffs_base__empty_struct
21202wuffs_adler32__hasher__up_x86_sse42(
21203 wuffs_adler32__hasher* self,
21204 wuffs_base__slice_u8 a_x);
Nigel Tao7804ffe2021-10-07 21:58:26 +110021205#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021206
21207// ---------------- VTables
21208
21209const wuffs_base__hasher_u32__func_ptrs
21210wuffs_adler32__hasher__func_ptrs_for__wuffs_base__hasher_u32 = {
21211 (wuffs_base__empty_struct(*)(void*,
21212 uint32_t,
21213 bool))(&wuffs_adler32__hasher__set_quirk_enabled),
21214 (uint32_t(*)(void*,
21215 wuffs_base__slice_u8))(&wuffs_adler32__hasher__update_u32),
21216};
21217
21218// ---------------- Initializer Implementations
21219
21220wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
21221wuffs_adler32__hasher__initialize(
21222 wuffs_adler32__hasher* self,
21223 size_t sizeof_star_self,
21224 uint64_t wuffs_version,
21225 uint32_t options){
21226 if (!self) {
21227 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
21228 }
21229 if (sizeof(*self) != sizeof_star_self) {
21230 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
21231 }
21232 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
21233 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
21234 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
21235 }
21236
21237 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
21238 // The whole point of this if-check is to detect an uninitialized *self.
21239 // We disable the warning on GCC. Clang-5.0 does not have this warning.
21240#if !defined(__clang__) && defined(__GNUC__)
21241#pragma GCC diagnostic push
21242#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
21243#endif
21244 if (self->private_impl.magic != 0) {
21245 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
21246 }
21247#if !defined(__clang__) && defined(__GNUC__)
21248#pragma GCC diagnostic pop
21249#endif
21250 } else {
21251 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
21252 memset(self, 0, sizeof(*self));
21253 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
21254 } else {
21255 memset(&(self->private_impl), 0, sizeof(self->private_impl));
21256 }
21257 }
21258
21259 self->private_impl.choosy_up = &wuffs_adler32__hasher__up__choosy_default;
21260
21261 self->private_impl.magic = WUFFS_BASE__MAGIC;
21262 self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name =
21263 wuffs_base__hasher_u32__vtable_name;
21264 self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers =
21265 (const void*)(&wuffs_adler32__hasher__func_ptrs_for__wuffs_base__hasher_u32);
21266 return wuffs_base__make_status(NULL);
21267}
21268
21269wuffs_adler32__hasher*
21270wuffs_adler32__hasher__alloc() {
21271 wuffs_adler32__hasher* x =
21272 (wuffs_adler32__hasher*)(calloc(sizeof(wuffs_adler32__hasher), 1));
21273 if (!x) {
21274 return NULL;
21275 }
21276 if (wuffs_adler32__hasher__initialize(
21277 x, sizeof(wuffs_adler32__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
21278 free(x);
21279 return NULL;
21280 }
21281 return x;
21282}
21283
21284size_t
21285sizeof__wuffs_adler32__hasher() {
21286 return sizeof(wuffs_adler32__hasher);
21287}
21288
21289// ---------------- Function Implementations
21290
21291// -------- func adler32.hasher.set_quirk_enabled
21292
21293WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
21294wuffs_adler32__hasher__set_quirk_enabled(
21295 wuffs_adler32__hasher* self,
21296 uint32_t a_quirk,
21297 bool a_enabled) {
21298 return wuffs_base__make_empty_struct();
21299}
21300
21301// -------- func adler32.hasher.update_u32
21302
21303WUFFS_BASE__MAYBE_STATIC uint32_t
21304wuffs_adler32__hasher__update_u32(
21305 wuffs_adler32__hasher* self,
21306 wuffs_base__slice_u8 a_x) {
21307 if (!self) {
21308 return 0;
21309 }
21310 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
21311 return 0;
21312 }
21313
21314 if ( ! self->private_impl.f_started) {
21315 self->private_impl.f_started = true;
21316 self->private_impl.f_state = 1;
21317 self->private_impl.choosy_up = (
21318#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
21319 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_adler32__hasher__up_arm_neon :
21320#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110021321#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021322 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_adler32__hasher__up_x86_sse42 :
21323#endif
21324 self->private_impl.choosy_up);
21325 }
21326 wuffs_adler32__hasher__up(self, a_x);
21327 return self->private_impl.f_state;
21328}
21329
21330// -------- func adler32.hasher.up
21331
21332static wuffs_base__empty_struct
21333wuffs_adler32__hasher__up(
21334 wuffs_adler32__hasher* self,
21335 wuffs_base__slice_u8 a_x) {
21336 return (*self->private_impl.choosy_up)(self, a_x);
21337}
21338
21339static wuffs_base__empty_struct
21340wuffs_adler32__hasher__up__choosy_default(
21341 wuffs_adler32__hasher* self,
21342 wuffs_base__slice_u8 a_x) {
21343 uint32_t v_s1 = 0;
21344 uint32_t v_s2 = 0;
21345 wuffs_base__slice_u8 v_remaining = {0};
21346 wuffs_base__slice_u8 v_p = {0};
21347
21348 v_s1 = ((self->private_impl.f_state) & 0xFFFF);
21349 v_s2 = ((self->private_impl.f_state) >> (32 - (16)));
21350 while (((uint64_t)(a_x.len)) > 0) {
21351 v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0);
21352 if (((uint64_t)(a_x.len)) > 5552) {
21353 v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5552);
21354 a_x = wuffs_base__slice_u8__subslice_j(a_x, 5552);
21355 }
21356 {
21357 wuffs_base__slice_u8 i_slice_p = a_x;
21358 v_p.ptr = i_slice_p.ptr;
21359 v_p.len = 1;
21360 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8);
21361 while (v_p.ptr < i_end0_p) {
21362 v_s1 += ((uint32_t)(v_p.ptr[0]));
21363 v_s2 += v_s1;
21364 v_p.ptr += 1;
21365 v_s1 += ((uint32_t)(v_p.ptr[0]));
21366 v_s2 += v_s1;
21367 v_p.ptr += 1;
21368 v_s1 += ((uint32_t)(v_p.ptr[0]));
21369 v_s2 += v_s1;
21370 v_p.ptr += 1;
21371 v_s1 += ((uint32_t)(v_p.ptr[0]));
21372 v_s2 += v_s1;
21373 v_p.ptr += 1;
21374 v_s1 += ((uint32_t)(v_p.ptr[0]));
21375 v_s2 += v_s1;
21376 v_p.ptr += 1;
21377 v_s1 += ((uint32_t)(v_p.ptr[0]));
21378 v_s2 += v_s1;
21379 v_p.ptr += 1;
21380 v_s1 += ((uint32_t)(v_p.ptr[0]));
21381 v_s2 += v_s1;
21382 v_p.ptr += 1;
21383 v_s1 += ((uint32_t)(v_p.ptr[0]));
21384 v_s2 += v_s1;
21385 v_p.ptr += 1;
21386 }
21387 v_p.len = 1;
21388 uint8_t* i_end1_p = i_slice_p.ptr + i_slice_p.len;
21389 while (v_p.ptr < i_end1_p) {
21390 v_s1 += ((uint32_t)(v_p.ptr[0]));
21391 v_s2 += v_s1;
21392 v_p.ptr += 1;
21393 }
21394 v_p.len = 0;
21395 }
21396 v_s1 %= 65521;
21397 v_s2 %= 65521;
21398 a_x = v_remaining;
21399 }
21400 self->private_impl.f_state = (((v_s2 & 65535) << 16) | (v_s1 & 65535));
21401 return wuffs_base__make_empty_struct();
21402}
21403
21404// ‼ WUFFS MULTI-FILE SECTION +arm_neon
21405// -------- func adler32.hasher.up_arm_neon
21406
21407#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
21408static wuffs_base__empty_struct
21409wuffs_adler32__hasher__up_arm_neon(
21410 wuffs_adler32__hasher* self,
21411 wuffs_base__slice_u8 a_x) {
21412 uint32_t v_s1 = 0;
21413 uint32_t v_s2 = 0;
21414 wuffs_base__slice_u8 v_remaining = {0};
21415 wuffs_base__slice_u8 v_p = {0};
21416 uint8x16_t v_p__left = {0};
21417 uint8x16_t v_p_right = {0};
21418 uint32x4_t v_v1 = {0};
21419 uint32x4_t v_v2 = {0};
21420 uint16x8_t v_col0 = {0};
21421 uint16x8_t v_col1 = {0};
21422 uint16x8_t v_col2 = {0};
21423 uint16x8_t v_col3 = {0};
21424 uint32x2_t v_sum1 = {0};
21425 uint32x2_t v_sum2 = {0};
21426 uint32x2_t v_sum12 = {0};
21427 uint32_t v_num_iterate_bytes = 0;
21428 uint64_t v_tail_index = 0;
21429
21430 v_s1 = ((self->private_impl.f_state) & 0xFFFF);
21431 v_s2 = ((self->private_impl.f_state) >> (32 - (16)));
21432 while ((((uint64_t)(a_x.len)) > 0) && ((15 & ((uint32_t)(0xFFF & (uintptr_t)(a_x.ptr)))) != 0)) {
21433 v_s1 += ((uint32_t)(a_x.ptr[0]));
21434 v_s2 += v_s1;
21435 a_x = wuffs_base__slice_u8__subslice_i(a_x, 1);
21436 }
21437 v_s1 %= 65521;
21438 v_s2 %= 65521;
21439 while (((uint64_t)(a_x.len)) > 0) {
21440 v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0);
21441 if (((uint64_t)(a_x.len)) > 5536) {
21442 v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5536);
21443 a_x = wuffs_base__slice_u8__subslice_j(a_x, 5536);
21444 }
21445 v_num_iterate_bytes = ((uint32_t)((((uint64_t)(a_x.len)) & 4294967264)));
21446 v_s2 += ((uint32_t)(v_s1 * v_num_iterate_bytes));
21447 v_v1 = vdupq_n_u32(0);
21448 v_v2 = vdupq_n_u32(0);
21449 v_col0 = vdupq_n_u16(0);
21450 v_col1 = vdupq_n_u16(0);
21451 v_col2 = vdupq_n_u16(0);
21452 v_col3 = vdupq_n_u16(0);
21453 {
21454 wuffs_base__slice_u8 i_slice_p = a_x;
21455 v_p.ptr = i_slice_p.ptr;
21456 v_p.len = 32;
21457 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32);
21458 while (v_p.ptr < i_end0_p) {
21459 v_p__left = vld1q_u8(v_p.ptr);
21460 v_p_right = vld1q_u8(v_p.ptr + 16);
21461 v_v2 = vaddq_u32(v_v2, v_v1);
21462 v_v1 = vpadalq_u16(v_v1, vpadalq_u8(vpaddlq_u8(v_p__left), v_p_right));
21463 v_col0 = vaddw_u8(v_col0, vget_low_u8(v_p__left));
21464 v_col1 = vaddw_u8(v_col1, vget_high_u8(v_p__left));
21465 v_col2 = vaddw_u8(v_col2, vget_low_u8(v_p_right));
21466 v_col3 = vaddw_u8(v_col3, vget_high_u8(v_p_right));
21467 v_p.ptr += 32;
21468 }
21469 v_p.len = 0;
21470 }
21471 v_v2 = vshlq_n_u32(v_v2, 5);
21472 v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col0), ((uint16x4_t){32, 31, 30, 29}));
21473 v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col0), ((uint16x4_t){28, 27, 26, 25}));
21474 v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col1), ((uint16x4_t){24, 23, 22, 21}));
21475 v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col1), ((uint16x4_t){20, 19, 18, 17}));
21476 v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col2), ((uint16x4_t){16, 15, 14, 13}));
21477 v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col2), ((uint16x4_t){12, 11, 10, 9}));
21478 v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col3), ((uint16x4_t){8, 7, 6, 5}));
21479 v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col3), ((uint16x4_t){4, 3, 2, 1}));
21480 v_sum1 = vpadd_u32(vget_low_u32(v_v1), vget_high_u32(v_v1));
21481 v_sum2 = vpadd_u32(vget_low_u32(v_v2), vget_high_u32(v_v2));
21482 v_sum12 = vpadd_u32(v_sum1, v_sum2);
21483 v_s1 += vget_lane_u32(v_sum12, 0);
21484 v_s2 += vget_lane_u32(v_sum12, 1);
21485 v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551584u);
21486 if (v_tail_index < ((uint64_t)(a_x.len))) {
21487 {
21488 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index);
21489 v_p.ptr = i_slice_p.ptr;
21490 v_p.len = 1;
21491 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
21492 while (v_p.ptr < i_end0_p) {
21493 v_s1 += ((uint32_t)(v_p.ptr[0]));
21494 v_s2 += v_s1;
21495 v_p.ptr += 1;
21496 }
21497 v_p.len = 0;
21498 }
21499 }
21500 v_s1 %= 65521;
21501 v_s2 %= 65521;
21502 a_x = v_remaining;
21503 }
21504 self->private_impl.f_state = (((v_s2 & 65535) << 16) | (v_s1 & 65535));
21505 return wuffs_base__make_empty_struct();
21506}
21507#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
21508// ‼ WUFFS MULTI-FILE SECTION -arm_neon
21509
21510// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
21511// -------- func adler32.hasher.up_x86_sse42
21512
Nigel Tao7804ffe2021-10-07 21:58:26 +110021513#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021514WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
21515static wuffs_base__empty_struct
21516wuffs_adler32__hasher__up_x86_sse42(
21517 wuffs_adler32__hasher* self,
21518 wuffs_base__slice_u8 a_x) {
21519 uint32_t v_s1 = 0;
21520 uint32_t v_s2 = 0;
21521 wuffs_base__slice_u8 v_remaining = {0};
21522 wuffs_base__slice_u8 v_p = {0};
21523 __m128i v_zeroes = {0};
21524 __m128i v_ones = {0};
21525 __m128i v_weights__left = {0};
21526 __m128i v_weights_right = {0};
Nigel Tao5571bfe2021-06-24 22:44:29 +100021527 __m128i v_q__left = {0};
21528 __m128i v_q_right = {0};
Nigel Taoe360a532021-04-05 22:47:03 +100021529 __m128i v_v1 = {0};
21530 __m128i v_v2 = {0};
21531 __m128i v_v2j = {0};
21532 __m128i v_v2k = {0};
21533 uint32_t v_num_iterate_bytes = 0;
21534 uint64_t v_tail_index = 0;
21535
21536 v_zeroes = _mm_set1_epi16((int16_t)(0));
21537 v_ones = _mm_set1_epi16((int16_t)(1));
21538 v_weights__left = _mm_set_epi8((int8_t)(17), (int8_t)(18), (int8_t)(19), (int8_t)(20), (int8_t)(21), (int8_t)(22), (int8_t)(23), (int8_t)(24), (int8_t)(25), (int8_t)(26), (int8_t)(27), (int8_t)(28), (int8_t)(29), (int8_t)(30), (int8_t)(31), (int8_t)(32));
21539 v_weights_right = _mm_set_epi8((int8_t)(1), (int8_t)(2), (int8_t)(3), (int8_t)(4), (int8_t)(5), (int8_t)(6), (int8_t)(7), (int8_t)(8), (int8_t)(9), (int8_t)(10), (int8_t)(11), (int8_t)(12), (int8_t)(13), (int8_t)(14), (int8_t)(15), (int8_t)(16));
21540 v_s1 = ((self->private_impl.f_state) & 0xFFFF);
21541 v_s2 = ((self->private_impl.f_state) >> (32 - (16)));
21542 while (((uint64_t)(a_x.len)) > 0) {
21543 v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0);
21544 if (((uint64_t)(a_x.len)) > 5536) {
21545 v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5536);
21546 a_x = wuffs_base__slice_u8__subslice_j(a_x, 5536);
21547 }
21548 v_num_iterate_bytes = ((uint32_t)((((uint64_t)(a_x.len)) & 4294967264)));
21549 v_s2 += ((uint32_t)(v_s1 * v_num_iterate_bytes));
21550 v_v1 = _mm_setzero_si128();
21551 v_v2j = _mm_setzero_si128();
21552 v_v2k = _mm_setzero_si128();
21553 {
21554 wuffs_base__slice_u8 i_slice_p = a_x;
21555 v_p.ptr = i_slice_p.ptr;
21556 v_p.len = 32;
21557 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32);
21558 while (v_p.ptr < i_end0_p) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100021559 v_q__left = _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr));
21560 v_q_right = _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16));
Nigel Taoe360a532021-04-05 22:47:03 +100021561 v_v2j = _mm_add_epi32(v_v2j, v_v1);
Nigel Tao5571bfe2021-06-24 22:44:29 +100021562 v_v1 = _mm_add_epi32(v_v1, _mm_sad_epu8(v_q__left, v_zeroes));
21563 v_v1 = _mm_add_epi32(v_v1, _mm_sad_epu8(v_q_right, v_zeroes));
21564 v_v2k = _mm_add_epi32(v_v2k, _mm_madd_epi16(v_ones, _mm_maddubs_epi16(v_q__left, v_weights__left)));
21565 v_v2k = _mm_add_epi32(v_v2k, _mm_madd_epi16(v_ones, _mm_maddubs_epi16(v_q_right, v_weights_right)));
Nigel Taoe360a532021-04-05 22:47:03 +100021566 v_p.ptr += 32;
21567 }
21568 v_p.len = 0;
21569 }
21570 v_v1 = _mm_add_epi32(v_v1, _mm_shuffle_epi32(v_v1, (int32_t)(177)));
21571 v_v1 = _mm_add_epi32(v_v1, _mm_shuffle_epi32(v_v1, (int32_t)(78)));
21572 v_s1 += ((uint32_t)(_mm_cvtsi128_si32(v_v1)));
21573 v_v2 = _mm_add_epi32(v_v2k, _mm_slli_epi32(v_v2j, (int32_t)(5)));
21574 v_v2 = _mm_add_epi32(v_v2, _mm_shuffle_epi32(v_v2, (int32_t)(177)));
21575 v_v2 = _mm_add_epi32(v_v2, _mm_shuffle_epi32(v_v2, (int32_t)(78)));
21576 v_s2 += ((uint32_t)(_mm_cvtsi128_si32(v_v2)));
21577 v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551584u);
21578 if (v_tail_index < ((uint64_t)(a_x.len))) {
21579 {
21580 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index);
21581 v_p.ptr = i_slice_p.ptr;
21582 v_p.len = 1;
21583 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
21584 while (v_p.ptr < i_end0_p) {
21585 v_s1 += ((uint32_t)(v_p.ptr[0]));
21586 v_s2 += v_s1;
21587 v_p.ptr += 1;
21588 }
21589 v_p.len = 0;
21590 }
21591 }
21592 v_s1 %= 65521;
21593 v_s2 %= 65521;
21594 a_x = v_remaining;
21595 }
21596 self->private_impl.f_state = (((v_s2 & 65535) << 16) | (v_s1 & 65535));
21597 return wuffs_base__make_empty_struct();
21598}
Nigel Tao7804ffe2021-10-07 21:58:26 +110021599#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021600// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
21601
21602#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32)
21603
21604#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP)
21605
21606// ---------------- Status Codes Implementations
21607
21608const char wuffs_bmp__error__bad_header[] = "#bmp: bad header";
21609const char wuffs_bmp__error__bad_rle_compression[] = "#bmp: bad RLE compression";
21610const char wuffs_bmp__error__unsupported_bmp_file[] = "#bmp: unsupported BMP file";
21611const char wuffs_bmp__note__internal_note_short_read[] = "@bmp: internal note: short read";
21612
21613// ---------------- Private Consts
21614
21615#define WUFFS_BMP__COMPRESSION_NONE 0
21616
21617#define WUFFS_BMP__COMPRESSION_RLE8 1
21618
21619#define WUFFS_BMP__COMPRESSION_RLE4 2
21620
21621#define WUFFS_BMP__COMPRESSION_BITFIELDS 3
21622
21623#define WUFFS_BMP__COMPRESSION_JPEG 4
21624
21625#define WUFFS_BMP__COMPRESSION_PNG 5
21626
21627#define WUFFS_BMP__COMPRESSION_ALPHABITFIELDS 6
21628
21629#define WUFFS_BMP__COMPRESSION_LOW_BIT_DEPTH 256
21630
21631#define WUFFS_BMP__RLE_STATE_NEUTRAL 0
21632
21633#define WUFFS_BMP__RLE_STATE_RUN 1
21634
21635#define WUFFS_BMP__RLE_STATE_ESCAPE 2
21636
21637#define WUFFS_BMP__RLE_STATE_LITERAL 3
21638
21639#define WUFFS_BMP__RLE_STATE_DELTA_X 4
21640
21641#define WUFFS_BMP__RLE_STATE_DELTA_Y 5
21642
21643// ---------------- Private Initializer Prototypes
21644
21645// ---------------- Private Function Prototypes
21646
21647static wuffs_base__status
21648wuffs_bmp__decoder__swizzle_none(
21649 wuffs_bmp__decoder* self,
21650 wuffs_base__pixel_buffer* a_dst,
21651 wuffs_base__io_buffer* a_src);
21652
21653static wuffs_base__status
21654wuffs_bmp__decoder__swizzle_rle(
21655 wuffs_bmp__decoder* self,
21656 wuffs_base__pixel_buffer* a_dst,
21657 wuffs_base__io_buffer* a_src);
21658
21659static wuffs_base__status
21660wuffs_bmp__decoder__swizzle_bitfields(
21661 wuffs_bmp__decoder* self,
21662 wuffs_base__pixel_buffer* a_dst,
21663 wuffs_base__io_buffer* a_src);
21664
21665static wuffs_base__status
21666wuffs_bmp__decoder__swizzle_low_bit_depth(
21667 wuffs_bmp__decoder* self,
21668 wuffs_base__pixel_buffer* a_dst,
21669 wuffs_base__io_buffer* a_src);
21670
21671static wuffs_base__status
21672wuffs_bmp__decoder__read_palette(
21673 wuffs_bmp__decoder* self,
21674 wuffs_base__io_buffer* a_src);
21675
21676static wuffs_base__status
21677wuffs_bmp__decoder__process_masks(
21678 wuffs_bmp__decoder* self);
21679
21680// ---------------- VTables
21681
21682const wuffs_base__image_decoder__func_ptrs
21683wuffs_bmp__decoder__func_ptrs_for__wuffs_base__image_decoder = {
21684 (wuffs_base__status(*)(void*,
21685 wuffs_base__pixel_buffer*,
21686 wuffs_base__io_buffer*,
21687 wuffs_base__pixel_blend,
21688 wuffs_base__slice_u8,
21689 wuffs_base__decode_frame_options*))(&wuffs_bmp__decoder__decode_frame),
21690 (wuffs_base__status(*)(void*,
21691 wuffs_base__frame_config*,
21692 wuffs_base__io_buffer*))(&wuffs_bmp__decoder__decode_frame_config),
21693 (wuffs_base__status(*)(void*,
21694 wuffs_base__image_config*,
21695 wuffs_base__io_buffer*))(&wuffs_bmp__decoder__decode_image_config),
21696 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_bmp__decoder__frame_dirty_rect),
21697 (uint32_t(*)(const void*))(&wuffs_bmp__decoder__num_animation_loops),
21698 (uint64_t(*)(const void*))(&wuffs_bmp__decoder__num_decoded_frame_configs),
21699 (uint64_t(*)(const void*))(&wuffs_bmp__decoder__num_decoded_frames),
21700 (wuffs_base__status(*)(void*,
21701 uint64_t,
21702 uint64_t))(&wuffs_bmp__decoder__restart_frame),
21703 (wuffs_base__empty_struct(*)(void*,
21704 uint32_t,
21705 bool))(&wuffs_bmp__decoder__set_quirk_enabled),
21706 (wuffs_base__empty_struct(*)(void*,
21707 uint32_t,
21708 bool))(&wuffs_bmp__decoder__set_report_metadata),
21709 (wuffs_base__status(*)(void*,
21710 wuffs_base__io_buffer*,
21711 wuffs_base__more_information*,
21712 wuffs_base__io_buffer*))(&wuffs_bmp__decoder__tell_me_more),
21713 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_bmp__decoder__workbuf_len),
21714};
21715
21716// ---------------- Initializer Implementations
21717
21718wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
21719wuffs_bmp__decoder__initialize(
21720 wuffs_bmp__decoder* self,
21721 size_t sizeof_star_self,
21722 uint64_t wuffs_version,
21723 uint32_t options){
21724 if (!self) {
21725 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
21726 }
21727 if (sizeof(*self) != sizeof_star_self) {
21728 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
21729 }
21730 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
21731 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
21732 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
21733 }
21734
21735 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
21736 // The whole point of this if-check is to detect an uninitialized *self.
21737 // We disable the warning on GCC. Clang-5.0 does not have this warning.
21738#if !defined(__clang__) && defined(__GNUC__)
21739#pragma GCC diagnostic push
21740#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
21741#endif
21742 if (self->private_impl.magic != 0) {
21743 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
21744 }
21745#if !defined(__clang__) && defined(__GNUC__)
21746#pragma GCC diagnostic pop
21747#endif
21748 } else {
21749 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
21750 memset(self, 0, sizeof(*self));
21751 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
21752 } else {
21753 memset(&(self->private_impl), 0, sizeof(self->private_impl));
21754 }
21755 }
21756
21757 self->private_impl.magic = WUFFS_BASE__MAGIC;
21758 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
21759 wuffs_base__image_decoder__vtable_name;
21760 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
21761 (const void*)(&wuffs_bmp__decoder__func_ptrs_for__wuffs_base__image_decoder);
21762 return wuffs_base__make_status(NULL);
21763}
21764
21765wuffs_bmp__decoder*
21766wuffs_bmp__decoder__alloc() {
21767 wuffs_bmp__decoder* x =
21768 (wuffs_bmp__decoder*)(calloc(sizeof(wuffs_bmp__decoder), 1));
21769 if (!x) {
21770 return NULL;
21771 }
21772 if (wuffs_bmp__decoder__initialize(
21773 x, sizeof(wuffs_bmp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
21774 free(x);
21775 return NULL;
21776 }
21777 return x;
21778}
21779
21780size_t
21781sizeof__wuffs_bmp__decoder() {
21782 return sizeof(wuffs_bmp__decoder);
21783}
21784
21785// ---------------- Function Implementations
21786
21787// -------- func bmp.decoder.set_quirk_enabled
21788
21789WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
21790wuffs_bmp__decoder__set_quirk_enabled(
21791 wuffs_bmp__decoder* self,
21792 uint32_t a_quirk,
21793 bool a_enabled) {
21794 return wuffs_base__make_empty_struct();
21795}
21796
21797// -------- func bmp.decoder.decode_image_config
21798
21799WUFFS_BASE__MAYBE_STATIC wuffs_base__status
21800wuffs_bmp__decoder__decode_image_config(
21801 wuffs_bmp__decoder* self,
21802 wuffs_base__image_config* a_dst,
21803 wuffs_base__io_buffer* a_src) {
21804 if (!self) {
21805 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
21806 }
21807 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
21808 return wuffs_base__make_status(
21809 (self->private_impl.magic == WUFFS_BASE__DISABLED)
21810 ? wuffs_base__error__disabled_by_previous_error
21811 : wuffs_base__error__initialize_not_called);
21812 }
21813 if (!a_src) {
21814 self->private_impl.magic = WUFFS_BASE__DISABLED;
21815 return wuffs_base__make_status(wuffs_base__error__bad_argument);
21816 }
21817 if ((self->private_impl.active_coroutine != 0) &&
21818 (self->private_impl.active_coroutine != 1)) {
21819 self->private_impl.magic = WUFFS_BASE__DISABLED;
21820 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
21821 }
21822 self->private_impl.active_coroutine = 0;
21823 wuffs_base__status status = wuffs_base__make_status(NULL);
21824
21825 uint32_t v_magic = 0;
21826 uint32_t v_width = 0;
21827 uint32_t v_height = 0;
21828 uint32_t v_planes = 0;
21829 uint32_t v_dst_pixfmt = 0;
21830 uint32_t v_byte_width = 0;
21831
21832 const uint8_t* iop_a_src = NULL;
21833 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
21834 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
21835 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
21836 if (a_src) {
21837 io0_a_src = a_src->data.ptr;
21838 io1_a_src = io0_a_src + a_src->meta.ri;
21839 iop_a_src = io1_a_src;
21840 io2_a_src = io0_a_src + a_src->meta.wi;
21841 }
21842
21843 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
21844 switch (coro_susp_point) {
21845 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
21846
21847 if ((self->private_impl.f_call_sequence != 0) || (self->private_impl.f_io_redirect_fourcc == 1)) {
21848 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
21849 goto exit;
21850 } else if (self->private_impl.f_io_redirect_fourcc != 0) {
21851 status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
21852 goto ok;
21853 }
21854 {
21855 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
21856 uint32_t t_0;
21857 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
21858 t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
21859 iop_a_src += 2;
21860 } else {
21861 self->private_data.s_decode_image_config[0].scratch = 0;
21862 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
21863 while (true) {
21864 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
21865 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
21866 goto suspend;
21867 }
21868 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
21869 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
21870 *scratch <<= 8;
21871 *scratch >>= 8;
21872 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
21873 if (num_bits_0 == 8) {
21874 t_0 = ((uint32_t)(*scratch));
21875 break;
21876 }
21877 num_bits_0 += 8;
21878 *scratch |= ((uint64_t)(num_bits_0)) << 56;
21879 }
21880 }
21881 v_magic = t_0;
21882 }
21883 if (v_magic != 19778) {
21884 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
21885 goto exit;
21886 }
21887 self->private_data.s_decode_image_config[0].scratch = 8;
21888 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
21889 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
21890 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
21891 iop_a_src = io2_a_src;
21892 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
21893 goto suspend;
21894 }
21895 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
21896 {
21897 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
21898 uint32_t t_1;
21899 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
21900 t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
21901 iop_a_src += 4;
21902 } else {
21903 self->private_data.s_decode_image_config[0].scratch = 0;
21904 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
21905 while (true) {
21906 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
21907 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
21908 goto suspend;
21909 }
21910 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
21911 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
21912 *scratch <<= 8;
21913 *scratch >>= 8;
21914 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
21915 if (num_bits_1 == 24) {
21916 t_1 = ((uint32_t)(*scratch));
21917 break;
21918 }
21919 num_bits_1 += 8;
21920 *scratch |= ((uint64_t)(num_bits_1)) << 56;
21921 }
21922 }
21923 self->private_impl.f_padding = t_1;
21924 }
21925 if (self->private_impl.f_padding < 14) {
21926 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
21927 goto exit;
21928 }
21929 self->private_impl.f_padding -= 14;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100021930 self->private_impl.f_io_redirect_pos = wuffs_base__u64__sat_add(((uint64_t)(self->private_impl.f_padding)), wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))));
Nigel Taoe360a532021-04-05 22:47:03 +100021931 {
21932 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
21933 uint32_t t_2;
21934 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
21935 t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
21936 iop_a_src += 4;
21937 } else {
21938 self->private_data.s_decode_image_config[0].scratch = 0;
21939 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
21940 while (true) {
21941 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
21942 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
21943 goto suspend;
21944 }
21945 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
21946 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
21947 *scratch <<= 8;
21948 *scratch >>= 8;
21949 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
21950 if (num_bits_2 == 24) {
21951 t_2 = ((uint32_t)(*scratch));
21952 break;
21953 }
21954 num_bits_2 += 8;
21955 *scratch |= ((uint64_t)(num_bits_2)) << 56;
21956 }
21957 }
21958 self->private_impl.f_bitmap_info_len = t_2;
21959 }
21960 if (self->private_impl.f_padding < self->private_impl.f_bitmap_info_len) {
21961 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
21962 goto exit;
21963 }
21964 self->private_impl.f_padding -= self->private_impl.f_bitmap_info_len;
21965 if (self->private_impl.f_bitmap_info_len == 12) {
21966 {
21967 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
21968 uint32_t t_3;
21969 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
21970 t_3 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
21971 iop_a_src += 2;
21972 } else {
21973 self->private_data.s_decode_image_config[0].scratch = 0;
21974 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
21975 while (true) {
21976 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
21977 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
21978 goto suspend;
21979 }
21980 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
21981 uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
21982 *scratch <<= 8;
21983 *scratch >>= 8;
21984 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
21985 if (num_bits_3 == 8) {
21986 t_3 = ((uint32_t)(*scratch));
21987 break;
21988 }
21989 num_bits_3 += 8;
21990 *scratch |= ((uint64_t)(num_bits_3)) << 56;
21991 }
21992 }
21993 self->private_impl.f_width = t_3;
21994 }
21995 {
21996 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
21997 uint32_t t_4;
21998 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
21999 t_4 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22000 iop_a_src += 2;
22001 } else {
22002 self->private_data.s_decode_image_config[0].scratch = 0;
22003 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
22004 while (true) {
22005 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22006 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22007 goto suspend;
22008 }
22009 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22010 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
22011 *scratch <<= 8;
22012 *scratch >>= 8;
22013 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
22014 if (num_bits_4 == 8) {
22015 t_4 = ((uint32_t)(*scratch));
22016 break;
22017 }
22018 num_bits_4 += 8;
22019 *scratch |= ((uint64_t)(num_bits_4)) << 56;
22020 }
22021 }
22022 self->private_impl.f_height = t_4;
22023 }
22024 {
22025 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
22026 uint32_t t_5;
22027 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22028 t_5 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22029 iop_a_src += 2;
22030 } else {
22031 self->private_data.s_decode_image_config[0].scratch = 0;
22032 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
22033 while (true) {
22034 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22035 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22036 goto suspend;
22037 }
22038 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22039 uint32_t num_bits_5 = ((uint32_t)(*scratch >> 56));
22040 *scratch <<= 8;
22041 *scratch >>= 8;
22042 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_5;
22043 if (num_bits_5 == 8) {
22044 t_5 = ((uint32_t)(*scratch));
22045 break;
22046 }
22047 num_bits_5 += 8;
22048 *scratch |= ((uint64_t)(num_bits_5)) << 56;
22049 }
22050 }
22051 v_planes = t_5;
22052 }
22053 if (v_planes != 1) {
22054 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22055 goto exit;
22056 }
22057 {
22058 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
22059 uint32_t t_6;
22060 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22061 t_6 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22062 iop_a_src += 2;
22063 } else {
22064 self->private_data.s_decode_image_config[0].scratch = 0;
22065 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
22066 while (true) {
22067 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22068 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22069 goto suspend;
22070 }
22071 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22072 uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56));
22073 *scratch <<= 8;
22074 *scratch >>= 8;
22075 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6;
22076 if (num_bits_6 == 8) {
22077 t_6 = ((uint32_t)(*scratch));
22078 break;
22079 }
22080 num_bits_6 += 8;
22081 *scratch |= ((uint64_t)(num_bits_6)) << 56;
22082 }
22083 }
22084 self->private_impl.f_bits_per_pixel = t_6;
22085 }
22086 } else if (self->private_impl.f_bitmap_info_len == 16) {
22087 {
22088 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
22089 uint32_t t_7;
22090 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22091 t_7 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22092 iop_a_src += 4;
22093 } else {
22094 self->private_data.s_decode_image_config[0].scratch = 0;
22095 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17);
22096 while (true) {
22097 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22098 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22099 goto suspend;
22100 }
22101 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22102 uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56));
22103 *scratch <<= 8;
22104 *scratch >>= 8;
22105 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7;
22106 if (num_bits_7 == 24) {
22107 t_7 = ((uint32_t)(*scratch));
22108 break;
22109 }
22110 num_bits_7 += 8;
22111 *scratch |= ((uint64_t)(num_bits_7)) << 56;
22112 }
22113 }
22114 v_width = t_7;
22115 }
22116 if (v_width >= 2147483648) {
22117 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
22118 goto exit;
22119 }
22120 self->private_impl.f_width = v_width;
22121 {
22122 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18);
22123 uint32_t t_8;
22124 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22125 t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22126 iop_a_src += 4;
22127 } else {
22128 self->private_data.s_decode_image_config[0].scratch = 0;
22129 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19);
22130 while (true) {
22131 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22132 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22133 goto suspend;
22134 }
22135 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22136 uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56));
22137 *scratch <<= 8;
22138 *scratch >>= 8;
22139 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8;
22140 if (num_bits_8 == 24) {
22141 t_8 = ((uint32_t)(*scratch));
22142 break;
22143 }
22144 num_bits_8 += 8;
22145 *scratch |= ((uint64_t)(num_bits_8)) << 56;
22146 }
22147 }
22148 v_height = t_8;
22149 }
22150 if (v_height >= 2147483648) {
22151 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
22152 goto exit;
22153 }
22154 self->private_impl.f_height = v_height;
22155 {
22156 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20);
22157 uint32_t t_9;
22158 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22159 t_9 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22160 iop_a_src += 2;
22161 } else {
22162 self->private_data.s_decode_image_config[0].scratch = 0;
22163 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21);
22164 while (true) {
22165 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22166 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22167 goto suspend;
22168 }
22169 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22170 uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56));
22171 *scratch <<= 8;
22172 *scratch >>= 8;
22173 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9;
22174 if (num_bits_9 == 8) {
22175 t_9 = ((uint32_t)(*scratch));
22176 break;
22177 }
22178 num_bits_9 += 8;
22179 *scratch |= ((uint64_t)(num_bits_9)) << 56;
22180 }
22181 }
22182 v_planes = t_9;
22183 }
22184 if (v_planes != 1) {
22185 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22186 goto exit;
22187 }
22188 {
22189 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
22190 uint32_t t_10;
22191 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22192 t_10 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22193 iop_a_src += 2;
22194 } else {
22195 self->private_data.s_decode_image_config[0].scratch = 0;
22196 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
22197 while (true) {
22198 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22199 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22200 goto suspend;
22201 }
22202 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22203 uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56));
22204 *scratch <<= 8;
22205 *scratch >>= 8;
22206 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10;
22207 if (num_bits_10 == 8) {
22208 t_10 = ((uint32_t)(*scratch));
22209 break;
22210 }
22211 num_bits_10 += 8;
22212 *scratch |= ((uint64_t)(num_bits_10)) << 56;
22213 }
22214 }
22215 self->private_impl.f_bits_per_pixel = t_10;
22216 }
22217 } else {
22218 {
22219 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
22220 uint32_t t_11;
22221 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22222 t_11 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22223 iop_a_src += 4;
22224 } else {
22225 self->private_data.s_decode_image_config[0].scratch = 0;
22226 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(25);
22227 while (true) {
22228 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22229 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22230 goto suspend;
22231 }
22232 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22233 uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56));
22234 *scratch <<= 8;
22235 *scratch >>= 8;
22236 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11;
22237 if (num_bits_11 == 24) {
22238 t_11 = ((uint32_t)(*scratch));
22239 break;
22240 }
22241 num_bits_11 += 8;
22242 *scratch |= ((uint64_t)(num_bits_11)) << 56;
22243 }
22244 }
22245 v_width = t_11;
22246 }
22247 if (v_width >= 2147483648) {
22248 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
22249 goto exit;
22250 }
22251 self->private_impl.f_width = v_width;
22252 {
22253 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(26);
22254 uint32_t t_12;
22255 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22256 t_12 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22257 iop_a_src += 4;
22258 } else {
22259 self->private_data.s_decode_image_config[0].scratch = 0;
22260 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(27);
22261 while (true) {
22262 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22263 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22264 goto suspend;
22265 }
22266 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22267 uint32_t num_bits_12 = ((uint32_t)(*scratch >> 56));
22268 *scratch <<= 8;
22269 *scratch >>= 8;
22270 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_12;
22271 if (num_bits_12 == 24) {
22272 t_12 = ((uint32_t)(*scratch));
22273 break;
22274 }
22275 num_bits_12 += 8;
22276 *scratch |= ((uint64_t)(num_bits_12)) << 56;
22277 }
22278 }
22279 v_height = t_12;
22280 }
22281 if (v_height == 2147483648) {
22282 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
22283 goto exit;
22284 } else if (v_height >= 2147483648) {
22285 self->private_impl.f_height = (((uint32_t)(0 - v_height)) & 2147483647);
22286 self->private_impl.f_top_down = true;
22287 } else {
22288 self->private_impl.f_height = v_height;
22289 }
22290 {
22291 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(28);
22292 uint32_t t_13;
22293 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22294 t_13 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22295 iop_a_src += 2;
22296 } else {
22297 self->private_data.s_decode_image_config[0].scratch = 0;
22298 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(29);
22299 while (true) {
22300 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22301 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22302 goto suspend;
22303 }
22304 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22305 uint32_t num_bits_13 = ((uint32_t)(*scratch >> 56));
22306 *scratch <<= 8;
22307 *scratch >>= 8;
22308 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_13;
22309 if (num_bits_13 == 8) {
22310 t_13 = ((uint32_t)(*scratch));
22311 break;
22312 }
22313 num_bits_13 += 8;
22314 *scratch |= ((uint64_t)(num_bits_13)) << 56;
22315 }
22316 }
22317 v_planes = t_13;
22318 }
22319 if (v_planes != 1) {
22320 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22321 goto exit;
22322 }
22323 {
22324 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(30);
22325 uint32_t t_14;
22326 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22327 t_14 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22328 iop_a_src += 2;
22329 } else {
22330 self->private_data.s_decode_image_config[0].scratch = 0;
22331 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(31);
22332 while (true) {
22333 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22334 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22335 goto suspend;
22336 }
22337 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22338 uint32_t num_bits_14 = ((uint32_t)(*scratch >> 56));
22339 *scratch <<= 8;
22340 *scratch >>= 8;
22341 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_14;
22342 if (num_bits_14 == 8) {
22343 t_14 = ((uint32_t)(*scratch));
22344 break;
22345 }
22346 num_bits_14 += 8;
22347 *scratch |= ((uint64_t)(num_bits_14)) << 56;
22348 }
22349 }
22350 self->private_impl.f_bits_per_pixel = t_14;
22351 }
22352 {
22353 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(32);
22354 uint32_t t_15;
22355 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22356 t_15 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22357 iop_a_src += 4;
22358 } else {
22359 self->private_data.s_decode_image_config[0].scratch = 0;
22360 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(33);
22361 while (true) {
22362 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22363 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22364 goto suspend;
22365 }
22366 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22367 uint32_t num_bits_15 = ((uint32_t)(*scratch >> 56));
22368 *scratch <<= 8;
22369 *scratch >>= 8;
22370 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_15;
22371 if (num_bits_15 == 24) {
22372 t_15 = ((uint32_t)(*scratch));
22373 break;
22374 }
22375 num_bits_15 += 8;
22376 *scratch |= ((uint64_t)(num_bits_15)) << 56;
22377 }
22378 }
22379 self->private_impl.f_compression = t_15;
22380 }
22381 if (self->private_impl.f_bits_per_pixel == 0) {
22382 if (self->private_impl.f_compression == 4) {
22383 self->private_impl.f_io_redirect_fourcc = 1246774599;
22384 status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
22385 goto ok;
22386 } else if (self->private_impl.f_compression == 5) {
22387 self->private_impl.f_io_redirect_fourcc = 1347307296;
22388 status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
22389 goto ok;
22390 }
22391 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22392 goto exit;
22393 }
22394 self->private_data.s_decode_image_config[0].scratch = 20;
22395 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(34);
22396 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
22397 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
22398 iop_a_src = io2_a_src;
22399 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22400 goto suspend;
22401 }
22402 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
22403 if (self->private_impl.f_bitmap_info_len == 40) {
22404 if (self->private_impl.f_bits_per_pixel >= 16) {
22405 if (self->private_impl.f_padding >= 16) {
22406 self->private_impl.f_bitmap_info_len = 56;
22407 self->private_impl.f_padding -= 16;
22408 } else if (self->private_impl.f_padding >= 12) {
22409 self->private_impl.f_bitmap_info_len = 52;
22410 self->private_impl.f_padding -= 12;
22411 }
22412 }
22413 } else if ((self->private_impl.f_bitmap_info_len != 52) &&
22414 (self->private_impl.f_bitmap_info_len != 56) &&
22415 (self->private_impl.f_bitmap_info_len != 64) &&
22416 (self->private_impl.f_bitmap_info_len != 108) &&
22417 (self->private_impl.f_bitmap_info_len != 124)) {
22418 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22419 goto exit;
22420 }
22421 if (self->private_impl.f_compression == 6) {
22422 self->private_impl.f_compression = 3;
22423 }
22424 if (self->private_impl.f_compression == 3) {
22425 if (self->private_impl.f_bitmap_info_len >= 52) {
22426 {
22427 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(35);
22428 uint32_t t_16;
22429 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22430 t_16 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22431 iop_a_src += 4;
22432 } else {
22433 self->private_data.s_decode_image_config[0].scratch = 0;
22434 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(36);
22435 while (true) {
22436 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22437 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22438 goto suspend;
22439 }
22440 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22441 uint32_t num_bits_16 = ((uint32_t)(*scratch >> 56));
22442 *scratch <<= 8;
22443 *scratch >>= 8;
22444 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_16;
22445 if (num_bits_16 == 24) {
22446 t_16 = ((uint32_t)(*scratch));
22447 break;
22448 }
22449 num_bits_16 += 8;
22450 *scratch |= ((uint64_t)(num_bits_16)) << 56;
22451 }
22452 }
22453 self->private_impl.f_channel_masks[2] = t_16;
22454 }
22455 {
22456 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(37);
22457 uint32_t t_17;
22458 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22459 t_17 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22460 iop_a_src += 4;
22461 } else {
22462 self->private_data.s_decode_image_config[0].scratch = 0;
22463 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(38);
22464 while (true) {
22465 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22466 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22467 goto suspend;
22468 }
22469 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22470 uint32_t num_bits_17 = ((uint32_t)(*scratch >> 56));
22471 *scratch <<= 8;
22472 *scratch >>= 8;
22473 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_17;
22474 if (num_bits_17 == 24) {
22475 t_17 = ((uint32_t)(*scratch));
22476 break;
22477 }
22478 num_bits_17 += 8;
22479 *scratch |= ((uint64_t)(num_bits_17)) << 56;
22480 }
22481 }
22482 self->private_impl.f_channel_masks[1] = t_17;
22483 }
22484 {
22485 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(39);
22486 uint32_t t_18;
22487 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22488 t_18 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22489 iop_a_src += 4;
22490 } else {
22491 self->private_data.s_decode_image_config[0].scratch = 0;
22492 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(40);
22493 while (true) {
22494 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22495 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22496 goto suspend;
22497 }
22498 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22499 uint32_t num_bits_18 = ((uint32_t)(*scratch >> 56));
22500 *scratch <<= 8;
22501 *scratch >>= 8;
22502 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_18;
22503 if (num_bits_18 == 24) {
22504 t_18 = ((uint32_t)(*scratch));
22505 break;
22506 }
22507 num_bits_18 += 8;
22508 *scratch |= ((uint64_t)(num_bits_18)) << 56;
22509 }
22510 }
22511 self->private_impl.f_channel_masks[0] = t_18;
22512 }
22513 if (self->private_impl.f_bitmap_info_len >= 56) {
22514 {
22515 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(41);
22516 uint32_t t_19;
22517 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22518 t_19 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22519 iop_a_src += 4;
22520 } else {
22521 self->private_data.s_decode_image_config[0].scratch = 0;
22522 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(42);
22523 while (true) {
22524 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22525 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22526 goto suspend;
22527 }
22528 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22529 uint32_t num_bits_19 = ((uint32_t)(*scratch >> 56));
22530 *scratch <<= 8;
22531 *scratch >>= 8;
22532 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_19;
22533 if (num_bits_19 == 24) {
22534 t_19 = ((uint32_t)(*scratch));
22535 break;
22536 }
22537 num_bits_19 += 8;
22538 *scratch |= ((uint64_t)(num_bits_19)) << 56;
22539 }
22540 }
22541 self->private_impl.f_channel_masks[3] = t_19;
22542 }
22543 self->private_data.s_decode_image_config[0].scratch = ((uint32_t)(self->private_impl.f_bitmap_info_len - 56));
22544 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(43);
22545 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
22546 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
22547 iop_a_src = io2_a_src;
22548 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22549 goto suspend;
22550 }
22551 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
22552 }
22553 if ((self->private_impl.f_channel_masks[0] == 255) && (self->private_impl.f_channel_masks[1] == 65280) && (self->private_impl.f_channel_masks[2] == 16711680)) {
22554 if (self->private_impl.f_bits_per_pixel == 24) {
22555 self->private_impl.f_compression = 0;
22556 } else if (self->private_impl.f_bits_per_pixel == 32) {
22557 if ((self->private_impl.f_channel_masks[3] == 0) || (self->private_impl.f_channel_masks[3] == 4278190080)) {
22558 self->private_impl.f_compression = 0;
22559 }
22560 }
22561 }
22562 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(44);
22563 status = wuffs_bmp__decoder__process_masks(self);
22564 if (status.repr) {
22565 goto suspend;
22566 }
22567 }
22568 } else if (self->private_impl.f_bitmap_info_len >= 40) {
22569 self->private_data.s_decode_image_config[0].scratch = (self->private_impl.f_bitmap_info_len - 40);
22570 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(45);
22571 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
22572 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
22573 iop_a_src = io2_a_src;
22574 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22575 goto suspend;
22576 }
22577 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
22578 } else {
22579 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22580 goto exit;
22581 }
22582 }
22583 if (self->private_impl.f_compression != 3) {
22584 if (self->private_impl.f_bits_per_pixel < 16) {
22585 if (a_src) {
22586 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22587 }
22588 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(46);
22589 status = wuffs_bmp__decoder__read_palette(self, a_src);
22590 if (a_src) {
22591 iop_a_src = a_src->data.ptr + a_src->meta.ri;
22592 }
22593 if (status.repr) {
22594 goto suspend;
22595 }
22596 }
22597 }
22598 if (self->private_impl.f_compression == 0) {
22599 if ((self->private_impl.f_bits_per_pixel == 1) || (self->private_impl.f_bits_per_pixel == 2) || (self->private_impl.f_bits_per_pixel == 4)) {
22600 self->private_impl.f_src_pixfmt = 2198077448;
22601 self->private_impl.f_compression = 256;
22602 } else if (self->private_impl.f_bits_per_pixel == 8) {
22603 self->private_impl.f_src_pixfmt = 2198077448;
22604 } else if (self->private_impl.f_bits_per_pixel == 16) {
22605 self->private_impl.f_compression = 3;
22606 self->private_impl.f_channel_masks[0] = 31;
22607 self->private_impl.f_channel_masks[1] = 992;
22608 self->private_impl.f_channel_masks[2] = 31744;
22609 self->private_impl.f_channel_masks[3] = 0;
22610 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(47);
22611 status = wuffs_bmp__decoder__process_masks(self);
22612 if (status.repr) {
22613 goto suspend;
22614 }
22615 self->private_impl.f_src_pixfmt = 2164308923;
22616 } else if (self->private_impl.f_bits_per_pixel == 24) {
22617 self->private_impl.f_src_pixfmt = 2147485832;
22618 } else if (self->private_impl.f_bits_per_pixel == 32) {
22619 if (self->private_impl.f_channel_masks[3] == 0) {
22620 self->private_impl.f_src_pixfmt = 2415954056;
22621 } else {
22622 self->private_impl.f_src_pixfmt = 2164295816;
22623 }
22624 } else {
22625 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22626 goto exit;
22627 }
22628 } else if (self->private_impl.f_compression == 1) {
22629 if (self->private_impl.f_bits_per_pixel == 8) {
22630 self->private_impl.f_src_pixfmt = 2198077448;
22631 } else {
22632 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22633 goto exit;
22634 }
22635 } else if (self->private_impl.f_compression == 2) {
22636 if (self->private_impl.f_bits_per_pixel == 4) {
22637 self->private_impl.f_src_pixfmt = 2198077448;
22638 } else {
22639 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22640 goto exit;
22641 }
22642 } else if (self->private_impl.f_compression == 3) {
22643 if ((self->private_impl.f_bits_per_pixel == 16) || (self->private_impl.f_bits_per_pixel == 32)) {
22644 self->private_impl.f_src_pixfmt = 2164308923;
22645 } else {
22646 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22647 goto exit;
22648 }
22649 } else {
22650 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22651 goto exit;
22652 }
22653 if (((self->private_impl.f_bitmap_info_len < 40) || (self->private_impl.f_bitmap_info_len == 64)) &&
22654 (self->private_impl.f_bits_per_pixel != 1) &&
22655 (self->private_impl.f_bits_per_pixel != 4) &&
22656 (self->private_impl.f_bits_per_pixel != 8) &&
22657 (self->private_impl.f_bits_per_pixel != 24)) {
22658 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
22659 goto exit;
22660 }
22661 if (self->private_impl.f_bits_per_pixel == 1) {
22662 v_byte_width = ((self->private_impl.f_width >> 3) + (((self->private_impl.f_width & 7) + 7) >> 3));
22663 self->private_impl.f_pad_per_row = ((4 - (v_byte_width & 3)) & 3);
22664 } else if (self->private_impl.f_bits_per_pixel == 2) {
22665 v_byte_width = ((self->private_impl.f_width >> 2) + (((self->private_impl.f_width & 3) + 3) >> 2));
22666 self->private_impl.f_pad_per_row = ((4 - (v_byte_width & 3)) & 3);
22667 } else if (self->private_impl.f_bits_per_pixel == 4) {
22668 v_byte_width = ((self->private_impl.f_width >> 1) + (self->private_impl.f_width & 1));
22669 self->private_impl.f_pad_per_row = ((4 - (v_byte_width & 3)) & 3);
22670 } else if (self->private_impl.f_bits_per_pixel == 8) {
22671 self->private_impl.f_pad_per_row = ((4 - (self->private_impl.f_width & 3)) & 3);
22672 } else if (self->private_impl.f_bits_per_pixel == 16) {
22673 self->private_impl.f_pad_per_row = ((self->private_impl.f_width & 1) * 2);
22674 } else if (self->private_impl.f_bits_per_pixel == 24) {
22675 self->private_impl.f_pad_per_row = (self->private_impl.f_width & 3);
22676 } else if (self->private_impl.f_bits_per_pixel == 32) {
22677 self->private_impl.f_pad_per_row = 0;
22678 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100022679 self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)));
Nigel Taoe360a532021-04-05 22:47:03 +100022680 if (a_dst != NULL) {
22681 v_dst_pixfmt = 2164295816;
22682 if ((self->private_impl.f_channel_num_bits[0] > 8) ||
22683 (self->private_impl.f_channel_num_bits[1] > 8) ||
22684 (self->private_impl.f_channel_num_bits[2] > 8) ||
22685 (self->private_impl.f_channel_num_bits[3] > 8)) {
22686 v_dst_pixfmt = 2164308923;
22687 }
22688 wuffs_base__image_config__set(
22689 a_dst,
22690 v_dst_pixfmt,
22691 0,
22692 self->private_impl.f_width,
22693 self->private_impl.f_height,
22694 self->private_impl.f_frame_config_io_position,
22695 (self->private_impl.f_channel_masks[3] == 0));
22696 }
22697 self->private_impl.f_call_sequence = 3;
22698
Nigel Taoe360a532021-04-05 22:47:03 +100022699 ok:
22700 self->private_impl.p_decode_image_config[0] = 0;
22701 goto exit;
22702 }
22703
22704 goto suspend;
22705 suspend:
22706 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
22707 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
22708
22709 goto exit;
22710 exit:
22711 if (a_src) {
22712 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22713 }
22714
22715 if (wuffs_base__status__is_error(&status)) {
22716 self->private_impl.magic = WUFFS_BASE__DISABLED;
22717 }
22718 return status;
22719}
22720
22721// -------- func bmp.decoder.decode_frame_config
22722
22723WUFFS_BASE__MAYBE_STATIC wuffs_base__status
22724wuffs_bmp__decoder__decode_frame_config(
22725 wuffs_bmp__decoder* self,
22726 wuffs_base__frame_config* a_dst,
22727 wuffs_base__io_buffer* a_src) {
22728 if (!self) {
22729 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
22730 }
22731 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
22732 return wuffs_base__make_status(
22733 (self->private_impl.magic == WUFFS_BASE__DISABLED)
22734 ? wuffs_base__error__disabled_by_previous_error
22735 : wuffs_base__error__initialize_not_called);
22736 }
22737 if (!a_src) {
22738 self->private_impl.magic = WUFFS_BASE__DISABLED;
22739 return wuffs_base__make_status(wuffs_base__error__bad_argument);
22740 }
22741 if ((self->private_impl.active_coroutine != 0) &&
22742 (self->private_impl.active_coroutine != 2)) {
22743 self->private_impl.magic = WUFFS_BASE__DISABLED;
22744 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
22745 }
22746 self->private_impl.active_coroutine = 0;
22747 wuffs_base__status status = wuffs_base__make_status(NULL);
22748
22749 const uint8_t* iop_a_src = NULL;
22750 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
22751 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
22752 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
22753 if (a_src) {
22754 io0_a_src = a_src->data.ptr;
22755 io1_a_src = io0_a_src + a_src->meta.ri;
22756 iop_a_src = io1_a_src;
22757 io2_a_src = io0_a_src + a_src->meta.wi;
22758 }
22759
22760 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
22761 switch (coro_susp_point) {
22762 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
22763
22764 if (self->private_impl.f_call_sequence < 3) {
22765 if (a_src) {
22766 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22767 }
22768 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
22769 status = wuffs_bmp__decoder__decode_image_config(self, NULL, a_src);
22770 if (a_src) {
22771 iop_a_src = a_src->data.ptr + a_src->meta.ri;
22772 }
22773 if (status.repr) {
22774 goto suspend;
22775 }
22776 } else if (self->private_impl.f_call_sequence == 3) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100022777 if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) {
Nigel Taoe360a532021-04-05 22:47:03 +100022778 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
22779 goto exit;
22780 }
22781 } else if (self->private_impl.f_call_sequence == 4) {
22782 self->private_impl.f_call_sequence = 255;
22783 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
22784 goto ok;
22785 } else {
22786 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
22787 goto ok;
22788 }
22789 if (a_dst != NULL) {
22790 wuffs_base__frame_config__set(
22791 a_dst,
22792 wuffs_base__utility__make_rect_ie_u32(
22793 0,
22794 0,
22795 self->private_impl.f_width,
22796 self->private_impl.f_height),
22797 ((wuffs_base__flicks)(0)),
22798 0,
22799 self->private_impl.f_frame_config_io_position,
22800 0,
22801 true,
22802 false,
22803 4278190080);
22804 }
22805 self->private_impl.f_call_sequence = 4;
22806
Nigel Taoe360a532021-04-05 22:47:03 +100022807 ok:
22808 self->private_impl.p_decode_frame_config[0] = 0;
22809 goto exit;
22810 }
22811
22812 goto suspend;
22813 suspend:
22814 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
22815 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
22816
22817 goto exit;
22818 exit:
22819 if (a_src) {
22820 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22821 }
22822
22823 if (wuffs_base__status__is_error(&status)) {
22824 self->private_impl.magic = WUFFS_BASE__DISABLED;
22825 }
22826 return status;
22827}
22828
22829// -------- func bmp.decoder.decode_frame
22830
22831WUFFS_BASE__MAYBE_STATIC wuffs_base__status
22832wuffs_bmp__decoder__decode_frame(
22833 wuffs_bmp__decoder* self,
22834 wuffs_base__pixel_buffer* a_dst,
22835 wuffs_base__io_buffer* a_src,
22836 wuffs_base__pixel_blend a_blend,
22837 wuffs_base__slice_u8 a_workbuf,
22838 wuffs_base__decode_frame_options* a_opts) {
22839 if (!self) {
22840 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
22841 }
22842 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
22843 return wuffs_base__make_status(
22844 (self->private_impl.magic == WUFFS_BASE__DISABLED)
22845 ? wuffs_base__error__disabled_by_previous_error
22846 : wuffs_base__error__initialize_not_called);
22847 }
22848 if (!a_dst || !a_src) {
22849 self->private_impl.magic = WUFFS_BASE__DISABLED;
22850 return wuffs_base__make_status(wuffs_base__error__bad_argument);
22851 }
22852 if ((self->private_impl.active_coroutine != 0) &&
22853 (self->private_impl.active_coroutine != 3)) {
22854 self->private_impl.magic = WUFFS_BASE__DISABLED;
22855 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
22856 }
22857 self->private_impl.active_coroutine = 0;
22858 wuffs_base__status status = wuffs_base__make_status(NULL);
22859
22860 wuffs_base__status v_status = wuffs_base__make_status(NULL);
22861
22862 const uint8_t* iop_a_src = NULL;
22863 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
22864 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
22865 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
22866 if (a_src) {
22867 io0_a_src = a_src->data.ptr;
22868 io1_a_src = io0_a_src + a_src->meta.ri;
22869 iop_a_src = io1_a_src;
22870 io2_a_src = io0_a_src + a_src->meta.wi;
22871 }
22872
22873 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
22874 if (coro_susp_point) {
22875 v_status = self->private_data.s_decode_frame[0].v_status;
22876 }
22877 switch (coro_susp_point) {
22878 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
22879
22880 if (self->private_impl.f_call_sequence < 4) {
22881 if (a_src) {
22882 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22883 }
22884 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
22885 status = wuffs_bmp__decoder__decode_frame_config(self, NULL, a_src);
22886 if (a_src) {
22887 iop_a_src = a_src->data.ptr + a_src->meta.ri;
22888 }
22889 if (status.repr) {
22890 goto suspend;
22891 }
22892 } else if (self->private_impl.f_call_sequence == 4) {
22893 } else {
22894 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
22895 goto ok;
22896 }
22897 self->private_data.s_decode_frame[0].scratch = self->private_impl.f_padding;
22898 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
22899 if (self->private_data.s_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
22900 self->private_data.s_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
22901 iop_a_src = io2_a_src;
22902 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22903 goto suspend;
22904 }
22905 iop_a_src += self->private_data.s_decode_frame[0].scratch;
22906 if ((self->private_impl.f_width > 0) && (self->private_impl.f_height > 0)) {
22907 self->private_impl.f_dst_x = 0;
22908 if (self->private_impl.f_top_down) {
22909 self->private_impl.f_dst_y = 0;
22910 self->private_impl.f_dst_y_inc = 1;
22911 } else {
22912 self->private_impl.f_dst_y = ((uint32_t)(self->private_impl.f_height - 1));
22913 self->private_impl.f_dst_y_inc = 4294967295;
22914 }
22915 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
22916 wuffs_base__pixel_buffer__pixel_format(a_dst),
22917 wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8((self->private_data.f_scratch) + 1024, 1024)),
22918 wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt),
22919 wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024),
22920 a_blend);
22921 if ( ! wuffs_base__status__is_ok(&v_status)) {
22922 status = v_status;
22923 if (wuffs_base__status__is_error(&status)) {
22924 goto exit;
22925 } else if (wuffs_base__status__is_suspension(&status)) {
22926 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
22927 goto exit;
22928 }
22929 goto ok;
22930 }
22931 while (true) {
22932 if (self->private_impl.f_compression == 0) {
22933 if (a_src) {
22934 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22935 }
22936 v_status = wuffs_bmp__decoder__swizzle_none(self, a_dst, a_src);
22937 if (a_src) {
22938 iop_a_src = a_src->data.ptr + a_src->meta.ri;
22939 }
22940 } else if (self->private_impl.f_compression < 3) {
22941 if (a_src) {
22942 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22943 }
22944 v_status = wuffs_bmp__decoder__swizzle_rle(self, a_dst, a_src);
22945 if (a_src) {
22946 iop_a_src = a_src->data.ptr + a_src->meta.ri;
22947 }
22948 } else if (self->private_impl.f_compression == 3) {
22949 if (a_src) {
22950 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22951 }
22952 v_status = wuffs_bmp__decoder__swizzle_bitfields(self, a_dst, a_src);
22953 if (a_src) {
22954 iop_a_src = a_src->data.ptr + a_src->meta.ri;
22955 }
22956 } else {
22957 if (a_src) {
22958 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
22959 }
22960 v_status = wuffs_bmp__decoder__swizzle_low_bit_depth(self, a_dst, a_src);
22961 if (a_src) {
22962 iop_a_src = a_src->data.ptr + a_src->meta.ri;
22963 }
22964 }
22965 if (wuffs_base__status__is_ok(&v_status)) {
22966 goto label__0__break;
22967 } else if (v_status.repr != wuffs_bmp__note__internal_note_short_read) {
22968 status = v_status;
22969 if (wuffs_base__status__is_error(&status)) {
22970 goto exit;
22971 } else if (wuffs_base__status__is_suspension(&status)) {
22972 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
22973 goto exit;
22974 }
22975 goto ok;
22976 }
22977 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22978 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
22979 }
22980 label__0__break:;
22981 self->private_data.s_decode_frame[0].scratch = self->private_impl.f_pending_pad;
22982 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
22983 if (self->private_data.s_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
22984 self->private_data.s_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
22985 iop_a_src = io2_a_src;
22986 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22987 goto suspend;
22988 }
22989 iop_a_src += self->private_data.s_decode_frame[0].scratch;
22990 self->private_impl.f_pending_pad = 0;
22991 }
22992 self->private_impl.f_call_sequence = 255;
22993
Nigel Taoe360a532021-04-05 22:47:03 +100022994 ok:
22995 self->private_impl.p_decode_frame[0] = 0;
22996 goto exit;
22997 }
22998
22999 goto suspend;
23000 suspend:
23001 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
23002 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
23003 self->private_data.s_decode_frame[0].v_status = v_status;
23004
23005 goto exit;
23006 exit:
23007 if (a_src) {
23008 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23009 }
23010
23011 if (wuffs_base__status__is_error(&status)) {
23012 self->private_impl.magic = WUFFS_BASE__DISABLED;
23013 }
23014 return status;
23015}
23016
23017// -------- func bmp.decoder.swizzle_none
23018
23019static wuffs_base__status
23020wuffs_bmp__decoder__swizzle_none(
23021 wuffs_bmp__decoder* self,
23022 wuffs_base__pixel_buffer* a_dst,
23023 wuffs_base__io_buffer* a_src) {
23024 wuffs_base__status status = wuffs_base__make_status(NULL);
23025
23026 wuffs_base__pixel_format v_dst_pixfmt = {0};
23027 uint32_t v_dst_bits_per_pixel = 0;
23028 uint64_t v_dst_bytes_per_pixel = 0;
23029 uint64_t v_dst_bytes_per_row = 0;
23030 wuffs_base__slice_u8 v_dst_palette = {0};
23031 wuffs_base__table_u8 v_tab = {0};
23032 wuffs_base__slice_u8 v_dst = {0};
23033 uint64_t v_i = 0;
23034 uint64_t v_n = 0;
23035
23036 const uint8_t* iop_a_src = NULL;
23037 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23038 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23039 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23040 if (a_src) {
23041 io0_a_src = a_src->data.ptr;
23042 io1_a_src = io0_a_src + a_src->meta.ri;
23043 iop_a_src = io1_a_src;
23044 io2_a_src = io0_a_src + a_src->meta.wi;
23045 }
23046
23047 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
23048 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
23049 if ((v_dst_bits_per_pixel & 7) != 0) {
23050 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
23051 goto exit;
23052 }
23053 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
23054 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
23055 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8((self->private_data.f_scratch) + 1024, 1024));
23056 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
23057 label__outer__continue:;
23058 while (true) {
23059 while (self->private_impl.f_pending_pad > 0) {
23060 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
23061 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
23062 goto ok;
23063 }
23064 self->private_impl.f_pending_pad -= 1;
23065 iop_a_src += 1;
23066 }
23067 label__inner__continue:;
23068 while (true) {
23069 if (self->private_impl.f_dst_x == self->private_impl.f_width) {
23070 self->private_impl.f_dst_x = 0;
23071 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
23072 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
23073 if (self->private_impl.f_height > 0) {
23074 self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row;
23075 }
23076 goto label__outer__break;
23077 } else if (self->private_impl.f_pad_per_row != 0) {
23078 self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row;
23079 goto label__outer__continue;
23080 }
23081 }
Nigel Taobf9dab32021-11-18 19:19:55 +110023082 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100023083 if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) {
23084 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row);
23085 }
23086 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
23087 if (v_i >= ((uint64_t)(v_dst.len))) {
23088 goto label__inner__continue;
23089 }
23090 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
23091 &self->private_impl.f_swizzler,
23092 wuffs_base__slice_u8__subslice_i(v_dst, v_i),
23093 v_dst_palette,
23094 &iop_a_src,
23095 io2_a_src);
23096 if (v_n == 0) {
23097 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
23098 goto ok;
23099 }
23100 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
23101 }
23102 }
23103 label__outer__break:;
23104 status = wuffs_base__make_status(NULL);
23105 goto ok;
23106
Nigel Taoe360a532021-04-05 22:47:03 +100023107 ok:
23108 goto exit;
23109 exit:
23110 if (a_src) {
23111 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23112 }
23113
23114 return status;
23115}
23116
23117// -------- func bmp.decoder.swizzle_rle
23118
23119static wuffs_base__status
23120wuffs_bmp__decoder__swizzle_rle(
23121 wuffs_bmp__decoder* self,
23122 wuffs_base__pixel_buffer* a_dst,
23123 wuffs_base__io_buffer* a_src) {
23124 wuffs_base__status status = wuffs_base__make_status(NULL);
23125
23126 wuffs_base__pixel_format v_dst_pixfmt = {0};
23127 uint32_t v_dst_bits_per_pixel = 0;
23128 uint64_t v_dst_bytes_per_pixel = 0;
23129 uint64_t v_dst_bytes_per_row = 0;
23130 wuffs_base__slice_u8 v_dst_palette = {0};
23131 wuffs_base__table_u8 v_tab = {0};
23132 wuffs_base__slice_u8 v_row = {0};
23133 wuffs_base__slice_u8 v_dst = {0};
23134 uint64_t v_i = 0;
23135 uint64_t v_n = 0;
23136 uint32_t v_p0 = 0;
23137 uint8_t v_code = 0;
23138 uint8_t v_indexes[2] = {0};
23139 uint32_t v_rle_state = 0;
23140 uint32_t v_chunk_bits = 0;
23141 uint32_t v_chunk_count = 0;
23142
23143 const uint8_t* iop_a_src = NULL;
23144 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23145 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23146 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23147 if (a_src) {
23148 io0_a_src = a_src->data.ptr;
23149 io1_a_src = io0_a_src + a_src->meta.ri;
23150 iop_a_src = io1_a_src;
23151 io2_a_src = io0_a_src + a_src->meta.wi;
23152 }
23153
23154 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
23155 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
23156 if ((v_dst_bits_per_pixel & 7) != 0) {
23157 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
23158 goto exit;
23159 }
23160 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
23161 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
23162 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8((self->private_data.f_scratch) + 1024, 1024));
23163 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
23164 v_rle_state = self->private_impl.f_rle_state;
23165 label__outer__continue:;
23166 while (true) {
Nigel Taobf9dab32021-11-18 19:19:55 +110023167 v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100023168 if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) {
23169 v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row);
23170 }
23171 label__middle__continue:;
23172 while (true) {
23173 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
23174 if (v_i <= ((uint64_t)(v_row.len))) {
23175 v_dst = wuffs_base__slice_u8__subslice_i(v_row, v_i);
23176 } else {
23177 v_dst = wuffs_base__utility__empty_slice_u8();
23178 }
23179 while (true) {
23180 label__inner__continue:;
23181 while (true) {
23182 if (v_rle_state == 0) {
23183 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
23184 goto label__goto_suspend__break;
23185 }
23186 v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
23187 iop_a_src += 1;
23188 if (v_code == 0) {
23189 v_rle_state = 2;
23190 goto label__inner__continue;
23191 }
23192 self->private_impl.f_rle_length = ((uint32_t)(v_code));
23193 v_rle_state = 1;
23194 goto label__inner__continue;
23195 } else if (v_rle_state == 1) {
23196 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
23197 goto label__goto_suspend__break;
23198 }
23199 v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
23200 iop_a_src += 1;
23201 if (self->private_impl.f_bits_per_pixel == 8) {
23202 v_p0 = 0;
23203 while (v_p0 < self->private_impl.f_rle_length) {
23204 self->private_data.f_scratch[v_p0] = v_code;
23205 v_p0 += 1;
23206 }
23207 } else {
23208 v_indexes[0] = ((uint8_t)((v_code >> 4)));
23209 v_indexes[1] = (v_code & 15);
23210 v_p0 = 0;
23211 while (v_p0 < self->private_impl.f_rle_length) {
23212 self->private_data.f_scratch[(v_p0 + 0)] = v_indexes[0];
23213 self->private_data.f_scratch[(v_p0 + 1)] = v_indexes[1];
23214 v_p0 += 2;
23215 }
23216 }
23217 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__slice_u8__subslice_j(wuffs_base__make_slice_u8(self->private_data.f_scratch, 2048), self->private_impl.f_rle_length));
23218 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, self->private_impl.f_rle_length);
23219 v_rle_state = 0;
23220 goto label__middle__continue;
23221 } else if (v_rle_state == 2) {
23222 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
23223 goto label__goto_suspend__break;
23224 }
23225 v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
23226 iop_a_src += 1;
23227 if (v_code < 2) {
23228 if ((self->private_impl.f_dst_y >= self->private_impl.f_height) && (v_code == 0)) {
23229 status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression);
23230 goto exit;
23231 }
23232 wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_dst, v_dst_palette, 18446744073709551615u);
23233 self->private_impl.f_dst_x = 0;
23234 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
23235 if (v_code > 0) {
23236 goto label__outer__break;
23237 }
23238 v_rle_state = 0;
23239 goto label__outer__continue;
23240 } else if (v_code == 2) {
23241 v_rle_state = 4;
23242 goto label__inner__continue;
23243 }
23244 self->private_impl.f_rle_length = ((uint32_t)(v_code));
23245 self->private_impl.f_rle_padded = ((self->private_impl.f_bits_per_pixel == 8) && ((v_code & 1) != 0));
23246 v_rle_state = 3;
23247 goto label__inner__continue;
23248 } else if (v_rle_state == 3) {
23249 if (self->private_impl.f_bits_per_pixel == 8) {
23250 v_n = wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
23251 &self->private_impl.f_swizzler,
23252 self->private_impl.f_rle_length,
23253 v_dst,
23254 v_dst_palette,
23255 &iop_a_src,
23256 io2_a_src);
23257 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
23258 wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_rle_length, ((uint32_t)((v_n & 4294967295))));
23259 } else {
23260 v_chunk_count = ((self->private_impl.f_rle_length + 3) / 4);
23261 v_p0 = 0;
23262 while ((v_chunk_count > 0) && (((uint64_t)(io2_a_src - iop_a_src)) >= 2)) {
23263 v_chunk_bits = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
23264 iop_a_src += 2;
23265 self->private_data.f_scratch[(v_p0 + 0)] = ((uint8_t)((15 & (v_chunk_bits >> 12))));
23266 self->private_data.f_scratch[(v_p0 + 1)] = ((uint8_t)((15 & (v_chunk_bits >> 8))));
23267 self->private_data.f_scratch[(v_p0 + 2)] = ((uint8_t)((15 & (v_chunk_bits >> 4))));
23268 self->private_data.f_scratch[(v_p0 + 3)] = ((uint8_t)((15 & (v_chunk_bits >> 0))));
23269 v_p0 = ((v_p0 & 255) + 4);
23270 v_chunk_count -= 1;
23271 }
23272 v_p0 = wuffs_base__u32__min(v_p0, self->private_impl.f_rle_length);
23273 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__slice_u8__subslice_j(wuffs_base__make_slice_u8(self->private_data.f_scratch, 2048), v_p0));
23274 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, v_p0);
23275 wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_rle_length, v_p0);
23276 }
23277 if (self->private_impl.f_rle_length > 0) {
23278 goto label__goto_suspend__break;
23279 }
23280 if (self->private_impl.f_rle_padded) {
23281 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
23282 goto label__goto_suspend__break;
23283 }
23284 iop_a_src += 1;
23285 self->private_impl.f_rle_padded = false;
23286 }
23287 v_rle_state = 0;
23288 goto label__middle__continue;
23289 } else if (v_rle_state == 4) {
23290 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
23291 goto label__goto_suspend__break;
23292 }
23293 self->private_impl.f_rle_delta_x = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
23294 iop_a_src += 1;
23295 v_rle_state = 5;
23296 goto label__inner__continue;
23297 }
23298 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
23299 goto label__goto_suspend__break;
23300 }
23301 v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
23302 iop_a_src += 1;
23303 if (self->private_impl.f_rle_delta_x > 0) {
23304 wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_dst, v_dst_palette, ((uint64_t)(self->private_impl.f_rle_delta_x)));
23305 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(self->private_impl.f_rle_delta_x)));
23306 self->private_impl.f_rle_delta_x = 0;
23307 if (self->private_impl.f_dst_x > self->private_impl.f_width) {
23308 status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression);
23309 goto exit;
23310 }
23311 }
23312 if (v_code > 0) {
23313#if defined(__GNUC__)
23314#pragma GCC diagnostic push
23315#pragma GCC diagnostic ignored "-Wconversion"
23316#endif
23317 v_code -= 1;
23318#if defined(__GNUC__)
23319#pragma GCC diagnostic pop
23320#endif
23321 while (true) {
23322 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
23323 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
23324 status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression);
23325 goto exit;
23326 }
Nigel Taobf9dab32021-11-18 19:19:55 +110023327 v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100023328 if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) {
23329 v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row);
23330 }
23331 if (v_code <= 0) {
23332 wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, ((uint64_t)(self->private_impl.f_dst_x)));
23333 goto label__0__break;
23334 }
23335 wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, 18446744073709551615u);
23336#if defined(__GNUC__)
23337#pragma GCC diagnostic push
23338#pragma GCC diagnostic ignored "-Wconversion"
23339#endif
23340 v_code -= 1;
23341#if defined(__GNUC__)
23342#pragma GCC diagnostic pop
23343#endif
23344 }
23345 label__0__break:;
23346 }
23347 v_rle_state = 0;
23348 goto label__middle__continue;
23349 }
23350 }
23351 label__goto_suspend__break:;
23352 self->private_impl.f_rle_state = v_rle_state;
23353 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
23354 goto ok;
23355 }
23356 }
23357 label__outer__break:;
23358 while (self->private_impl.f_dst_y < self->private_impl.f_height) {
Nigel Taobf9dab32021-11-18 19:19:55 +110023359 v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100023360 if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) {
23361 v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row);
23362 }
23363 wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, 18446744073709551615u);
23364 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
23365 }
23366 status = wuffs_base__make_status(NULL);
23367 goto ok;
23368
Nigel Taoe360a532021-04-05 22:47:03 +100023369 ok:
23370 goto exit;
23371 exit:
23372 if (a_src) {
23373 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23374 }
23375
23376 return status;
23377}
23378
23379// -------- func bmp.decoder.swizzle_bitfields
23380
23381static wuffs_base__status
23382wuffs_bmp__decoder__swizzle_bitfields(
23383 wuffs_bmp__decoder* self,
23384 wuffs_base__pixel_buffer* a_dst,
23385 wuffs_base__io_buffer* a_src) {
23386 wuffs_base__status status = wuffs_base__make_status(NULL);
23387
23388 wuffs_base__pixel_format v_dst_pixfmt = {0};
23389 uint32_t v_dst_bits_per_pixel = 0;
23390 uint64_t v_dst_bytes_per_pixel = 0;
23391 uint64_t v_dst_bytes_per_row = 0;
23392 wuffs_base__slice_u8 v_dst_palette = {0};
23393 wuffs_base__table_u8 v_tab = {0};
23394 wuffs_base__slice_u8 v_dst = {0};
23395 uint64_t v_i = 0;
23396 uint64_t v_n = 0;
23397 uint32_t v_p0 = 0;
23398 uint32_t v_p1 = 0;
23399 uint32_t v_p1_temp = 0;
23400 uint32_t v_num_bits = 0;
23401 uint32_t v_c = 0;
23402 uint32_t v_c32 = 0;
23403 uint32_t v_channel = 0;
23404
23405 const uint8_t* iop_a_src = NULL;
23406 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23407 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23408 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23409 if (a_src) {
23410 io0_a_src = a_src->data.ptr;
23411 io1_a_src = io0_a_src + a_src->meta.ri;
23412 iop_a_src = io1_a_src;
23413 io2_a_src = io0_a_src + a_src->meta.wi;
23414 }
23415
23416 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
23417 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
23418 if ((v_dst_bits_per_pixel & 7) != 0) {
23419 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
23420 goto exit;
23421 }
23422 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
23423 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
23424 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8((self->private_data.f_scratch) + 1024, 1024));
23425 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
23426 label__outer__continue:;
23427 while (true) {
23428 while (self->private_impl.f_pending_pad > 0) {
23429 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
23430 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
23431 goto ok;
23432 }
23433 self->private_impl.f_pending_pad -= 1;
23434 iop_a_src += 1;
23435 }
23436 label__inner__continue:;
23437 while (true) {
23438 if (self->private_impl.f_dst_x == self->private_impl.f_width) {
23439 self->private_impl.f_dst_x = 0;
23440 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
23441 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
23442 if (self->private_impl.f_height > 0) {
23443 self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row;
23444 }
23445 goto label__outer__break;
23446 } else if (self->private_impl.f_pad_per_row != 0) {
23447 self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row;
23448 goto label__outer__continue;
23449 }
23450 }
23451 v_p1_temp = ((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x));
23452 v_p1 = wuffs_base__u32__min(v_p1_temp, 256);
23453 v_p0 = 0;
23454 while (v_p0 < v_p1) {
23455 if (self->private_impl.f_bits_per_pixel == 16) {
23456 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
23457 goto label__0__break;
23458 }
23459 v_c32 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
23460 iop_a_src += 2;
23461 } else {
23462 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
23463 goto label__0__break;
23464 }
23465 v_c32 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23466 iop_a_src += 4;
23467 }
23468 v_channel = 0;
23469 while (v_channel < 4) {
23470 if (self->private_impl.f_channel_num_bits[v_channel] == 0) {
23471 self->private_data.f_scratch[((8 * v_p0) + (2 * v_channel) + 0)] = 255;
23472 self->private_data.f_scratch[((8 * v_p0) + (2 * v_channel) + 1)] = 255;
23473 } else {
23474 v_c = ((v_c32 & self->private_impl.f_channel_masks[v_channel]) >> self->private_impl.f_channel_shifts[v_channel]);
23475 v_num_bits = ((uint32_t)(self->private_impl.f_channel_num_bits[v_channel]));
23476 while (v_num_bits < 16) {
23477 v_c |= ((uint32_t)(v_c << v_num_bits));
23478 v_num_bits *= 2;
23479 }
23480 v_c >>= (v_num_bits - 16);
23481 self->private_data.f_scratch[((8 * v_p0) + (2 * v_channel) + 0)] = ((uint8_t)((255 & (v_c >> 0))));
23482 self->private_data.f_scratch[((8 * v_p0) + (2 * v_channel) + 1)] = ((uint8_t)((255 & (v_c >> 8))));
23483 }
23484 v_channel += 1;
23485 }
23486 v_p0 += 1;
23487 }
23488 label__0__break:;
Nigel Taobf9dab32021-11-18 19:19:55 +110023489 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100023490 if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) {
23491 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row);
23492 }
23493 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
23494 if (v_i >= ((uint64_t)(v_dst.len))) {
23495 goto label__inner__continue;
23496 }
23497 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__slice_u8__subslice_j(wuffs_base__make_slice_u8(self->private_data.f_scratch, 2048), (8 * v_p0)));
23498 if (v_n == 0) {
23499 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
23500 goto ok;
23501 }
23502 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
23503 }
23504 }
23505 label__outer__break:;
23506 status = wuffs_base__make_status(NULL);
23507 goto ok;
23508
Nigel Taoe360a532021-04-05 22:47:03 +100023509 ok:
23510 goto exit;
23511 exit:
23512 if (a_src) {
23513 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23514 }
23515
23516 return status;
23517}
23518
23519// -------- func bmp.decoder.swizzle_low_bit_depth
23520
23521static wuffs_base__status
23522wuffs_bmp__decoder__swizzle_low_bit_depth(
23523 wuffs_bmp__decoder* self,
23524 wuffs_base__pixel_buffer* a_dst,
23525 wuffs_base__io_buffer* a_src) {
23526 wuffs_base__status status = wuffs_base__make_status(NULL);
23527
23528 wuffs_base__pixel_format v_dst_pixfmt = {0};
23529 uint32_t v_dst_bits_per_pixel = 0;
23530 uint64_t v_dst_bytes_per_pixel = 0;
23531 uint64_t v_dst_bytes_per_row = 0;
23532 wuffs_base__slice_u8 v_dst_palette = {0};
23533 wuffs_base__table_u8 v_tab = {0};
23534 wuffs_base__slice_u8 v_dst = {0};
23535 uint64_t v_i = 0;
23536 uint64_t v_n = 0;
23537 uint32_t v_p0 = 0;
23538 uint32_t v_chunk_bits = 0;
23539 uint32_t v_chunk_count = 0;
23540
23541 const uint8_t* iop_a_src = NULL;
23542 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23543 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23544 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23545 if (a_src) {
23546 io0_a_src = a_src->data.ptr;
23547 io1_a_src = io0_a_src + a_src->meta.ri;
23548 iop_a_src = io1_a_src;
23549 io2_a_src = io0_a_src + a_src->meta.wi;
23550 }
23551
23552 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
23553 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
23554 if ((v_dst_bits_per_pixel & 7) != 0) {
23555 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
23556 goto exit;
23557 }
23558 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
23559 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
23560 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8((self->private_data.f_scratch) + 1024, 1024));
23561 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
23562 label__loop__continue:;
23563 while (true) {
23564 if (self->private_impl.f_dst_x == self->private_impl.f_width) {
23565 self->private_impl.f_dst_x = 0;
23566 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
23567 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
23568 goto label__loop__break;
23569 }
23570 }
Nigel Taobf9dab32021-11-18 19:19:55 +110023571 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100023572 if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) {
23573 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row);
23574 }
23575 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
23576 if (v_i >= ((uint64_t)(v_dst.len))) {
23577 goto label__loop__continue;
23578 }
23579 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i);
23580 v_p0 = 0;
23581 if (self->private_impl.f_bits_per_pixel == 1) {
23582 v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 31) / 32);
23583 v_chunk_count = wuffs_base__u32__min(v_chunk_count, 16);
23584 while ((v_chunk_count > 0) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
23585 v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
23586 iop_a_src += 4;
23587 self->private_data.f_scratch[(v_p0 + 0)] = ((uint8_t)((1 & (v_chunk_bits >> 31))));
23588 self->private_data.f_scratch[(v_p0 + 1)] = ((uint8_t)((1 & (v_chunk_bits >> 30))));
23589 self->private_data.f_scratch[(v_p0 + 2)] = ((uint8_t)((1 & (v_chunk_bits >> 29))));
23590 self->private_data.f_scratch[(v_p0 + 3)] = ((uint8_t)((1 & (v_chunk_bits >> 28))));
23591 self->private_data.f_scratch[(v_p0 + 4)] = ((uint8_t)((1 & (v_chunk_bits >> 27))));
23592 self->private_data.f_scratch[(v_p0 + 5)] = ((uint8_t)((1 & (v_chunk_bits >> 26))));
23593 self->private_data.f_scratch[(v_p0 + 6)] = ((uint8_t)((1 & (v_chunk_bits >> 25))));
23594 self->private_data.f_scratch[(v_p0 + 7)] = ((uint8_t)((1 & (v_chunk_bits >> 24))));
23595 self->private_data.f_scratch[(v_p0 + 8)] = ((uint8_t)((1 & (v_chunk_bits >> 23))));
23596 self->private_data.f_scratch[(v_p0 + 9)] = ((uint8_t)((1 & (v_chunk_bits >> 22))));
23597 self->private_data.f_scratch[(v_p0 + 10)] = ((uint8_t)((1 & (v_chunk_bits >> 21))));
23598 self->private_data.f_scratch[(v_p0 + 11)] = ((uint8_t)((1 & (v_chunk_bits >> 20))));
23599 self->private_data.f_scratch[(v_p0 + 12)] = ((uint8_t)((1 & (v_chunk_bits >> 19))));
23600 self->private_data.f_scratch[(v_p0 + 13)] = ((uint8_t)((1 & (v_chunk_bits >> 18))));
23601 self->private_data.f_scratch[(v_p0 + 14)] = ((uint8_t)((1 & (v_chunk_bits >> 17))));
23602 self->private_data.f_scratch[(v_p0 + 15)] = ((uint8_t)((1 & (v_chunk_bits >> 16))));
23603 self->private_data.f_scratch[(v_p0 + 16)] = ((uint8_t)((1 & (v_chunk_bits >> 15))));
23604 self->private_data.f_scratch[(v_p0 + 17)] = ((uint8_t)((1 & (v_chunk_bits >> 14))));
23605 self->private_data.f_scratch[(v_p0 + 18)] = ((uint8_t)((1 & (v_chunk_bits >> 13))));
23606 self->private_data.f_scratch[(v_p0 + 19)] = ((uint8_t)((1 & (v_chunk_bits >> 12))));
23607 self->private_data.f_scratch[(v_p0 + 20)] = ((uint8_t)((1 & (v_chunk_bits >> 11))));
23608 self->private_data.f_scratch[(v_p0 + 21)] = ((uint8_t)((1 & (v_chunk_bits >> 10))));
23609 self->private_data.f_scratch[(v_p0 + 22)] = ((uint8_t)((1 & (v_chunk_bits >> 9))));
23610 self->private_data.f_scratch[(v_p0 + 23)] = ((uint8_t)((1 & (v_chunk_bits >> 8))));
23611 self->private_data.f_scratch[(v_p0 + 24)] = ((uint8_t)((1 & (v_chunk_bits >> 7))));
23612 self->private_data.f_scratch[(v_p0 + 25)] = ((uint8_t)((1 & (v_chunk_bits >> 6))));
23613 self->private_data.f_scratch[(v_p0 + 26)] = ((uint8_t)((1 & (v_chunk_bits >> 5))));
23614 self->private_data.f_scratch[(v_p0 + 27)] = ((uint8_t)((1 & (v_chunk_bits >> 4))));
23615 self->private_data.f_scratch[(v_p0 + 28)] = ((uint8_t)((1 & (v_chunk_bits >> 3))));
23616 self->private_data.f_scratch[(v_p0 + 29)] = ((uint8_t)((1 & (v_chunk_bits >> 2))));
23617 self->private_data.f_scratch[(v_p0 + 30)] = ((uint8_t)((1 & (v_chunk_bits >> 1))));
23618 self->private_data.f_scratch[(v_p0 + 31)] = ((uint8_t)((1 & (v_chunk_bits >> 0))));
23619 v_p0 = ((v_p0 & 511) + 32);
23620 v_chunk_count -= 1;
23621 }
23622 } else if (self->private_impl.f_bits_per_pixel == 2) {
23623 v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 15) / 16);
23624 v_chunk_count = wuffs_base__u32__min(v_chunk_count, 32);
23625 while ((v_chunk_count > 0) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
23626 v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
23627 iop_a_src += 4;
23628 self->private_data.f_scratch[(v_p0 + 0)] = ((uint8_t)((3 & (v_chunk_bits >> 30))));
23629 self->private_data.f_scratch[(v_p0 + 1)] = ((uint8_t)((3 & (v_chunk_bits >> 28))));
23630 self->private_data.f_scratch[(v_p0 + 2)] = ((uint8_t)((3 & (v_chunk_bits >> 26))));
23631 self->private_data.f_scratch[(v_p0 + 3)] = ((uint8_t)((3 & (v_chunk_bits >> 24))));
23632 self->private_data.f_scratch[(v_p0 + 4)] = ((uint8_t)((3 & (v_chunk_bits >> 22))));
23633 self->private_data.f_scratch[(v_p0 + 5)] = ((uint8_t)((3 & (v_chunk_bits >> 20))));
23634 self->private_data.f_scratch[(v_p0 + 6)] = ((uint8_t)((3 & (v_chunk_bits >> 18))));
23635 self->private_data.f_scratch[(v_p0 + 7)] = ((uint8_t)((3 & (v_chunk_bits >> 16))));
23636 self->private_data.f_scratch[(v_p0 + 8)] = ((uint8_t)((3 & (v_chunk_bits >> 14))));
23637 self->private_data.f_scratch[(v_p0 + 9)] = ((uint8_t)((3 & (v_chunk_bits >> 12))));
23638 self->private_data.f_scratch[(v_p0 + 10)] = ((uint8_t)((3 & (v_chunk_bits >> 10))));
23639 self->private_data.f_scratch[(v_p0 + 11)] = ((uint8_t)((3 & (v_chunk_bits >> 8))));
23640 self->private_data.f_scratch[(v_p0 + 12)] = ((uint8_t)((3 & (v_chunk_bits >> 6))));
23641 self->private_data.f_scratch[(v_p0 + 13)] = ((uint8_t)((3 & (v_chunk_bits >> 4))));
23642 self->private_data.f_scratch[(v_p0 + 14)] = ((uint8_t)((3 & (v_chunk_bits >> 2))));
23643 self->private_data.f_scratch[(v_p0 + 15)] = ((uint8_t)((3 & (v_chunk_bits >> 0))));
23644 v_p0 = ((v_p0 & 511) + 16);
23645 v_chunk_count -= 1;
23646 }
23647 } else if (self->private_impl.f_bits_per_pixel == 4) {
23648 v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 7) / 8);
23649 v_chunk_count = wuffs_base__u32__min(v_chunk_count, 64);
23650 while ((v_chunk_count > 0) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
23651 v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
23652 iop_a_src += 4;
23653 self->private_data.f_scratch[(v_p0 + 0)] = ((uint8_t)((15 & (v_chunk_bits >> 28))));
23654 self->private_data.f_scratch[(v_p0 + 1)] = ((uint8_t)((15 & (v_chunk_bits >> 24))));
23655 self->private_data.f_scratch[(v_p0 + 2)] = ((uint8_t)((15 & (v_chunk_bits >> 20))));
23656 self->private_data.f_scratch[(v_p0 + 3)] = ((uint8_t)((15 & (v_chunk_bits >> 16))));
23657 self->private_data.f_scratch[(v_p0 + 4)] = ((uint8_t)((15 & (v_chunk_bits >> 12))));
23658 self->private_data.f_scratch[(v_p0 + 5)] = ((uint8_t)((15 & (v_chunk_bits >> 8))));
23659 self->private_data.f_scratch[(v_p0 + 6)] = ((uint8_t)((15 & (v_chunk_bits >> 4))));
23660 self->private_data.f_scratch[(v_p0 + 7)] = ((uint8_t)((15 & (v_chunk_bits >> 0))));
23661 v_p0 = ((v_p0 & 511) + 8);
23662 v_chunk_count -= 1;
23663 }
23664 }
23665 v_p0 = wuffs_base__u32__min(v_p0, wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x));
23666 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__slice_u8__subslice_j(wuffs_base__make_slice_u8(self->private_data.f_scratch, 2048), v_p0));
23667 if (v_n == 0) {
23668 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
23669 goto ok;
23670 }
23671 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
23672 }
23673 label__loop__break:;
23674 status = wuffs_base__make_status(NULL);
23675 goto ok;
23676
Nigel Taoe360a532021-04-05 22:47:03 +100023677 ok:
23678 goto exit;
23679 exit:
23680 if (a_src) {
23681 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23682 }
23683
23684 return status;
23685}
23686
23687// -------- func bmp.decoder.frame_dirty_rect
23688
23689WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
23690wuffs_bmp__decoder__frame_dirty_rect(
23691 const wuffs_bmp__decoder* self) {
23692 if (!self) {
23693 return wuffs_base__utility__empty_rect_ie_u32();
23694 }
23695 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
23696 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
23697 return wuffs_base__utility__empty_rect_ie_u32();
23698 }
23699
23700 return wuffs_base__utility__make_rect_ie_u32(
23701 0,
23702 0,
23703 self->private_impl.f_width,
23704 self->private_impl.f_height);
23705}
23706
23707// -------- func bmp.decoder.num_animation_loops
23708
23709WUFFS_BASE__MAYBE_STATIC uint32_t
23710wuffs_bmp__decoder__num_animation_loops(
23711 const wuffs_bmp__decoder* self) {
23712 if (!self) {
23713 return 0;
23714 }
23715 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
23716 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
23717 return 0;
23718 }
23719
23720 return 0;
23721}
23722
23723// -------- func bmp.decoder.num_decoded_frame_configs
23724
23725WUFFS_BASE__MAYBE_STATIC uint64_t
23726wuffs_bmp__decoder__num_decoded_frame_configs(
23727 const wuffs_bmp__decoder* self) {
23728 if (!self) {
23729 return 0;
23730 }
23731 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
23732 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
23733 return 0;
23734 }
23735
23736 if (self->private_impl.f_call_sequence > 3) {
23737 return 1;
23738 }
23739 return 0;
23740}
23741
23742// -------- func bmp.decoder.num_decoded_frames
23743
23744WUFFS_BASE__MAYBE_STATIC uint64_t
23745wuffs_bmp__decoder__num_decoded_frames(
23746 const wuffs_bmp__decoder* self) {
23747 if (!self) {
23748 return 0;
23749 }
23750 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
23751 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
23752 return 0;
23753 }
23754
23755 if (self->private_impl.f_call_sequence > 4) {
23756 return 1;
23757 }
23758 return 0;
23759}
23760
23761// -------- func bmp.decoder.restart_frame
23762
23763WUFFS_BASE__MAYBE_STATIC wuffs_base__status
23764wuffs_bmp__decoder__restart_frame(
23765 wuffs_bmp__decoder* self,
23766 uint64_t a_index,
23767 uint64_t a_io_position) {
23768 if (!self) {
23769 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
23770 }
23771 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
23772 return wuffs_base__make_status(
23773 (self->private_impl.magic == WUFFS_BASE__DISABLED)
23774 ? wuffs_base__error__disabled_by_previous_error
23775 : wuffs_base__error__initialize_not_called);
23776 }
23777
23778 if (self->private_impl.f_call_sequence < 3) {
23779 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
23780 }
23781 if (a_index != 0) {
23782 return wuffs_base__make_status(wuffs_base__error__bad_argument);
23783 }
23784 self->private_impl.f_call_sequence = 3;
23785 self->private_impl.f_frame_config_io_position = a_io_position;
23786 return wuffs_base__make_status(NULL);
23787}
23788
23789// -------- func bmp.decoder.set_report_metadata
23790
23791WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
23792wuffs_bmp__decoder__set_report_metadata(
23793 wuffs_bmp__decoder* self,
23794 uint32_t a_fourcc,
23795 bool a_report) {
23796 return wuffs_base__make_empty_struct();
23797}
23798
23799// -------- func bmp.decoder.tell_me_more
23800
23801WUFFS_BASE__MAYBE_STATIC wuffs_base__status
23802wuffs_bmp__decoder__tell_me_more(
23803 wuffs_bmp__decoder* self,
23804 wuffs_base__io_buffer* a_dst,
23805 wuffs_base__more_information* a_minfo,
23806 wuffs_base__io_buffer* a_src) {
23807 if (!self) {
23808 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
23809 }
23810 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
23811 return wuffs_base__make_status(
23812 (self->private_impl.magic == WUFFS_BASE__DISABLED)
23813 ? wuffs_base__error__disabled_by_previous_error
23814 : wuffs_base__error__initialize_not_called);
23815 }
23816 if (!a_dst || !a_src) {
23817 self->private_impl.magic = WUFFS_BASE__DISABLED;
23818 return wuffs_base__make_status(wuffs_base__error__bad_argument);
23819 }
23820 if ((self->private_impl.active_coroutine != 0) &&
23821 (self->private_impl.active_coroutine != 4)) {
23822 self->private_impl.magic = WUFFS_BASE__DISABLED;
23823 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
23824 }
23825 self->private_impl.active_coroutine = 0;
23826 wuffs_base__status status = wuffs_base__make_status(NULL);
23827
23828 if (self->private_impl.f_io_redirect_fourcc <= 1) {
23829 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
23830 goto exit;
23831 }
23832 if (a_minfo != NULL) {
23833 wuffs_base__more_information__set(a_minfo,
23834 1,
23835 self->private_impl.f_io_redirect_fourcc,
23836 0,
23837 self->private_impl.f_io_redirect_pos,
23838 18446744073709551615u);
23839 }
23840 self->private_impl.f_io_redirect_fourcc = 1;
23841
23842 goto ok;
23843 ok:
23844 goto exit;
23845 exit:
23846 if (wuffs_base__status__is_error(&status)) {
23847 self->private_impl.magic = WUFFS_BASE__DISABLED;
23848 }
23849 return status;
23850}
23851
23852// -------- func bmp.decoder.workbuf_len
23853
23854WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
23855wuffs_bmp__decoder__workbuf_len(
23856 const wuffs_bmp__decoder* self) {
23857 if (!self) {
23858 return wuffs_base__utility__empty_range_ii_u64();
23859 }
23860 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
23861 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
23862 return wuffs_base__utility__empty_range_ii_u64();
23863 }
23864
23865 return wuffs_base__utility__make_range_ii_u64(0, 0);
23866}
23867
23868// -------- func bmp.decoder.read_palette
23869
23870static wuffs_base__status
23871wuffs_bmp__decoder__read_palette(
23872 wuffs_bmp__decoder* self,
23873 wuffs_base__io_buffer* a_src) {
23874 wuffs_base__status status = wuffs_base__make_status(NULL);
23875
23876 uint32_t v_i = 0;
23877 uint32_t v_argb = 0;
23878
23879 const uint8_t* iop_a_src = NULL;
23880 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23881 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23882 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23883 if (a_src) {
23884 io0_a_src = a_src->data.ptr;
23885 io1_a_src = io0_a_src + a_src->meta.ri;
23886 iop_a_src = io1_a_src;
23887 io2_a_src = io0_a_src + a_src->meta.wi;
23888 }
23889
23890 uint32_t coro_susp_point = self->private_impl.p_read_palette[0];
23891 if (coro_susp_point) {
23892 v_i = self->private_data.s_read_palette[0].v_i;
23893 }
23894 switch (coro_susp_point) {
23895 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
23896
23897 if (self->private_impl.f_bitmap_info_len == 12) {
23898 while ((v_i < 256) && (self->private_impl.f_padding >= 3)) {
23899 self->private_impl.f_padding -= 3;
23900 {
23901 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
23902 uint32_t t_0;
23903 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
23904 t_0 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
23905 iop_a_src += 3;
23906 } else {
23907 self->private_data.s_read_palette[0].scratch = 0;
23908 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
23909 while (true) {
23910 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23911 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23912 goto suspend;
23913 }
23914 uint64_t* scratch = &self->private_data.s_read_palette[0].scratch;
23915 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
23916 *scratch <<= 8;
23917 *scratch >>= 8;
23918 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
23919 if (num_bits_0 == 16) {
23920 t_0 = ((uint32_t)(*scratch));
23921 break;
23922 }
23923 num_bits_0 += 8;
23924 *scratch |= ((uint64_t)(num_bits_0)) << 56;
23925 }
23926 }
23927 v_argb = t_0;
23928 }
23929 v_argb |= 4278190080;
23930 self->private_data.f_src_palette[((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
23931 self->private_data.f_src_palette[((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
23932 self->private_data.f_src_palette[((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
23933 self->private_data.f_src_palette[((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
23934 v_i += 1;
23935 }
23936 } else {
23937 while ((v_i < 256) && (self->private_impl.f_padding >= 4)) {
23938 self->private_impl.f_padding -= 4;
23939 {
23940 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
23941 uint32_t t_1;
23942 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23943 t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23944 iop_a_src += 4;
23945 } else {
23946 self->private_data.s_read_palette[0].scratch = 0;
23947 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
23948 while (true) {
23949 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23950 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23951 goto suspend;
23952 }
23953 uint64_t* scratch = &self->private_data.s_read_palette[0].scratch;
23954 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
23955 *scratch <<= 8;
23956 *scratch >>= 8;
23957 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
23958 if (num_bits_1 == 24) {
23959 t_1 = ((uint32_t)(*scratch));
23960 break;
23961 }
23962 num_bits_1 += 8;
23963 *scratch |= ((uint64_t)(num_bits_1)) << 56;
23964 }
23965 }
23966 v_argb = t_1;
23967 }
23968 v_argb |= 4278190080;
23969 self->private_data.f_src_palette[((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
23970 self->private_data.f_src_palette[((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
23971 self->private_data.f_src_palette[((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
23972 self->private_data.f_src_palette[((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
23973 v_i += 1;
23974 }
23975 }
23976 while (v_i < 256) {
23977 self->private_data.f_src_palette[((4 * v_i) + 0)] = 0;
23978 self->private_data.f_src_palette[((4 * v_i) + 1)] = 0;
23979 self->private_data.f_src_palette[((4 * v_i) + 2)] = 0;
23980 self->private_data.f_src_palette[((4 * v_i) + 3)] = 255;
23981 v_i += 1;
23982 }
23983
23984 goto ok;
23985 ok:
23986 self->private_impl.p_read_palette[0] = 0;
23987 goto exit;
23988 }
23989
23990 goto suspend;
23991 suspend:
23992 self->private_impl.p_read_palette[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
23993 self->private_data.s_read_palette[0].v_i = v_i;
23994
23995 goto exit;
23996 exit:
23997 if (a_src) {
23998 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23999 }
24000
24001 return status;
24002}
24003
24004// -------- func bmp.decoder.process_masks
24005
24006static wuffs_base__status
24007wuffs_bmp__decoder__process_masks(
24008 wuffs_bmp__decoder* self) {
24009 wuffs_base__status status = wuffs_base__make_status(NULL);
24010
24011 uint32_t v_i = 0;
24012 uint32_t v_mask = 0;
24013 uint32_t v_n = 0;
24014
24015 while (v_i < 4) {
24016 v_mask = self->private_impl.f_channel_masks[v_i];
24017 if (v_mask != 0) {
24018 v_n = 0;
24019 while ((v_mask & 1) == 0) {
24020 v_n += 1;
24021 v_mask >>= 1;
24022 }
24023 self->private_impl.f_channel_shifts[v_i] = ((uint8_t)((v_n & 31)));
24024 v_n = 0;
24025 while ((v_mask & 1) == 1) {
24026 v_n += 1;
24027 v_mask >>= 1;
24028 }
24029 if ((v_mask != 0) || (v_n > 32)) {
24030 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
24031 goto exit;
24032 }
24033 self->private_impl.f_channel_num_bits[v_i] = ((uint8_t)(v_n));
24034 } else if (v_i != 3) {
24035 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
24036 goto exit;
24037 }
24038 v_i += 1;
24039 }
24040
24041 goto ok;
24042 ok:
24043 goto exit;
24044 exit:
24045 return status;
24046}
24047
24048#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP)
24049
24050#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR)
24051
24052// ---------------- Status Codes Implementations
24053
24054const char wuffs_cbor__error__bad_input[] = "#cbor: bad input";
24055const char wuffs_cbor__error__unsupported_recursion_depth[] = "#cbor: unsupported recursion depth";
24056const char wuffs_cbor__error__internal_error_inconsistent_i_o[] = "#cbor: internal error: inconsistent I/O";
24057const char wuffs_cbor__error__internal_error_inconsistent_token_length[] = "#cbor: internal error: inconsistent token length";
24058
24059// ---------------- Private Consts
24060
24061static const uint32_t
24062WUFFS_CBOR__LITERALS[4] WUFFS_BASE__POTENTIALLY_UNUSED = {
24063 8388612, 8388616, 8388610, 8388609,
24064};
24065
24066static const uint8_t
24067WUFFS_CBOR__TOKEN_LENGTHS[32] WUFFS_BASE__POTENTIALLY_UNUSED = {
24068 1, 1, 1, 1, 1, 1, 1, 1,
24069 1, 1, 1, 1, 1, 1, 1, 1,
24070 1, 1, 1, 1, 1, 1, 1, 1,
24071 2, 3, 5, 9, 0, 0, 0, 1,
24072};
24073
24074// ---------------- Private Initializer Prototypes
24075
24076// ---------------- Private Function Prototypes
24077
24078// ---------------- VTables
24079
24080const wuffs_base__token_decoder__func_ptrs
24081wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder = {
24082 (wuffs_base__status(*)(void*,
24083 wuffs_base__token_buffer*,
24084 wuffs_base__io_buffer*,
24085 wuffs_base__slice_u8))(&wuffs_cbor__decoder__decode_tokens),
24086 (wuffs_base__empty_struct(*)(void*,
24087 uint32_t,
24088 bool))(&wuffs_cbor__decoder__set_quirk_enabled),
24089 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_cbor__decoder__workbuf_len),
24090};
24091
24092// ---------------- Initializer Implementations
24093
24094wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
24095wuffs_cbor__decoder__initialize(
24096 wuffs_cbor__decoder* self,
24097 size_t sizeof_star_self,
24098 uint64_t wuffs_version,
24099 uint32_t options){
24100 if (!self) {
24101 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
24102 }
24103 if (sizeof(*self) != sizeof_star_self) {
24104 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
24105 }
24106 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
24107 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
24108 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
24109 }
24110
24111 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
24112 // The whole point of this if-check is to detect an uninitialized *self.
24113 // We disable the warning on GCC. Clang-5.0 does not have this warning.
24114#if !defined(__clang__) && defined(__GNUC__)
24115#pragma GCC diagnostic push
24116#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
24117#endif
24118 if (self->private_impl.magic != 0) {
24119 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
24120 }
24121#if !defined(__clang__) && defined(__GNUC__)
24122#pragma GCC diagnostic pop
24123#endif
24124 } else {
24125 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
24126 memset(self, 0, sizeof(*self));
24127 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
24128 } else {
24129 memset(&(self->private_impl), 0, sizeof(self->private_impl));
24130 }
24131 }
24132
24133 self->private_impl.magic = WUFFS_BASE__MAGIC;
24134 self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name =
24135 wuffs_base__token_decoder__vtable_name;
24136 self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers =
24137 (const void*)(&wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder);
24138 return wuffs_base__make_status(NULL);
24139}
24140
24141wuffs_cbor__decoder*
24142wuffs_cbor__decoder__alloc() {
24143 wuffs_cbor__decoder* x =
24144 (wuffs_cbor__decoder*)(calloc(sizeof(wuffs_cbor__decoder), 1));
24145 if (!x) {
24146 return NULL;
24147 }
24148 if (wuffs_cbor__decoder__initialize(
24149 x, sizeof(wuffs_cbor__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
24150 free(x);
24151 return NULL;
24152 }
24153 return x;
24154}
24155
24156size_t
24157sizeof__wuffs_cbor__decoder() {
24158 return sizeof(wuffs_cbor__decoder);
24159}
24160
24161// ---------------- Function Implementations
24162
24163// -------- func cbor.decoder.set_quirk_enabled
24164
24165WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
24166wuffs_cbor__decoder__set_quirk_enabled(
24167 wuffs_cbor__decoder* self,
24168 uint32_t a_quirk,
24169 bool a_enabled) {
24170 return wuffs_base__make_empty_struct();
24171}
24172
24173// -------- func cbor.decoder.workbuf_len
24174
24175WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
24176wuffs_cbor__decoder__workbuf_len(
24177 const wuffs_cbor__decoder* self) {
24178 if (!self) {
24179 return wuffs_base__utility__empty_range_ii_u64();
24180 }
24181 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
24182 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
24183 return wuffs_base__utility__empty_range_ii_u64();
24184 }
24185
24186 return wuffs_base__utility__empty_range_ii_u64();
24187}
24188
24189// -------- func cbor.decoder.decode_tokens
24190
24191WUFFS_BASE__MAYBE_STATIC wuffs_base__status
24192wuffs_cbor__decoder__decode_tokens(
24193 wuffs_cbor__decoder* self,
24194 wuffs_base__token_buffer* a_dst,
24195 wuffs_base__io_buffer* a_src,
24196 wuffs_base__slice_u8 a_workbuf) {
24197 if (!self) {
24198 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
24199 }
24200 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
24201 return wuffs_base__make_status(
24202 (self->private_impl.magic == WUFFS_BASE__DISABLED)
24203 ? wuffs_base__error__disabled_by_previous_error
24204 : wuffs_base__error__initialize_not_called);
24205 }
24206 if (!a_dst || !a_src) {
24207 self->private_impl.magic = WUFFS_BASE__DISABLED;
24208 return wuffs_base__make_status(wuffs_base__error__bad_argument);
24209 }
24210 if ((self->private_impl.active_coroutine != 0) &&
24211 (self->private_impl.active_coroutine != 1)) {
24212 self->private_impl.magic = WUFFS_BASE__DISABLED;
24213 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
24214 }
24215 self->private_impl.active_coroutine = 0;
24216 wuffs_base__status status = wuffs_base__make_status(NULL);
24217
24218 uint64_t v_string_length = 0;
24219 uint64_t v_n64 = 0;
24220 uint32_t v_depth = 0;
24221 uint32_t v_stack_byte = 0;
24222 uint32_t v_stack_bit = 0;
24223 uint32_t v_stack_val = 0;
24224 uint32_t v_token_length = 0;
24225 uint32_t v_vminor = 0;
24226 uint32_t v_vminor_alt = 0;
24227 uint32_t v_continued = 0;
24228 uint8_t v_c = 0;
24229 uint8_t v_c_major = 0;
24230 uint8_t v_c_minor = 0;
24231 bool v_tagged = false;
24232 uint8_t v_indefinite_string_major_type = 0;
24233
24234 wuffs_base__token* iop_a_dst = NULL;
24235 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24236 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24237 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24238 if (a_dst) {
24239 io0_a_dst = a_dst->data.ptr;
24240 io1_a_dst = io0_a_dst + a_dst->meta.wi;
24241 iop_a_dst = io1_a_dst;
24242 io2_a_dst = io0_a_dst + a_dst->data.len;
24243 if (a_dst->meta.closed) {
24244 io2_a_dst = iop_a_dst;
24245 }
24246 }
24247 const uint8_t* iop_a_src = NULL;
24248 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24249 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24250 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24251 if (a_src) {
24252 io0_a_src = a_src->data.ptr;
24253 io1_a_src = io0_a_src + a_src->meta.ri;
24254 iop_a_src = io1_a_src;
24255 io2_a_src = io0_a_src + a_src->meta.wi;
24256 }
24257
24258 uint32_t coro_susp_point = self->private_impl.p_decode_tokens[0];
24259 if (coro_susp_point) {
24260 v_string_length = self->private_data.s_decode_tokens[0].v_string_length;
24261 v_depth = self->private_data.s_decode_tokens[0].v_depth;
24262 v_token_length = self->private_data.s_decode_tokens[0].v_token_length;
24263 v_tagged = self->private_data.s_decode_tokens[0].v_tagged;
24264 v_indefinite_string_major_type = self->private_data.s_decode_tokens[0].v_indefinite_string_major_type;
24265 }
24266 switch (coro_susp_point) {
24267 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
24268
24269 if (self->private_impl.f_end_of_data) {
24270 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
24271 goto ok;
24272 }
24273 label__outer__continue:;
24274 while (true) {
24275 while (true) {
24276 while (true) {
24277 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1) {
24278 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
24279 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
24280 goto label__outer__continue;
24281 }
24282 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
24283 if (a_src && a_src->meta.closed) {
24284 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
24285 goto exit;
24286 }
24287 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
24288 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
24289 goto label__outer__continue;
24290 }
24291 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
24292 if ((v_indefinite_string_major_type != 0) && (v_indefinite_string_major_type != (v_c >> 5))) {
24293 if (v_c != 255) {
24294 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
24295 goto exit;
24296 }
24297 v_vminor = 4194560;
24298 if (v_indefinite_string_major_type == 3) {
24299 v_vminor |= 19;
24300 }
24301 v_indefinite_string_major_type = 0;
24302 iop_a_src += 1;
24303 *iop_a_dst++ = wuffs_base__make_token(
24304 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24305 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24306 goto label__goto_parsed_a_leaf_value__break;
24307 }
24308 iop_a_src += 1;
24309 v_c_major = ((uint8_t)((v_c >> 5)));
24310 v_c_minor = (v_c & 31);
24311 if (v_c_minor < 24) {
24312 v_string_length = ((uint64_t)(v_c_minor));
24313 } else {
24314 while (true) {
24315 if (v_c_minor == 24) {
24316 if (((uint64_t)(io2_a_src - iop_a_src)) >= 1) {
24317 v_string_length = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src)));
24318 iop_a_src += 1;
24319 goto label__goto_have_string_length__break;
24320 }
24321 } else if (v_c_minor == 25) {
24322 if (((uint64_t)(io2_a_src - iop_a_src)) >= 2) {
24323 v_string_length = ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
24324 iop_a_src += 2;
24325 goto label__goto_have_string_length__break;
24326 }
24327 } else if (v_c_minor == 26) {
24328 if (((uint64_t)(io2_a_src - iop_a_src)) >= 4) {
24329 v_string_length = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
24330 iop_a_src += 4;
24331 goto label__goto_have_string_length__break;
24332 }
24333 } else if (v_c_minor == 27) {
24334 if (((uint64_t)(io2_a_src - iop_a_src)) >= 8) {
24335 v_string_length = wuffs_base__peek_u64be__no_bounds_check(iop_a_src);
24336 iop_a_src += 8;
24337 goto label__goto_have_string_length__break;
24338 }
24339 } else {
24340 v_string_length = 0;
24341 goto label__goto_have_string_length__break;
24342 }
24343 if (iop_a_src > io1_a_src) {
24344 iop_a_src--;
24345 if (a_src && a_src->meta.closed) {
24346 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
24347 goto exit;
24348 }
24349 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
24350 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
24351 v_c_major = 0;
24352 v_c_minor = 0;
24353 goto label__outer__continue;
24354 }
24355 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
24356 goto exit;
24357 }
24358 label__goto_have_string_length__break:;
24359 }
24360 if (v_c_major == 0) {
24361 if (v_c_minor < 26) {
24362 *iop_a_dst++ = wuffs_base__make_token(
24363 (((uint64_t)((14680064 | ((uint32_t)((v_string_length & 65535)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24364 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24365 goto label__goto_parsed_a_leaf_value__break;
24366 } else if (v_c_minor < 28) {
24367 *iop_a_dst++ = wuffs_base__make_token(
24368 (((uint64_t)((14680064 | ((uint32_t)((v_string_length >> 46)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24369 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24370 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24371 *iop_a_dst++ = wuffs_base__make_token(
24372 (~(v_string_length & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
24373 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24374 goto label__goto_parsed_a_leaf_value__break;
24375 }
24376 } else if (v_c_major == 1) {
24377 if (v_c_minor < 26) {
24378 *iop_a_dst++ = wuffs_base__make_token(
24379 (((uint64_t)((12582912 | (2097151 - ((uint32_t)((v_string_length & 65535))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24380 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24381 goto label__goto_parsed_a_leaf_value__break;
24382 } else if (v_c_minor < 28) {
24383 if (v_string_length < 9223372036854775808u) {
24384 *iop_a_dst++ = wuffs_base__make_token(
24385 (((uint64_t)((12582912 | (2097151 - ((uint32_t)((v_string_length >> 46))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24386 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24387 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24388 *iop_a_dst++ = wuffs_base__make_token(
24389 (~((18446744073709551615u - v_string_length) & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
24390 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24391 } else {
24392 *iop_a_dst++ = wuffs_base__make_token(
24393 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
24394 (((uint64_t)(16777216)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24395 (((uint64_t)(9)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24396 }
24397 goto label__goto_parsed_a_leaf_value__break;
24398 }
24399 } else if (v_c_major == 2) {
24400 if (v_c_minor < 28) {
24401 if (v_string_length == 0) {
24402 *iop_a_dst++ = wuffs_base__make_token(
24403 (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24404 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24405 goto label__goto_parsed_a_leaf_value__break;
24406 }
24407 *iop_a_dst++ = wuffs_base__make_token(
24408 (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24409 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24410 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24411 } else if (v_c_minor == 31) {
24412 if (v_indefinite_string_major_type != 0) {
24413 goto label__goto_fail__break;
24414 }
24415 v_indefinite_string_major_type = 2;
24416 *iop_a_dst++ = wuffs_base__make_token(
24417 (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24418 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24419 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24420 goto label__outer__continue;
24421 } else {
24422 goto label__goto_fail__break;
24423 }
24424 label__0__continue:;
24425 while (true) {
24426 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
24427 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
24428 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
24429 goto label__0__continue;
24430 }
24431 v_n64 = wuffs_base__u64__min(v_string_length, ((uint64_t)(io2_a_src - iop_a_src)));
24432 v_token_length = ((uint32_t)((v_n64 & 65535)));
24433 if (v_n64 > 65535) {
24434 v_token_length = 65535;
24435 } else if (v_token_length <= 0) {
24436 if (a_src && a_src->meta.closed) {
24437 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
24438 goto exit;
24439 }
24440 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
24441 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
24442 goto label__0__continue;
24443 }
24444 if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) {
24445 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length);
24446 goto exit;
24447 }
24448 v_string_length -= ((uint64_t)(v_token_length));
24449 v_continued = 0;
24450 if ((v_string_length > 0) || (v_indefinite_string_major_type > 0)) {
24451 v_continued = 1;
24452 }
24453 iop_a_src += v_token_length;
24454 *iop_a_dst++ = wuffs_base__make_token(
24455 (((uint64_t)(4194816)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24456 (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24457 (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24458 if (v_string_length > 0) {
24459 goto label__0__continue;
24460 } else if (v_indefinite_string_major_type > 0) {
24461 goto label__outer__continue;
24462 }
24463 goto label__goto_parsed_a_leaf_value__break;
24464 }
24465 } else if (v_c_major == 3) {
24466 if (v_c_minor < 28) {
24467 if (v_string_length == 0) {
24468 *iop_a_dst++ = wuffs_base__make_token(
24469 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24470 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24471 goto label__goto_parsed_a_leaf_value__break;
24472 }
24473 *iop_a_dst++ = wuffs_base__make_token(
24474 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24475 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24476 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24477 } else if (v_c_minor == 31) {
24478 if (v_indefinite_string_major_type != 0) {
24479 goto label__goto_fail__break;
24480 }
24481 v_indefinite_string_major_type = 3;
24482 *iop_a_dst++ = wuffs_base__make_token(
24483 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24484 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24485 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24486 goto label__outer__continue;
24487 } else {
24488 goto label__goto_fail__break;
24489 }
24490 label__1__continue:;
24491 while (true) {
24492 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
24493 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
24494 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
24495 goto label__1__continue;
24496 }
24497 v_n64 = wuffs_base__u64__min(v_string_length, 65535);
24498 v_n64 = ((uint64_t)(wuffs_base__utf_8__longest_valid_prefix(iop_a_src,
24499 ((size_t)(wuffs_base__u64__min(((uint64_t)(io2_a_src - iop_a_src)), v_n64))))));
24500 v_token_length = ((uint32_t)((v_n64 & 65535)));
24501 if (v_token_length <= 0) {
24502 if ((a_src && a_src->meta.closed) || (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
24503 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
24504 goto exit;
24505 }
24506 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
24507 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
24508 goto label__1__continue;
24509 }
24510 if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) {
24511 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length);
24512 goto exit;
24513 }
24514 v_string_length -= ((uint64_t)(v_token_length));
24515 v_continued = 0;
24516 if ((v_string_length > 0) || (v_indefinite_string_major_type > 0)) {
24517 v_continued = 1;
24518 }
24519 iop_a_src += v_token_length;
24520 *iop_a_dst++ = wuffs_base__make_token(
24521 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24522 (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24523 (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24524 if (v_string_length > 0) {
24525 goto label__1__continue;
24526 } else if (v_indefinite_string_major_type > 0) {
24527 goto label__outer__continue;
24528 }
24529 goto label__goto_parsed_a_leaf_value__break;
24530 }
24531 } else if (v_c_major == 4) {
24532 if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0) {
24533 goto label__goto_fail__break;
24534 } else if (v_depth >= 1024) {
24535 v_token_length = ((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor]));
24536 while ((v_token_length > 0) && (iop_a_src > io1_a_src)) {
24537 iop_a_src--;
24538 v_token_length -= 1;
24539 }
24540 status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth);
24541 goto exit;
24542 }
24543 v_vminor = 2105361;
24544 v_vminor_alt = 2101282;
24545 if (v_depth > 0) {
24546 v_stack_byte = ((v_depth - 1) / 16);
24547 v_stack_bit = (((v_depth - 1) & 15) * 2);
24548 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
24549 v_vminor = 2105377;
24550 v_vminor_alt = 2105378;
24551 } else {
24552 v_vminor = 2105409;
24553 v_vminor_alt = 2113570;
24554 }
24555 }
24556 *iop_a_dst++ = wuffs_base__make_token(
24557 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24558 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24559 if (v_c_minor == 0) {
24560 *iop_a_dst++ = wuffs_base__make_token(
24561 (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24562 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24563 goto label__goto_parsed_a_leaf_value__break;
24564 }
24565 v_stack_byte = (v_depth / 16);
24566 v_stack_bit = ((v_depth & 15) * 2);
24567 self->private_data.f_stack[v_stack_byte] &= (4294967295 ^ (((uint32_t)(3)) << v_stack_bit));
24568 self->private_data.f_container_num_remaining[v_depth] = v_string_length;
24569 v_depth += 1;
24570 v_tagged = false;
24571 goto label__outer__continue;
24572 } else if (v_c_major == 5) {
24573 if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0) {
24574 goto label__goto_fail__break;
24575 } else if (v_depth >= 1024) {
24576 v_token_length = ((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor]));
24577 while ((v_token_length > 0) && (iop_a_src > io1_a_src)) {
24578 iop_a_src--;
24579 v_token_length -= 1;
24580 }
24581 status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth);
24582 goto exit;
24583 }
24584 v_vminor = 2113553;
24585 v_vminor_alt = 2101314;
24586 if (v_depth > 0) {
24587 v_stack_byte = ((v_depth - 1) / 16);
24588 v_stack_bit = (((v_depth - 1) & 15) * 2);
24589 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
24590 v_vminor = 2113569;
24591 v_vminor_alt = 2105410;
24592 } else {
24593 v_vminor = 2113601;
24594 v_vminor_alt = 2113602;
24595 }
24596 }
24597 *iop_a_dst++ = wuffs_base__make_token(
24598 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24599 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24600 if (v_c_minor == 0) {
24601 *iop_a_dst++ = wuffs_base__make_token(
24602 (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24603 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24604 goto label__goto_parsed_a_leaf_value__break;
24605 }
24606 v_stack_byte = (v_depth / 16);
24607 v_stack_bit = ((v_depth & 15) * 2);
24608 self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(3)) << v_stack_bit);
24609 self->private_data.f_container_num_remaining[v_depth] = v_string_length;
24610 v_depth += 1;
24611 v_tagged = false;
24612 goto label__outer__continue;
24613 } else if (v_c_major == 6) {
24614 if (v_c_minor >= 28) {
24615 goto label__goto_fail__break;
24616 }
24617 if (v_string_length < 262144) {
24618 *iop_a_dst++ = wuffs_base__make_token(
24619 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
24620 (((uint64_t)((4194304 | ((uint32_t)(v_string_length))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24621 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24622 } else {
24623 *iop_a_dst++ = wuffs_base__make_token(
24624 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
24625 (((uint64_t)((4194304 | ((uint32_t)((v_string_length >> 46)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24626 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
24627 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24628 *iop_a_dst++ = wuffs_base__make_token(
24629 (~(v_string_length & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
24630 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24631 }
24632 v_tagged = true;
24633 goto label__outer__continue;
24634 } else if (v_c_major == 7) {
24635 if (v_c_minor < 20) {
24636 *iop_a_dst++ = wuffs_base__make_token(
24637 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
24638 (((uint64_t)((8388608 | ((uint32_t)((v_string_length & 255)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24639 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24640 goto label__goto_parsed_a_leaf_value__break;
24641 } else if (v_c_minor < 24) {
24642 *iop_a_dst++ = wuffs_base__make_token(
24643 (((uint64_t)(WUFFS_CBOR__LITERALS[(v_c_minor & 3)])) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24644 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24645 goto label__goto_parsed_a_leaf_value__break;
24646 } else if (v_c_minor == 24) {
24647 if (v_string_length < 24) {
24648 if ( ! (iop_a_src > io1_a_src)) {
24649 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
24650 goto exit;
24651 }
24652 iop_a_src--;
24653 goto label__goto_fail__break;
24654 }
24655 *iop_a_dst++ = wuffs_base__make_token(
24656 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
24657 (((uint64_t)((8388608 | ((uint32_t)((v_string_length & 255)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24658 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24659 goto label__goto_parsed_a_leaf_value__break;
24660 } else if (v_c_minor < 28) {
24661 *iop_a_dst++ = wuffs_base__make_token(
24662 (((uint64_t)(10490113)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24663 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24664 goto label__goto_parsed_a_leaf_value__break;
24665 } else if (v_c_minor == 31) {
24666 if (v_tagged || (v_depth <= 0)) {
24667 goto label__goto_fail__break;
24668 }
24669 v_depth -= 1;
24670 if (self->private_data.f_container_num_remaining[v_depth] != 0) {
24671 goto label__goto_fail__break;
24672 }
24673 v_stack_byte = (v_depth / 16);
24674 v_stack_bit = ((v_depth & 15) * 2);
24675 v_stack_val = (3 & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit));
24676 if (v_stack_val == 1) {
24677 goto label__goto_fail__break;
24678 }
24679 if (v_stack_val != 3) {
24680 v_vminor_alt = 2097186;
24681 } else {
24682 v_vminor_alt = 2097218;
24683 }
24684 if (v_depth <= 0) {
24685 v_vminor_alt |= 4096;
24686 } else {
24687 v_stack_byte = ((v_depth - 1) / 16);
24688 v_stack_bit = (((v_depth - 1) & 15) * 2);
24689 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
24690 v_vminor_alt |= 8192;
24691 } else {
24692 v_vminor_alt |= 16384;
24693 }
24694 }
24695 *iop_a_dst++ = wuffs_base__make_token(
24696 (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24697 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24698 goto label__goto_parsed_a_leaf_value__break;
24699 }
24700 }
24701 goto label__goto_fail__break;
24702 }
24703 label__goto_fail__break:;
24704 if (iop_a_src > io1_a_src) {
24705 iop_a_src--;
24706 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
24707 goto exit;
24708 }
24709 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
24710 goto exit;
24711 }
24712 label__goto_parsed_a_leaf_value__break:;
24713 v_tagged = false;
24714 while (v_depth > 0) {
24715 v_stack_byte = ((v_depth - 1) / 16);
24716 v_stack_bit = (((v_depth - 1) & 15) * 2);
24717 self->private_data.f_stack[v_stack_byte] ^= (((uint32_t)(1)) << (v_stack_bit + 1));
24718 if (1 == (3 & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit))) {
24719 goto label__outer__continue;
24720 }
24721 if (self->private_data.f_container_num_remaining[(v_depth - 1)] <= 0) {
24722 goto label__outer__continue;
24723 }
24724 self->private_data.f_container_num_remaining[(v_depth - 1)] -= 1;
24725 if (self->private_data.f_container_num_remaining[(v_depth - 1)] > 0) {
24726 goto label__outer__continue;
24727 }
24728 label__2__continue:;
24729 while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
24730 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
24731 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
24732 goto label__2__continue;
24733 }
24734 v_depth -= 1;
24735 v_stack_byte = (v_depth / 16);
24736 v_stack_bit = ((v_depth & 15) * 2);
24737 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
24738 v_vminor_alt = 2097186;
24739 } else {
24740 v_vminor_alt = 2097218;
24741 }
24742 if (v_depth <= 0) {
24743 v_vminor_alt |= 4096;
24744 } else {
24745 v_stack_byte = ((v_depth - 1) / 16);
24746 v_stack_bit = (((v_depth - 1) & 15) * 2);
24747 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
24748 v_vminor_alt |= 8192;
24749 } else {
24750 v_vminor_alt |= 16384;
24751 }
24752 }
24753 *iop_a_dst++ = wuffs_base__make_token(
24754 (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
24755 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
24756 }
24757 goto label__outer__break;
24758 }
24759 label__outer__break:;
24760 self->private_impl.f_end_of_data = true;
24761
Nigel Taoe360a532021-04-05 22:47:03 +100024762 ok:
24763 self->private_impl.p_decode_tokens[0] = 0;
24764 goto exit;
24765 }
24766
24767 goto suspend;
24768 suspend:
24769 self->private_impl.p_decode_tokens[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
24770 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
24771 self->private_data.s_decode_tokens[0].v_string_length = v_string_length;
24772 self->private_data.s_decode_tokens[0].v_depth = v_depth;
24773 self->private_data.s_decode_tokens[0].v_token_length = v_token_length;
24774 self->private_data.s_decode_tokens[0].v_tagged = v_tagged;
24775 self->private_data.s_decode_tokens[0].v_indefinite_string_major_type = v_indefinite_string_major_type;
24776
24777 goto exit;
24778 exit:
24779 if (a_dst) {
24780 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
24781 }
24782 if (a_src) {
24783 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
24784 }
24785
24786 if (wuffs_base__status__is_error(&status)) {
24787 self->private_impl.magic = WUFFS_BASE__DISABLED;
24788 }
24789 return status;
24790}
24791
24792#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR)
24793
24794#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32)
24795
24796// ---------------- Status Codes Implementations
24797
24798// ---------------- Private Consts
24799
24800static const uint32_t
24801WUFFS_CRC32__IEEE_TABLE[16][256] WUFFS_BASE__POTENTIALLY_UNUSED = {
24802 {
24803 0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035,
24804 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049,
24805 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639,
24806 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317,
24807 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443,
24808 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665,
24809 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303,
24810 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565,
24811 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059,
24812 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297,
24813 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223,
24814 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405,
24815 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995,
24816 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649,
24817 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015,
24818 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989,
24819 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523,
24820 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377,
24821 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879,
24822 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637,
24823 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859,
24824 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161,
24825 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815,
24826 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221,
24827 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371,
24828 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881,
24829 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567,
24830 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701,
24831 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035,
24832 2932959818, 3654703836, 1088359270, 936918000, 2847714899, 3736837829, 1202900863, 817233897,
24833 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431,
24834 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117,
24835 }, {
24836 0, 421212481, 842424962, 724390851, 1684849924, 2105013317, 1448781702, 1329698503,
24837 3369699848, 3519200073, 4210026634, 3824474571, 2897563404, 3048111693, 2659397006, 2274893007,
24838 1254232657, 1406739216, 2029285587, 1643069842, 783210325, 934667796, 479770071, 92505238,
24839 2182846553, 2600511768, 2955803355, 2838940570, 3866582365, 4285295644, 3561045983, 3445231262,
24840 2508465314, 2359236067, 2813478432, 3198777185, 4058571174, 3908292839, 3286139684, 3670389349,
24841 1566420650, 1145479147, 1869335592, 1987116393, 959540142, 539646703, 185010476, 303839341,
24842 3745920755, 3327985586, 3983561841, 4100678960, 3140154359, 2721170102, 2300350837, 2416418868,
24843 396344571, 243568058, 631889529, 1018359608, 1945336319, 1793607870, 1103436669, 1490954812,
24844 4034481925, 3915546180, 3259968903, 3679722694, 2484439553, 2366552896, 2787371139, 3208174018,
24845 950060301, 565965900, 177645455, 328046286, 1556873225, 1171730760, 1861902987, 2011255754,
24846 3132841300, 2745199637, 2290958294, 2442530455, 3738671184, 3352078609, 3974232786, 4126854035,
24847 1919080284, 1803150877, 1079293406, 1498383519, 370020952, 253043481, 607678682, 1025720731,
24848 1711106983, 2095471334, 1472923941, 1322268772, 26324643, 411738082, 866634785, 717028704,
24849 2904875439, 3024081134, 2668790573, 2248782444, 3376948395, 3495106026, 4219356713, 3798300520,
24850 792689142, 908347575, 487136116, 68299317, 1263779058, 1380486579, 2036719216, 1618931505,
24851 3890672638, 4278043327, 3587215740, 3435896893, 2206873338, 2593195963, 2981909624, 2829542713,
24852 998479947, 580430090, 162921161, 279890824, 1609522511, 1190423566, 1842954189, 1958874764,
24853 4082766403, 3930137346, 3245109441, 3631694208, 2536953671, 2385372678, 2768287173, 3155920004,
24854 1900120602, 1750776667, 1131931800, 1517083097, 355290910, 204897887, 656092572, 1040194781,
24855 3113746450, 2692952403, 2343461520, 2461357009, 3723805974, 3304059991, 4022511508, 4141455061,
24856 2919742697, 3072101800, 2620513899, 2234183466, 3396041197, 3547351212, 4166851439, 3779471918,
24857 1725839073, 2143618976, 1424512099, 1307796770, 45282277, 464110244, 813994343, 698327078,
24858 3838160568, 4259225593, 3606301754, 3488152955, 2158586812, 2578602749, 2996767038, 2877569151,
24859 740041904, 889656817, 506086962, 120682355, 1215357364, 1366020341, 2051441462, 1667084919,
24860 3422213966, 3538019855, 4190942668, 3772220557, 2945847882, 3062702859, 2644537544, 2226864521,
24861 52649286, 439905287, 823476164, 672009861, 1733269570, 2119477507, 1434057408, 1281543041,
24862 2167981343, 2552493150, 3004082077, 2853541596, 3847487515, 4233048410, 3613549209, 3464057816,
24863 1239502615, 1358593622, 2077699477, 1657543892, 764250643, 882293586, 532408465, 111204816,
24864 1585378284, 1197851309, 1816695150, 1968414767, 974272232, 587794345, 136598634, 289367339,
24865 2527558116, 2411481253, 2760973158, 3179948583, 4073438432, 3956313505, 3237863010, 3655790371,
24866 347922877, 229101820, 646611775, 1066513022, 1892689081, 1774917112, 1122387515, 1543337850,
24867 3697634229, 3313392372, 3998419255, 4148705398, 3087642289, 2702352368, 2319436851, 2468674930,
24868 }, {
24869 0, 29518391, 59036782, 38190681, 118073564, 114017003, 76381362, 89069189,
24870 236147128, 265370511, 228034006, 206958561, 152762724, 148411219, 178138378, 190596925,
24871 472294256, 501532999, 530741022, 509615401, 456068012, 451764635, 413917122, 426358261,
24872 305525448, 334993663, 296822438, 275991697, 356276756, 352202787, 381193850, 393929805,
24873 944588512, 965684439, 1003065998, 973863097, 1061482044, 1049003019, 1019230802, 1023561829,
24874 912136024, 933002607, 903529270, 874031361, 827834244, 815125939, 852716522, 856752605,
24875 611050896, 631869351, 669987326, 640506825, 593644876, 580921211, 551983394, 556069653,
24876 712553512, 733666847, 704405574, 675154545, 762387700, 749958851, 787859610, 792175277,
24877 1889177024, 1901651959, 1931368878, 1927033753, 2006131996, 1985040171, 1947726194, 1976933189,
24878 2122964088, 2135668303, 2098006038, 2093965857, 2038461604, 2017599123, 2047123658, 2076625661,
24879 1824272048, 1836991623, 1866005214, 1861914857, 1807058540, 1786244187, 1748062722, 1777547317,
24880 1655668488, 1668093247, 1630251878, 1625932113, 1705433044, 1684323811, 1713505210, 1742760333,
24881 1222101792, 1226154263, 1263738702, 1251046777, 1339974652, 1310460363, 1281013650, 1301863845,
24882 1187289752, 1191637167, 1161842422, 1149379777, 1103966788, 1074747507, 1112139306, 1133218845,
24883 1425107024, 1429406311, 1467333694, 1454888457, 1408811148, 1379576507, 1350309090, 1371438805,
24884 1524775400, 1528845279, 1499917702, 1487177649, 1575719220, 1546255107, 1584350554, 1605185389,
24885 3778354048, 3774312887, 3803303918, 3816007129, 3862737756, 3892238699, 3854067506, 3833203973,
24886 4012263992, 4007927823, 3970080342, 3982554209, 3895452388, 3924658387, 3953866378, 3932773565,
24887 4245928176, 4241609415, 4271336606, 4283762345, 4196012076, 4225268251, 4187931714, 4166823541,
24888 4076923208, 4072833919, 4035198246, 4047918865, 4094247316, 4123732899, 4153251322, 4132437965,
24889 3648544096, 3636082519, 3673983246, 3678331705, 3732010428, 3753090955, 3723829714, 3694611429,
24890 3614117080, 3601426159, 3572488374, 3576541825, 3496125444, 3516976691, 3555094634, 3525581405,
24891 3311336976, 3298595879, 3336186494, 3340255305, 3260503756, 3281337595, 3251864226, 3222399125,
24892 3410866088, 3398419871, 3368647622, 3372945905, 3427010420, 3448139075, 3485520666, 3456284973,
24893 2444203584, 2423127159, 2452308526, 2481530905, 2527477404, 2539934891, 2502093554, 2497740997,
24894 2679949304, 2659102159, 2620920726, 2650438049, 2562027300, 2574714131, 2603727690, 2599670141,
24895 2374579504, 2353749767, 2383274334, 2412743529, 2323684844, 2336421851, 2298759554, 2294686645,
24896 2207933576, 2186809023, 2149495014, 2178734801, 2224278612, 2236720739, 2266437690, 2262135309,
24897 2850214048, 2820717207, 2858812622, 2879680249, 2934667388, 2938704459, 2909776914, 2897069605,
24898 2817622296, 2788420399, 2759153014, 2780249921, 2700618180, 2704950259, 2742877610, 2730399645,
24899 3049550800, 3020298727, 3057690558, 3078802825, 2999835404, 3004150075, 2974355298, 2961925461,
24900 3151438440, 3121956959, 3092510214, 3113327665, 3168701108, 3172786307, 3210370778, 3197646061,
24901 }, {
24902 0, 3099354981, 2852767883, 313896942, 2405603159, 937357362, 627793884, 2648127673,
24903 3316918511, 2097696650, 1874714724, 3607201537, 1255587768, 4067088605, 3772741427, 1482887254,
24904 1343838111, 3903140090, 4195393300, 1118632049, 3749429448, 1741137837, 1970407491, 3452858150,
24905 2511175536, 756094997, 1067759611, 2266550430, 449832999, 2725482306, 2965774508, 142231497,
24906 2687676222, 412010587, 171665333, 2995192016, 793786473, 2548850444, 2237264098, 1038456711,
24907 1703315409, 3711623348, 3482275674, 1999841343, 3940814982, 1381529571, 1089329165, 4166106984,
24908 4029413537, 1217896388, 1512189994, 3802027855, 2135519222, 3354724499, 3577784189, 1845280792,
24909 899665998, 2367928107, 2677414085, 657096608, 3137160985, 37822588, 284462994, 2823350519,
24910 2601801789, 598228824, 824021174, 2309093331, 343330666, 2898962447, 3195996129, 113467524,
24911 1587572946, 3860600759, 4104763481, 1276501820, 3519211397, 1769898208, 2076913422, 3279374443,
24912 3406630818, 1941006535, 1627703081, 3652755532, 1148164341, 4241751952, 3999682686, 1457141531,
24913 247015245, 3053797416, 2763059142, 470583459, 2178658330, 963106687, 735213713, 2473467892,
24914 992409347, 2207944806, 2435792776, 697522413, 3024379988, 217581361, 508405983, 2800865210,
24915 4271038444, 1177467017, 1419450215, 3962007554, 1911572667, 3377213406, 3690561584, 1665525589,
24916 1799331996, 3548628985, 3241568279, 2039091058, 3831314379, 1558270126, 1314193216, 4142438437,
24917 2928380019, 372764438, 75645176, 3158189981, 568925988, 2572515393, 2346768303, 861712586,
24918 3982079547, 1441124702, 1196457648, 4293663189, 1648042348, 3666298377, 3358779879, 1888390786,
24919 686661332, 2421291441, 2196002399, 978858298, 2811169155, 523464422, 226935048, 3040519789,
24920 3175145892, 100435649, 390670639, 2952089162, 841119475, 2325614998, 2553003640, 546822429,
24921 2029308235, 3225988654, 3539796416, 1782671013, 4153826844, 1328167289, 1570739863, 3844338162,
24922 1298864389, 4124540512, 3882013070, 1608431339, 3255406162, 2058742071, 1744848601, 3501990332,
24923 2296328682, 811816591, 584513889, 2590678532, 129869501, 3204563416, 2914283062, 352848211,
24924 494030490, 2781751807, 3078325777, 264757620, 2450577869, 715964072, 941166918, 2158327331,
24925 3636881013, 1618608400, 1926213374, 3396585883, 1470427426, 4011365959, 4255988137, 1158766284,
24926 1984818694, 3471935843, 3695453837, 1693991400, 4180638033, 1100160564, 1395044826, 3952793279,
24927 3019491049, 189112716, 435162722, 2706139399, 1016811966, 2217162459, 2526189877, 774831696,
24928 643086745, 2666061564, 2354934034, 887166583, 2838900430, 294275499, 54519365, 3145957664,
24929 3823145334, 1532818963, 1240029693, 4048895640, 1820460577, 3560857924, 3331051178, 2117577167,
24930 3598663992, 1858283101, 2088143283, 3301633750, 1495127663, 3785470218, 4078182116, 1269332353,
24931 332098007, 2876706482, 3116540252, 25085497, 2628386432, 605395429, 916469259, 2384220526,
24932 2254837415, 1054503362, 745528876, 2496903497, 151290352, 2981684885, 2735556987, 464596510,
24933 1137851976, 4218313005, 3923506883, 1365741990, 3434129695, 1946996346, 1723425172, 3724871409,
24934 }, {
24935 0, 1029712304, 2059424608, 1201699536, 4118849216, 3370159984, 2403399072, 2988497936,
24936 812665793, 219177585, 1253054625, 2010132753, 3320900865, 4170237105, 3207642721, 2186319825,
24937 1625331586, 1568718386, 438355170, 658566482, 2506109250, 2818578674, 4020265506, 3535817618,
24938 1351670851, 1844508147, 709922595, 389064339, 2769320579, 2557498163, 3754961379, 3803185235,
24939 3250663172, 4238411444, 3137436772, 2254525908, 876710340, 153198708, 1317132964, 1944187668,
24940 4054934725, 3436268917, 2339452837, 3054575125, 70369797, 961670069, 2129760613, 1133623509,
24941 2703341702, 2621542710, 3689016294, 3867263574, 1419845190, 1774270454, 778128678, 318858390,
24942 2438067015, 2888948471, 3952189479, 3606153623, 1691440519, 1504803895, 504432359, 594620247,
24943 1492342857, 1704161785, 573770537, 525542041, 2910060169, 2417219385, 3618876905, 3939730521,
24944 1753420680, 1440954936, 306397416, 790849880, 2634265928, 2690882808, 3888375336, 3668168600,
24945 940822475, 91481723, 1121164459, 2142483739, 3448989963, 4042473659, 3075684971, 2318603227,
24946 140739594, 889433530, 1923340138, 1338244826, 4259521226, 3229813626, 2267247018, 3124975642,
24947 2570221389, 2756861693, 3824297005, 3734113693, 1823658381, 1372780605, 376603373, 722643805,
24948 2839690380, 2485261628, 3548540908, 4007806556, 1556257356, 1638052860, 637716780, 459464860,
24949 4191346895, 3300051327, 2199040943, 3195181599, 206718479, 825388991, 1989285231, 1274166495,
24950 3382881038, 4106388158, 3009607790, 2382549470, 1008864718, 21111934, 1189240494, 2072147742,
24951 2984685714, 2357631266, 3408323570, 4131834434, 1147541074, 2030452706, 1051084082, 63335554,
24952 2174155603, 3170292451, 4216760371, 3325460867, 1947622803, 1232499747, 248909555, 867575619,
24953 3506841360, 3966111392, 2881909872, 2527485376, 612794832, 434546784, 1581699760, 1663499008,
24954 3782634705, 3692447073, 2612412337, 2799048193, 351717905, 697754529, 1849071985, 1398190273,
24955 1881644950, 1296545318, 182963446, 931652934, 2242328918, 3100053734, 4284967478, 3255255942,
24956 1079497815, 2100821479, 983009079, 133672583, 3050795671, 2293717799, 3474399735, 4067887175,
24957 281479188, 765927844, 1778867060, 1466397380, 3846680276, 3626469220, 2676489652, 2733102084,
24958 548881365, 500656741, 1517752501, 1729575173, 3577210133, 3898068133, 2952246901, 2459410373,
24959 3910527195, 3564487019, 2480257979, 2931134987, 479546907, 569730987, 1716854139, 1530213579,
24960 3647316762, 3825568426, 2745561210, 2663766474, 753206746, 293940330, 1445287610, 1799716618,
24961 2314567513, 3029685993, 4080348217, 3461678473, 2088098201, 1091956777, 112560889, 1003856713,
24962 3112514712, 2229607720, 3276105720, 4263857736, 1275433560, 1902492648, 918929720, 195422344,
24963 685033439, 364179055, 1377080511, 1869921551, 3713294623, 3761522863, 2811507327, 2599689167,
24964 413436958, 633644462, 1650777982, 1594160846, 3978570462, 3494118254, 2548332990, 2860797966,
24965 1211387997, 1968470509, 854852413, 261368461, 3182753437, 2161434413, 3346310653, 4195650637,
24966 2017729436, 1160000044, 42223868, 1071931724, 2378480988, 2963576044, 4144295484, 3395602316,
24967 }, {
24968 0, 3411858341, 1304994059, 2257875630, 2609988118, 1355649459, 3596215069, 486879416,
24969 3964895853, 655315400, 2711298918, 1791488195, 2009251963, 3164476382, 973758832, 4048990933,
24970 64357019, 3364540734, 1310630800, 2235723829, 2554806413, 1394316072, 3582976390, 517157411,
24971 4018503926, 618222419, 2722963965, 1762783832, 1947517664, 3209171269, 970744811, 4068520014,
24972 128714038, 3438335635, 1248109629, 2167961496, 2621261600, 1466012805, 3522553387, 447296910,
24973 3959392091, 547575038, 2788632144, 1835791861, 1886307661, 3140622056, 1034314822, 4143626211,
24974 75106221, 3475428360, 1236444838, 2196665603, 2682996155, 1421317662, 3525567664, 427767573,
24975 3895035328, 594892389, 2782995659, 1857943406, 1941489622, 3101955187, 1047553757, 4113347960,
24976 257428076, 3288652233, 1116777319, 2311878850, 2496219258, 1603640287, 3640781169, 308099796,
24977 3809183745, 676813732, 2932025610, 1704983215, 2023410199, 3016104370, 894593820, 4262377657,
24978 210634999, 3352484690, 1095150076, 2316991065, 2535410401, 1547934020, 3671583722, 294336591,
24979 3772615322, 729897279, 2903845777, 1716123700, 2068629644, 2953845545, 914647431, 4258839074,
24980 150212442, 3282623743, 1161604689, 2388688372, 2472889676, 1480171241, 3735940167, 368132066,
24981 3836185911, 805002898, 2842635324, 1647574937, 2134298401, 3026852996, 855535146, 4188192143,
24982 186781121, 3229539940, 1189784778, 2377547631, 2427670487, 1542429810, 3715886812, 371670393,
24983 3882979244, 741170185, 2864262823, 1642462466, 2095107514, 3082559007, 824732849, 4201955092,
24984 514856152, 3589064573, 1400419795, 2552522358, 2233554638, 1316849003, 3370776517, 62202976,
24985 4075001525, 968836368, 3207280574, 1954014235, 1769133219, 2720925446, 616199592, 4024870413,
24986 493229635, 3594175974, 1353627464, 2616354029, 2264355925, 1303087088, 3409966430, 6498043,
24987 4046820398, 979978123, 3170710821, 2007099008, 1789187640, 2717386141, 661419827, 3962610838,
24988 421269998, 3527459403, 1423225061, 2676515648, 2190300152, 1238466653, 3477467891, 68755798,
24989 4115633027, 1041448998, 3095868040, 1943789869, 1860096405, 2776760880, 588673182, 3897205563,
24990 449450869, 3516317904, 1459794558, 2623431131, 2170245475, 1242006214, 3432247400, 131015629,
24991 4137259288, 1036337853, 3142660115, 1879958454, 1829294862, 2790523051, 549483013, 3952910752,
24992 300424884, 3669282065, 1545650111, 2541513754, 2323209378, 1092980487, 3350330793, 216870412,
24993 4256931033, 921128828, 2960342482, 2066738807, 1714085583, 2910195050, 736264132, 3770592353,
24994 306060335, 3647131530, 1610005796, 2494197377, 2309971513, 1123257756, 3295149874, 255536279,
24995 4268596802, 892423655, 3013951305, 2029645036, 1711070292, 2929725425, 674528607, 3815288570,
24996 373562242, 3709388839, 1535949449, 2429577516, 2379569556, 1183418929, 3223189663, 188820282,
24997 4195850735, 827017802, 3084859620, 2089020225, 1636228089, 2866415708, 743340786, 3876759895,
24998 361896217, 3738094268, 1482340370, 2466671543, 2382584591, 1163888810, 3284924932, 144124321,
24999 4190215028, 849168593, 3020503679, 2136336858, 1649465698, 2836138695, 798521449, 3838094284,
25000 }, {
25001 0, 2792819636, 2543784233, 837294749, 4098827283, 1379413927, 1674589498, 3316072078,
25002 871321191, 2509784531, 2758827854, 34034938, 3349178996, 1641505216, 1346337629, 4131942633,
25003 1742642382, 3249117050, 4030828007, 1446413907, 2475800797, 904311657, 68069876, 2725880384,
25004 1412551337, 4064729373, 3283010432, 1708771380, 2692675258, 101317902, 937551763, 2442587175,
25005 3485284764, 1774858792, 1478633653, 4266992385, 1005723023, 2642744891, 2892827814, 169477906,
25006 4233263099, 1512406095, 1808623314, 3451546982, 136139752, 2926205020, 2676114113, 972376437,
25007 2825102674, 236236518, 1073525883, 2576072655, 1546420545, 4200303349, 3417542760, 1841601500,
25008 2609703733, 1039917185, 202635804, 2858742184, 1875103526, 3384067218, 4166835727, 1579931067,
25009 1141601657, 3799809741, 3549717584, 1977839588, 2957267306, 372464350, 668680259, 2175552503,
25010 2011446046, 3516084394, 3766168119, 1175200131, 2209029901, 635180217, 338955812, 2990736784,
25011 601221559, 2242044419, 3024812190, 306049834, 3617246628, 1911408144, 1074125965, 3866285881,
25012 272279504, 3058543716, 2275784441, 567459149, 3832906691, 1107462263, 1944752874, 3583875422,
25013 2343980261, 767641425, 472473036, 3126744696, 2147051766, 3649987394, 3899029983, 1309766251,
25014 3092841090, 506333494, 801510315, 2310084639, 1276520081, 3932237093, 3683203000, 2113813516,
25015 3966292011, 1243601823, 2079834370, 3716205238, 405271608, 3192979340, 2411259153, 701492901,
25016 3750207052, 2045810168, 1209569125, 4000285905, 734575199, 2378150379, 3159862134, 438345922,
25017 2283203314, 778166598, 529136603, 3120492655, 2086260449, 3660498261, 3955679176, 1303499900,
25018 3153699989, 495890209, 744928700, 2316418568, 1337360518, 3921775410, 3626602927, 2120129051,
25019 4022892092, 1237286280, 2018993941, 3726666913, 461853231, 3186645403, 2350400262, 711936178,
25020 3693557851, 2052076527, 1270360434, 3989775046, 677911624, 2384402428, 3220639073, 427820757,
25021 1202443118, 3789347034, 3493118535, 1984154099, 3018127229, 362020041, 612099668, 2181885408,
25022 1950653705, 3526596285, 3822816288, 1168934804, 2148251930, 645706414, 395618355, 2984485767,
25023 544559008, 2248295444, 3085590153, 295523645, 3560598451, 1917673479, 1134918298, 3855773998,
25024 328860103, 3052210803, 2214924526, 577903450, 3889505748, 1101147744, 1883911421, 3594338121,
25025 3424493451, 1785369663, 1535282850, 4260726038, 944946072, 2653270060, 2949491377, 163225861,
25026 4294103532, 1501944408, 1752023237, 3457862513, 196998655, 2915761739, 2619532502, 978710370,
25027 2881684293, 229902577, 1012666988, 2586515928, 1603020630, 4193987810, 3356702335, 1852063179,
25028 2553040162, 1046169238, 263412747, 2848217023, 1818454321, 3390333573, 4227627032, 1569420204,
25029 60859927, 2782375331, 2487203646, 843627658, 4159668740, 1368951216, 1617990445, 3322386585,
25030 810543216, 2520310724, 2815490393, 27783917, 3288386659, 1652017111, 1402985802, 4125677310,
25031 1685994201, 3255382381, 4091620336, 1435902020, 2419138250, 910562686, 128847843, 2715354199,
25032 1469150398, 4058414858, 3222168983, 1719234083, 2749255853, 94984985, 876691844, 2453031472,
25033 }, {
25034 0, 3433693342, 1109723005, 2391738339, 2219446010, 1222643300, 3329165703, 180685081,
25035 3555007413, 525277995, 2445286600, 1567235158, 1471092047, 2600801745, 361370162, 3642757804,
25036 2092642603, 2953916853, 1050555990, 4063508168, 4176560081, 878395215, 3134470316, 1987983410,
25037 2942184094, 1676945920, 3984272867, 567356797, 722740324, 3887998202, 1764827929, 2778407815,
25038 4185285206, 903635656, 3142804779, 2012833205, 2101111980, 2979425330, 1058630609, 4088621903,
25039 714308067, 3862526333, 1756790430, 2753330688, 2933487385, 1651734407, 3975966820, 542535930,
25040 2244825981, 1231508451, 3353891840, 188896414, 25648519, 3442302233, 1134713594, 2399689316,
25041 1445480648, 2592229462, 336416693, 3634843435, 3529655858, 516441772, 2420588879, 1559052753,
25042 698204909, 3845636723, 1807271312, 2803025166, 2916600855, 1635634313, 4025666410, 593021940,
25043 4202223960, 919787974, 3093159461, 1962401467, 2117261218, 2996361020, 1008193759, 4038971457,
25044 1428616134, 2576151384, 386135227, 3685348389, 3513580860, 499580322, 2471098945, 1608776415,
25045 2260985971, 1248454893, 3303468814, 139259792, 42591881, 3458459159, 1085071860, 2349261162,
25046 3505103035, 474062885, 2463016902, 1583654744, 1419882049, 2550902495, 377792828, 3660491170,
25047 51297038, 3483679632, 1093385331, 2374089965, 2269427188, 1273935210, 3311514249, 164344343,
25048 2890961296, 1627033870, 4000683757, 585078387, 672833386, 3836780532, 1782552599, 2794821769,
25049 2142603813, 3005188795, 1032883544, 4047146438, 4227826911, 928351297, 3118105506, 1970307900,
25050 1396409818, 2677114180, 287212199, 3719594553, 3614542624, 467372990, 2505346141, 1509854403,
25051 2162073199, 1282711281, 3271268626, 240228748, 76845205, 3359543307, 1186043880, 2317064054,
25052 796964081, 3811226735, 1839575948, 2702160658, 2882189835, 1734392469, 3924802934, 625327592,
25053 4234522436, 818917338, 3191908409, 1927981223, 2016387518, 3028656416, 973776579, 4137723485,
25054 2857232268, 1726474002, 3899187441, 616751215, 772270454, 3803048424, 1814228491, 2693328533,
25055 2041117753, 3036871847, 999160644, 4146592730, 4259508931, 826864221, 3217552830, 1936586016,
25056 3606501031, 442291769, 2496909786, 1484378436, 1388107869, 2652297411, 278519584, 3694387134,
25057 85183762, 3384397196, 1194773103, 2342308593, 2170143720, 1307820918, 3279733909, 265733131,
25058 2057717559, 3054258089, 948125770, 4096344276, 4276898253, 843467091, 3167309488, 1885556270,
25059 2839764098, 1709792284, 3949353983, 667704161, 755585656, 3785577190, 1865176325, 2743489947,
25060 102594076, 3401021058, 1144549729, 2291298815, 2186770662, 1325234296, 3228729243, 215514885,
25061 3589828009, 424832311, 2547870420, 1534552650, 1370645331, 2635621325, 328688686, 3745342640,
25062 2211456353, 1333405183, 3254067740, 224338562, 127544219, 3408931589, 1170156774, 2299866232,
25063 1345666772, 2627681866, 303053225, 3736746295, 3565105198, 416624816, 2522494803, 1525692365,
25064 4285207626, 868291796, 3176010551, 1910772649, 2065767088, 3079346734, 956571085, 4121828691,
25065 747507711, 3760459617, 1856702594, 2717976604, 2831417605, 1684930971, 3940615800, 642451174,
25066 },
25067 {
25068 0, 393942083, 787884166, 965557445, 1575768332, 1251427663, 1931114890, 1684106697,
25069 3151536664, 2896410203, 2502855326, 2186649309, 3862229780, 4048545623, 3368213394, 3753496529,
25070 2898281073, 3149616690, 2184604407, 2504883892, 4046197629, 3864463166, 3755621371, 3366006712,
25071 387506281, 6550570, 971950319, 781573292, 1257550181, 1569695014, 1677892067, 1937345952,
25072 2196865699, 2508887776, 2886183461, 3145514598, 3743273903, 3362179052, 4058774313, 3868258154,
25073 958996667, 777139448, 400492605, 10755198, 1690661303, 1941857780, 1244879153, 1565019506,
25074 775012562, 961205393, 13101140, 398261271, 1943900638, 1688634781, 1563146584, 1246801179,
25075 2515100362, 2190636681, 3139390028, 2892258831, 3355784134, 3749586821, 3874691904, 4052225795,
25076 3734110983, 3387496260, 4033096577, 3877584834, 2206093835, 2483373640, 2911402637, 3136515790,
25077 1699389727, 1915860316, 1270647193, 1556585946, 950464531, 803071056, 374397077, 19647702,
25078 1917993334, 1697207605, 1554278896, 1272937907, 800985210, 952435769, 21510396, 372452543,
25079 3381322606, 3740399405, 3883715560, 4027047851, 2489758306, 2199758369, 3130039012, 2917895847,
25080 1550025124, 1259902439, 1922410786, 1710144865, 26202280, 385139947, 796522542, 939715693,
25081 3887801276, 4039129087, 3377269562, 3728088953, 3126293168, 2905368307, 2493602358, 2212122229,
25082 4037264341, 3889747862, 3730172755, 3375300368, 2907673305, 3124004506, 2209987167, 2495786524,
25083 1266377165, 1543533966, 1703758155, 1928748296, 379007169, 32253058, 945887303, 790236164,
25084 1716846671, 1898845196, 1218652361, 1608006794, 1002000707, 750929152, 357530053, 36990342,
25085 3717046871, 3405166100, 4084959953, 3825245842, 2153902939, 2535122712, 2929187805, 3119304606,
25086 3398779454, 3723384445, 3831720632, 4078468859, 2541294386, 2147616625, 3113171892, 2935238647,
25087 1900929062, 1714877541, 1606142112, 1220599011, 748794154, 1004184937, 39295404, 355241455,
25088 3835986668, 4091516591, 3394415210, 3710500393, 3108557792, 2922629027, 2545875814, 2160455461,
25089 1601970420, 1208431799, 1904871538, 1727077425, 43020792, 367748539, 744905086, 991776061,
25090 1214562461, 1595921630, 1720903707, 1911159896, 361271697, 49513938, 998160663, 738569556,
25091 4089209477, 3838277318, 3712633347, 3392233024, 2924491657, 3106613194, 2158369551, 2547846988,
25092 3100050248, 2948339467, 2519804878, 2169126797, 3844821572, 4065347079, 3420289730, 3701894785,
25093 52404560, 342144275, 770279894, 982687125, 1593045084, 1233708063, 1879431386, 1736363161,
25094 336019769, 58479994, 988899775, 764050940, 1240141877, 1586496630, 1729968307, 1885744368,
25095 2950685473, 3097818978, 2166999975, 2522013668, 4063474221, 3846743662, 3703937707, 3418263272,
25096 976650731, 760059304, 348170605, 62635310, 1742393575, 1889649828, 1227683937, 1582820386,
25097 2179867635, 2526361520, 2937588597, 3093503798, 3691148031, 3413731004, 4076100217, 3851374138,
25098 2532754330, 2173556697, 3087067932, 2944139103, 3407516310, 3697379029, 3857496592, 4070026835,
25099 758014338, 978679233, 64506116, 346250567, 1891774606, 1740186829, 1580472328, 1229917259,
25100 }, {
25101 0, 4022496062, 83218493, 3946298115, 166436986, 3861498692, 220098631, 3806075769,
25102 332873972, 4229245898, 388141257, 4175494135, 440197262, 4127099824, 516501683, 4044053389,
25103 665747944, 3362581206, 593187285, 3432594155, 776282514, 3246869164, 716239279, 3312622225,
25104 880394524, 3686509090, 814485793, 3746462239, 1033003366, 3528460888, 963096923, 3601193573,
25105 1331495888, 2694801646, 1269355501, 2758457555, 1186374570, 2843003028, 1111716759, 2910918825,
25106 1552565028, 3007850522, 1484755737, 3082680359, 1432478558, 3131279456, 1368666979, 3193329757,
25107 1760789048, 2268195078, 1812353541, 2210675003, 1628971586, 2396670332, 1710092927, 2318375233,
25108 2066006732, 2498144754, 2144408305, 2417195471, 1926193846, 2634877320, 1983558283, 2583222709,
25109 2662991776, 1903717534, 2588923805, 1972223139, 2538711002, 2022952164, 2477029351, 2087066841,
25110 2372749140, 1655647338, 2308478825, 1717238871, 2223433518, 1799654416, 2155034387, 1873894445,
25111 3105130056, 1456926070, 3185661557, 1378041163, 2969511474, 1597852940, 3020617231, 1539874097,
25112 2864957116, 1157737858, 2922780289, 1106542015, 2737333958, 1290407416, 2816325371, 1210047941,
25113 3521578096, 1042640718, 3574781005, 986759027, 3624707082, 936300340, 3707335735, 859512585,
25114 3257943172, 770846650, 3334837433, 688390023, 3420185854, 605654976, 3475911875, 552361981,
25115 4132013464, 428600998, 4072428965, 494812827, 4288816610, 274747100, 4216845791, 345349857,
25116 3852387692, 173846098, 3781891409, 245988975, 3967116566, 62328360, 3900749099, 121822741,
25117 3859089665, 164061759, 3807435068, 221426178, 4025395579, 2933317, 3944446278, 81334904,
25118 4124199413, 437265099, 4045904328, 518386422, 4231653775, 335250097, 4174133682, 386814604,
25119 3249244393, 778691543, 3311294676, 714879978, 3359647891, 662848429, 3434477742, 595039120,
25120 3531393053, 1035903779, 3599308832, 961245982, 3684132967, 877986649, 3747788890, 815846244,
25121 2841119441, 1184522735, 2913852140, 1114616274, 2696129195, 1332855189, 2756082326, 1266946472,
25122 3129952805, 1431118107, 3195705880, 1371074854, 3009735263, 1554415969, 3079748194, 1481855324,
25123 2398522169, 1630855175, 2315475716, 1707159610, 2266835779, 1759461501, 2213084030, 1814728768,
25124 2636237773, 1927520499, 2580814832, 1981182158, 2496293815, 2064121993, 2420095882, 2147340468,
25125 2025787041, 2541577631, 2085281436, 2475210146, 1901375195, 2660681189, 1973518054, 2590184920,
25126 1801997909, 2225743211, 1872600680, 2153772374, 1652813359, 2369881361, 1719025170, 2310296876,
25127 1594986313, 2966676599, 1541693300, 3022402634, 1459236659, 3107472397, 1376780046, 3184366640,
25128 1288097725, 2734990467, 1211309952, 2817619134, 1160605639, 2867791097, 1104723962, 2920993988,
25129 937561457, 3626001999, 857201996, 3704993394, 1040821515, 3519792693, 989625654, 3577615880,
25130 607473029, 3421972155, 549494200, 3473077894, 769584639, 3256649409, 690699714, 3337180924,
25131 273452185, 4287555495, 347692196, 4219156378, 430386403, 4133832669, 491977950, 4069562336,
25132 60542061, 3965298515, 124656720, 3903616878, 175139863, 3853649705, 243645482, 3779581716,
25133 }, {
25134 0, 3247366080, 1483520449, 2581751297, 2967040898, 1901571138, 3904227907, 691737987,
25135 3133399365, 2068659845, 3803142276, 589399876, 169513671, 3415493895, 1383475974, 2482566342,
25136 2935407819, 1870142219, 4137319690, 924099274, 506443593, 3751897225, 1178799752, 2278412616,
25137 339027342, 3585866318, 1280941135, 2379694991, 2766951948, 1700956620, 4236308429, 1024339981,
25138 2258407383, 1192382487, 3740284438, 528411094, 910556245, 4157285269, 1848198548, 2946996820,
25139 1012887186, 4258378066, 1681119059, 2780629139, 2357599504, 1292419792, 3572147409, 358906641,
25140 678054684, 3924071644, 1879503581, 2978491677, 2561882270, 1497229150, 3235873119, 22109855,
25141 2460592729, 1395094937, 3401913240, 189516888, 577821147, 3825075739, 2048679962, 3146956762,
25142 3595049455, 398902831, 2384764974, 1336573934, 1720805997, 2803873197, 1056822188, 4285729900,
25143 1821112490, 2902796138, 887570795, 4117339819, 3696397096, 500978920, 2218668777, 1169222953,
25144 2025774372, 3106931428, 550659301, 3780950821, 3362238118, 166293862, 2416645991, 1367722151,
25145 3262987361, 66315169, 2584839584, 1537170016, 1923370979, 3005911075, 717813282, 3947244002,
25146 1356109368, 2438613496, 146288633, 3375820857, 3759007162, 562248314, 3093388411, 2045739963,
25147 3927406461, 731490493, 2994458300, 1945440636, 1523451135, 2604718911, 44219710, 3274466046,
25148 4263662323, 1068272947, 2790189874, 1740649714, 1325080945, 2406874801, 379033776, 3608758128,
25149 1155642294, 2238671990, 479005303, 3708016055, 4097359924, 901128180, 2891217397, 1843045941,
25150 2011248031, 3060787807, 797805662, 3993195422, 3342353949, 112630237, 2673147868, 1591353372,
25151 3441611994, 212601626, 2504944923, 1421914843, 2113644376, 3161815192, 630660761, 3826893145,
25152 3642224980, 412692116, 2172340373, 1089836885, 1775141590, 2822790422, 832715543, 4029474007,
25153 1674842129, 2723860433, 1001957840, 4197873168, 3540870035, 310623315, 2338445906, 1257178514,
25154 4051548744, 821257608, 2836464521, 1755307081, 1101318602, 2150241802, 432566283, 3628511179,
25155 1270766349, 2318435533, 332587724, 3529260300, 4217841807, 988411727, 2735444302, 1652903566,
25156 1602977411, 2651169091, 132630338, 3328776322, 4015131905, 786223809, 3074340032, 1991273216,
25157 3846741958, 616972294, 3173262855, 2091579847, 1435626564, 2485072772, 234706309, 3430124101,
25158 2712218736, 1613231024, 4190475697, 944458353, 292577266, 3506339890, 1226630707, 2291284467,
25159 459984181, 3672380149, 1124496628, 2189994804, 2880683703, 1782407543, 4091479926, 844224694,
25160 257943739, 3469817723, 1462980986, 2529005242, 3213269817, 2114471161, 3890881272, 644152632,
25161 3046902270, 1947391550, 3991973951, 746483711, 88439420, 3301680572, 1563018173, 2628197501,
25162 657826727, 3871046759, 2136545894, 3201811878, 2548879397, 1449267173, 3481299428, 235845156,
25163 2650161890, 1551408418, 3315268387, 68429027, 758067552, 3970035360, 1967360161, 3033356129,
25164 2311284588, 1213053100, 3517963949, 270598509, 958010606, 4170500910, 1635167535, 2700636911,
25165 855672361, 4069415401, 1802256360, 2866995240, 2212099499, 1113008747, 3686091882, 440112042,
25166 }, {
25167 0, 2611301487, 3963330207, 2006897392, 50740095, 2560849680, 4013794784, 1956178319,
25168 101480190, 2645113489, 3929532513, 1905435662, 84561281, 2662269422, 3912356638, 1922342769,
25169 202960380, 2545787283, 3760419683, 2072395532, 253679235, 2495322860, 3810871324, 2021655667,
25170 169122562, 2444351341, 3861841309, 2106214898, 152215677, 2461527058, 3844685538, 2123133581,
25171 405920760, 2207553431, 4094313831, 1873742088, 456646791, 2157096168, 4144791064, 1823027831,
25172 507358470, 2241388905, 4060492697, 1772322806, 490444409, 2258557462, 4043311334, 1789215881,
25173 338245124, 2408348267, 4161972379, 1672996084, 388959611, 2357870868, 4212429796, 1622269835,
25174 304431354, 2306870421, 4263435877, 1706791434, 287538053, 2324051946, 4246267162, 1723705717,
25175 811841520, 2881944479, 3696765295, 1207788800, 862293135, 2831204576, 3747484176, 1157324415,
25176 913293582, 2915732833, 3662962577, 1106318334, 896137841, 2932651550, 3646055662, 1123494017,
25177 1014716940, 2816349795, 3493905555, 1273334012, 1065181555, 2765630748, 3544645612, 1222882179,
25178 980888818, 2714919069, 3595350637, 1307180546, 963712909, 2731826146, 3578431762, 1324336509,
25179 676490248, 3019317351, 3295277719, 1607253752, 726947703, 2968591128, 3345992168, 1556776327,
25180 777919222, 3053147801, 3261432937, 1505806342, 760750473, 3070062054, 3244539670, 1522987897,
25181 608862708, 3220163995, 3362856811, 1406423812, 659339915, 3169449700, 3413582868, 1355966587,
25182 575076106, 3118709605, 3464325525, 1440228858, 557894773, 3135602714, 3447411434, 1457397381,
25183 1623683040, 4217512847, 2365387135, 391757072, 1673614495, 4167309552, 2415577600, 341804655,
25184 1724586270, 4251866481, 2331019137, 290835438, 1707942497, 4268256782, 2314648830, 307490961,
25185 1826587164, 4152020595, 2162433155, 457265388, 1876539747, 4101829900, 2212636668, 407333779,
25186 1792275682, 4051089549, 2263378557, 491595282, 1775619997, 4067460082, 2246988034, 508239213,
25187 2029433880, 3813931127, 2496473735, 258500328, 2079362919, 3763716872, 2546668024, 208559511,
25188 2130363110, 3848244873, 2462145657, 157552662, 2113730969, 3864638966, 2445764358, 174205801,
25189 1961777636, 4014675339, 2564147067, 57707284, 2011718299, 3964481268, 2614361092, 7778411,
25190 1927425818, 3913769845, 2665066885, 92077546, 1910772837, 3930150922, 2648673018, 108709525,
25191 1352980496, 3405878399, 3164554895, 658115296, 1403183983, 3355946752, 3214507504, 607924639,
25192 1453895406, 3440239233, 3130208369, 557218846, 1437504913, 3456883198, 3113552654, 573589345,
25193 1555838444, 3340335491, 2961681267, 723707676, 1606028947, 3290383100, 3011612684, 673504355,
25194 1521500946, 3239382909, 3062619533, 758026722, 1505130605, 3256038402, 3045975794, 774417053,
25195 1217725416, 3543158663, 2762906999, 1057739032, 1267939479, 3493229816, 2812847624, 1007544935,
25196 1318679830, 3577493881, 2728586121, 956803046, 1302285929, 3594125830, 2711933174, 973184153,
25197 1150152212, 3743982203, 2830528651, 856898788, 1200346475, 3694041348, 2880457716, 806684571,
25198 1115789546, 3643069573, 2931426933, 891243034, 1099408277, 3659722746, 2914794762, 907637093,
25199 }, {
25200 0, 3717650821, 1616688459, 3184159950, 3233376918, 489665299, 2699419613, 2104690264,
25201 1510200173, 2274691816, 979330598, 3888758691, 2595928571, 1194090622, 4209380528, 661706037,
25202 3020400346, 1771143007, 3562738577, 164481556, 1958661196, 2837976521, 350386439, 3379863682,
25203 3993269687, 865250354, 2388181244, 1406015865, 784146209, 4079732388, 1323412074, 2474079215,
25204 3011398645, 1860735600, 3542286014, 246687547, 1942430051, 2924607718, 328963112, 3456978349,
25205 3917322392, 887832861, 2300653011, 1421341782, 700772878, 4099025803, 1234716485, 2483986112,
25206 125431087, 3673109674, 1730500708, 3132326369, 3351283641, 441867836, 2812031730, 2047535991,
25207 1568292418, 2163009479, 1025936137, 3769651852, 2646824148, 1079348561, 4255113631, 537475098,
25208 3180171691, 1612400686, 3721471200, 4717925, 2100624189, 2694980280, 493375094, 3237910515,
25209 3884860102, 974691139, 2278750093, 1514417672, 657926224, 4204917205, 1198234907, 2600289438,
25210 160053105, 3558665972, 1775665722, 3024116671, 3375586791, 346391650, 2842683564, 1962488105,
25211 1401545756, 2384412057, 869618007, 3997403346, 2469432970, 1319524111, 4083956673, 788193860,
25212 250862174, 3546612699, 1856990997, 3006903952, 3461001416, 333211981, 2920678787, 1937824774,
25213 1425017139, 2305216694, 883735672, 3912918525, 2487837605, 1239398944, 4095071982, 696455019,
25214 3136584836, 1734518017, 3668494799, 121507914, 2051872274, 2816200599, 437363545, 3347544796,
25215 3774328809, 1029797484, 2158697122, 1564328743, 542033279, 4258798842, 1074950196, 2642717105,
25216 2691310871, 2113731730, 3224801372, 497043929, 1624461185, 3175454212, 9435850, 3709412175,
25217 4201248378, 671035391, 2587181873, 1201904308, 986750188, 3880142185, 1519135143, 2266689570,
25218 342721485, 3388693064, 1949382278, 2846355203, 3570723163, 155332830, 3028835344, 1763607957,
25219 1315852448, 2482538789, 775087595, 4087626862, 2396469814, 1396827059, 4002123645, 857560824,
25220 320106210, 3464673127, 1934154665, 2933785132, 3551331444, 238804465, 3018961215, 1852270778,
25221 1226292623, 2491507722, 692783300, 4108177729, 2309936921, 1412959900, 3924976210, 879016919,
25222 2803091512, 2055541181, 3343875443, 450471158, 1739236014, 3124525867, 133568485, 3663777376,
25223 4245691221, 545702608, 2639048222, 1088059291, 1034514883, 3762268230, 1576387720, 2153979149,
25224 501724348, 3228659001, 2109407735, 2687359090, 3713981994, 13109167, 3171052385, 1620357860,
25225 1206151121, 2591211092, 666423962, 4197321503, 2271022407, 1523307714, 3875649548, 982999433,
25226 2850034278, 1953942499, 3384583981, 338329256, 1767471344, 3033506165, 151375291, 3566408766,
25227 4091789579, 779425934, 2478797888, 1311354309, 861580189, 4006375960, 1392910038, 2391852883,
25228 2929327945, 1930372812, 3469036034, 324244359, 1847629279, 3015068762, 243015828, 3555391761,
25229 4103744548, 688715169, 2496043375, 1229996266, 874727090, 3920994103, 1417671673, 2313759356,
25230 446585235, 3339223062, 2059594968, 2807313757, 3660002053, 129100416, 3128657486, 1743609803,
25231 1084066558, 2634765179, 549535669, 4250396208, 2149900392, 1571961325, 3765982499, 1039043750,
25232 }, {
25233 0, 2635063670, 3782132909, 2086741467, 430739227, 2225303149, 4173482934, 1707977408,
25234 861478454, 2924937024, 3526875803, 1329085421, 720736557, 3086643291, 3415954816, 1452586230,
25235 1722956908, 4223524122, 2279405761, 450042295, 2132718455, 3792785921, 2658170842, 58693292,
25236 1441473114, 3370435372, 3028674295, 696911745, 1279765825, 3511176247, 2905172460, 807831706,
25237 3445913816, 1349228974, 738901109, 2969918723, 3569940419, 1237784245, 900084590, 2829701656,
25238 4265436910, 1664255896, 525574723, 2187084597, 3885099509, 2057177219, 117386584, 2616249390,
25239 2882946228, 920233410, 1253605401, 3619119471, 2994391983, 796207833, 1393823490, 3457937012,
25240 2559531650, 92322804, 2044829231, 3840835417, 2166609305, 472659183, 1615663412, 4249022530,
25241 1102706673, 3702920839, 2698457948, 1037619754, 1477802218, 3306854812, 3111894087, 611605809,
25242 1927342535, 4025419953, 2475568490, 243387420, 1800169180, 4131620778, 2317525617, 388842247,
25243 655084445, 3120835307, 3328511792, 1533734470, 1051149446, 2745738736, 3754524715, 1120297309,
25244 340972971, 2304586973, 4114354438, 1748234352, 234773168, 2431761350, 3968900637, 1906278251,
25245 2363330345, 299003487, 1840466820, 4038896370, 2507210802, 142532932, 1948239007, 3910149609,
25246 3213136159, 579563625, 1592415666, 3286611140, 2787646980, 992477042, 1195825833, 3662232543,
25247 3933188933, 2002801203, 184645608, 2517538462, 4089658462, 1858919720, 313391347, 2409765253,
25248 3644239219, 1144605701, 945318366, 2773977256, 3231326824, 1570095902, 569697989, 3170568115,
25249 2205413346, 511446676, 1646078799, 4279421497, 2598330617, 131105167, 2075239508, 3871229218,
25250 2955604436, 757403810, 1363424633, 3427521551, 2844163791, 881434553, 1223211618, 3588709140,
25251 3854685070, 2026779384, 78583587, 2577462869, 4235025557, 1633861091, 486774840, 2148301134,
25252 3600338360, 1268198606, 938871061, 2868504675, 3476308643, 1379640277, 777684494, 3008718712,
25253 1310168890, 3541595724, 2943964055, 846639841, 1471879201, 3400857943, 3067468940, 735723002,
25254 2102298892, 3762382970, 2619362721, 19901655, 1692534295, 4193118049, 2240594618, 411247564,
25255 681945942, 3047836192, 3385552891, 1422167693, 822682701, 2886124859, 3496468704, 1298661782,
25256 469546336, 2264093718, 4203901389, 1738379451, 38812283, 2673859341, 3812556502, 2117148576,
25257 3268024339, 1606809957, 598006974, 3198893512, 3680933640, 1181316734, 973624229, 2802299603,
25258 4052944421, 1822222163, 285065864, 2381456382, 3896478014, 1966106696, 156323219, 2489232613,
25259 2759337087, 964150537, 1159127250, 3625517476, 3184831332, 551242258, 1555722185, 3249901247,
25260 2535537225, 170842943, 1984954084, 3946848146, 2391651666, 327308324, 1877176831, 4075589769,
25261 263086283, 2460058045, 4005602406, 1942963472, 369291216, 2332888742, 4151061373, 1784924683,
25262 1022852861, 2717425547, 3717839440, 1083595558, 626782694, 3092517008, 3291821387, 1497027645,
25263 1763466407, 4094934481, 2289211402, 360544636, 1890636732, 3988730570, 2447251217, 215086695,
25264 1514488465, 3343557607, 3140191804, 639919946, 1139395978, 3739626748, 2726758695, 1065936977,
25265 }, {
25266 0, 3120290792, 2827399569, 293431929, 2323408227, 864534155, 586863858, 2600537882,
25267 3481914503, 1987188591, 1729068310, 3740575486, 1173727716, 4228805132, 3983743093, 1418249117,
25268 1147313999, 4254680231, 3974377182, 1428157750, 3458136620, 2011505092, 1721256893, 3747844181,
25269 2347455432, 839944224, 594403929, 2593536433, 26687147, 3094146371, 2836498234, 283794642,
25270 2294627998, 826205558, 541298447, 2578994407, 45702141, 3141697557, 2856315500, 331624836,
25271 1196225049, 4273416689, 4023010184, 1446090848, 3442513786, 1959480466, 1706436331, 3696098563,
25272 3433538001, 1968994873, 1679888448, 3722103720, 1188807858, 4280295258, 3999102243, 1470541515,
25273 53374294, 3134568126, 2879970503, 307431215, 2303854645, 816436189, 567589284, 2553242188,
25274 3405478781, 1929420949, 1652411116, 3682996484, 1082596894, 4185703926, 3892424591, 1375368295,
25275 91404282, 3163122706, 2918450795, 336584067, 2400113305, 922028401, 663249672, 2658384096,
25276 2392450098, 929185754, 639587747, 2682555979, 82149713, 3172883129, 2892181696, 362343208,
25277 1091578037, 4176212829, 3918960932, 1349337804, 3412872662, 1922537022, 1676344391, 3658557359,
25278 1111377379, 4224032267, 3937989746, 1396912026, 3359776896, 1908013928, 1623494929, 3644803833,
25279 2377615716, 877417100, 623982837, 2630542109, 130804743, 3190831087, 2941083030, 381060734,
25280 106748588, 3215393092, 2933549885, 388083925, 2350956495, 903570471, 614862430, 2640172470,
25281 3386185259, 1882115523, 1632872378, 3634920530, 1135178568, 4199721120, 3945775833, 1389631793,
25282 1317531835, 4152109907, 3858841898, 1610259138, 3304822232, 2097172016, 1820140617, 3582394273,
25283 2165193788, 955639764, 696815021, 2423477829, 192043359, 2995356343, 2750736590, 437203750,
25284 182808564, 3005133852, 2724453989, 462947725, 2157513367, 962777471, 673168134, 2447663342,
25285 3312231283, 2090301595, 1844056802, 3557935370, 1326499344, 4142603768, 3885397889, 1584245865,
25286 3326266917, 2142836173, 1858371508, 3611272284, 1279175494, 4123357358, 3837270743, 1564721471,
25287 164299426, 2955991370, 2706223923, 414607579, 2209834945, 978107433, 724686416, 2462715320,
25288 2183156074, 1004243586, 715579643, 2472360723, 140260361, 2980573153, 2698675608, 421617264,
25289 1302961645, 4099032581, 3845074044, 1557460884, 3352688782, 2116952934, 1867729183, 3601371895,
25290 2222754758, 1032278062, 754596439, 2499928511, 234942117, 3086693709, 2793824052, 528319708,
25291 1274365761, 4061043881, 3816027856, 1518873912, 3246989858, 2020800970, 1762628531, 3505670235,
25292 3223196809, 2045103969, 1754834200, 3512958704, 1247965674, 4086934018, 3806642299, 1528765331,
25293 261609486, 3060532198, 2802936223, 518697591, 2246819181, 1007707781, 762121468, 2492913428,
25294 213497176, 3041029808, 2755593417, 499441441, 2261110843, 1061030867, 776167850, 2545465922,
25295 3274734047, 2060165687, 1807140942, 3528266662, 1229724860, 4038575956, 3788156205, 1479636677,
25296 1222322711, 4045468159, 3764231046, 1504067694, 3265744756, 2069664924, 1780612837, 3554288909,
25297 2270357136, 1051278712, 802445057, 2519698665, 221152243, 3033880603, 2779263586, 475261322,
25298 }, {
25299 0, 2926088593, 2275419491, 701019378, 3560000647, 2052709654, 1402038756, 4261017717,
25300 1930665807, 3715829470, 4105419308, 1524313021, 2804077512, 155861593, 545453739, 2397726522,
25301 3861331614, 1213181711, 1636244477, 3488582252, 840331801, 2625561480, 3048626042, 467584747,
25302 2503254481, 995897408, 311723186, 3170637091, 1090907478, 4016929991, 3332753461, 1758288292,
25303 390036349, 3109546732, 2426363422, 1056427919, 3272488954, 1835443819, 1152258713, 3938878216,
25304 1680663602, 3393484195, 3817652561, 1306808512, 2954733749, 510998820, 935169494, 2580880455,
25305 4044899811, 1601229938, 1991794816, 3637571857, 623446372, 2336332021, 2726898695, 216120726,
25306 2181814956, 744704829, 95158223, 2881711710, 1446680107, 4166125498, 3516576584, 2146575065,
25307 780072698, 2148951915, 2849952665, 129384968, 4199529085, 1411853292, 2112855838, 3548843663,
25308 1567451573, 4077254692, 3670887638, 1957027143, 2304517426, 657765539, 251396177, 2694091200,
25309 3361327204, 1714510325, 1341779207, 3784408214, 476611811, 2986349938, 2613617024, 899690513,
25310 3142211371, 354600634, 1021997640, 2458051545, 1870338988, 3239283261, 3906682575, 1186180958,
25311 960597383, 2536053782, 3202459876, 277428597, 3983589632, 1125666961, 1792074851, 3300423154,
25312 1246892744, 3829039961, 3455203243, 1671079482, 2657312335, 806080478, 432241452, 3081497277,
25313 3748049689, 1896751752, 1489409658, 4138600427, 190316446, 2772397583, 2365053693, 580864876,
25314 2893360214, 35503559, 735381813, 2243795108, 2017747153, 3593269568, 4293150130, 1368183843,
25315 1560145396, 4069882981, 3680356503, 1966430470, 2295112051, 648294626, 258769936, 2701399425,
25316 804156091, 2173100842, 2823706584, 103204425, 4225711676, 1438101421, 2088704863, 3524758222,
25317 3134903146, 347226875, 1031468553, 2467456920, 1860935661, 3229814396, 3914054286, 1193487135,
25318 3385412645, 1738661300, 1315531078, 3758225623, 502792354, 3012596019, 2589468097, 875607120,
25319 1271043721, 3853125400, 3429020650, 1644831355, 2683558414, 832261023, 408158061, 3057348348,
25320 953223622, 2528745559, 3211865253, 286899508, 3974120769, 1116263632, 1799381026, 3307794867,
25321 2917509143, 59586950, 709201268, 2217549029, 2043995280, 3619452161, 4269064691, 1344032866,
25322 3740677976, 1889445577, 1498812987, 4148069290, 180845535, 2762992206, 2372361916, 588238637,
25323 1921194766, 3706423967, 4112727661, 1531686908, 2796705673, 148555288, 554857194, 2407195515,
25324 26248257, 2952271312, 2251333922, 676868275, 3584149702, 2076793175, 1375858085, 4234771508,
25325 2493785488, 986493953, 319029491, 3178008930, 1083533591, 4009621638, 3342158964, 1767759333,
25326 3887577823, 1239362382, 1612160956, 3464433197, 864482904, 2649647049, 3022443323, 441336490,
25327 1706844275, 3419730402, 3793503504, 1282724993, 2978819316, 535149925, 908921239, 2554697734,
25328 380632892, 3100077741, 2433735263, 1063734222, 3265180603, 1828069930, 1161729752, 3948283721,
25329 2207997677, 770953084, 71007118, 2857626143, 1470763626, 4190274555, 3490330377, 2120394392,
25330 4035494306, 1591758899, 1999168705, 3644880208, 616140069, 2328960180, 2736367686, 225524183,
25331 },
25332};
25333
25334static const uint8_t
25335WUFFS_CRC32__IEEE_X86_SSE42_K1K2[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
25336 212, 43, 68, 84, 1, 0, 0, 0,
25337 150, 21, 228, 198, 1, 0, 0, 0,
25338};
25339
25340static const uint8_t
25341WUFFS_CRC32__IEEE_X86_SSE42_K3K4[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
25342 208, 151, 25, 117, 1, 0, 0, 0,
25343 158, 0, 170, 204, 0, 0, 0, 0,
25344};
25345
25346static const uint8_t
25347WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
25348 36, 97, 205, 99, 1, 0, 0, 0,
25349 0, 0, 0, 0, 0, 0, 0, 0,
25350};
25351
25352static const uint8_t
25353WUFFS_CRC32__IEEE_X86_SSE42_PXMU[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
25354 65, 6, 113, 219, 1, 0, 0, 0,
25355 65, 22, 1, 247, 1, 0, 0, 0,
25356};
25357
25358// ---------------- Private Initializer Prototypes
25359
25360// ---------------- Private Function Prototypes
25361
25362static wuffs_base__empty_struct
25363wuffs_crc32__ieee_hasher__up(
25364 wuffs_crc32__ieee_hasher* self,
25365 wuffs_base__slice_u8 a_x);
25366
25367static wuffs_base__empty_struct
25368wuffs_crc32__ieee_hasher__up__choosy_default(
25369 wuffs_crc32__ieee_hasher* self,
25370 wuffs_base__slice_u8 a_x);
25371
25372#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
25373static wuffs_base__empty_struct
25374wuffs_crc32__ieee_hasher__up_arm_crc32(
25375 wuffs_crc32__ieee_hasher* self,
25376 wuffs_base__slice_u8 a_x);
25377#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
25378
Nigel Tao7804ffe2021-10-07 21:58:26 +110025379#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100025380static wuffs_base__empty_struct
Nigel Tao5571bfe2021-06-24 22:44:29 +100025381wuffs_crc32__ieee_hasher__up_x86_avx2(
25382 wuffs_crc32__ieee_hasher* self,
25383 wuffs_base__slice_u8 a_x);
Nigel Tao7804ffe2021-10-07 21:58:26 +110025384#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100025385
Nigel Tao7804ffe2021-10-07 21:58:26 +110025386#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100025387static wuffs_base__empty_struct
Nigel Taoe360a532021-04-05 22:47:03 +100025388wuffs_crc32__ieee_hasher__up_x86_sse42(
25389 wuffs_crc32__ieee_hasher* self,
25390 wuffs_base__slice_u8 a_x);
Nigel Tao7804ffe2021-10-07 21:58:26 +110025391#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100025392
25393// ---------------- VTables
25394
25395const wuffs_base__hasher_u32__func_ptrs
25396wuffs_crc32__ieee_hasher__func_ptrs_for__wuffs_base__hasher_u32 = {
25397 (wuffs_base__empty_struct(*)(void*,
25398 uint32_t,
25399 bool))(&wuffs_crc32__ieee_hasher__set_quirk_enabled),
25400 (uint32_t(*)(void*,
25401 wuffs_base__slice_u8))(&wuffs_crc32__ieee_hasher__update_u32),
25402};
25403
25404// ---------------- Initializer Implementations
25405
25406wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
25407wuffs_crc32__ieee_hasher__initialize(
25408 wuffs_crc32__ieee_hasher* self,
25409 size_t sizeof_star_self,
25410 uint64_t wuffs_version,
25411 uint32_t options){
25412 if (!self) {
25413 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
25414 }
25415 if (sizeof(*self) != sizeof_star_self) {
25416 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
25417 }
25418 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
25419 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
25420 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
25421 }
25422
25423 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
25424 // The whole point of this if-check is to detect an uninitialized *self.
25425 // We disable the warning on GCC. Clang-5.0 does not have this warning.
25426#if !defined(__clang__) && defined(__GNUC__)
25427#pragma GCC diagnostic push
25428#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
25429#endif
25430 if (self->private_impl.magic != 0) {
25431 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
25432 }
25433#if !defined(__clang__) && defined(__GNUC__)
25434#pragma GCC diagnostic pop
25435#endif
25436 } else {
25437 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
25438 memset(self, 0, sizeof(*self));
25439 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
25440 } else {
25441 memset(&(self->private_impl), 0, sizeof(self->private_impl));
25442 }
25443 }
25444
25445 self->private_impl.choosy_up = &wuffs_crc32__ieee_hasher__up__choosy_default;
25446
25447 self->private_impl.magic = WUFFS_BASE__MAGIC;
25448 self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name =
25449 wuffs_base__hasher_u32__vtable_name;
25450 self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers =
25451 (const void*)(&wuffs_crc32__ieee_hasher__func_ptrs_for__wuffs_base__hasher_u32);
25452 return wuffs_base__make_status(NULL);
25453}
25454
25455wuffs_crc32__ieee_hasher*
25456wuffs_crc32__ieee_hasher__alloc() {
25457 wuffs_crc32__ieee_hasher* x =
25458 (wuffs_crc32__ieee_hasher*)(calloc(sizeof(wuffs_crc32__ieee_hasher), 1));
25459 if (!x) {
25460 return NULL;
25461 }
25462 if (wuffs_crc32__ieee_hasher__initialize(
25463 x, sizeof(wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
25464 free(x);
25465 return NULL;
25466 }
25467 return x;
25468}
25469
25470size_t
25471sizeof__wuffs_crc32__ieee_hasher() {
25472 return sizeof(wuffs_crc32__ieee_hasher);
25473}
25474
25475// ---------------- Function Implementations
25476
25477// -------- func crc32.ieee_hasher.set_quirk_enabled
25478
25479WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
25480wuffs_crc32__ieee_hasher__set_quirk_enabled(
25481 wuffs_crc32__ieee_hasher* self,
25482 uint32_t a_quirk,
25483 bool a_enabled) {
25484 return wuffs_base__make_empty_struct();
25485}
25486
25487// -------- func crc32.ieee_hasher.update_u32
25488
25489WUFFS_BASE__MAYBE_STATIC uint32_t
25490wuffs_crc32__ieee_hasher__update_u32(
25491 wuffs_crc32__ieee_hasher* self,
25492 wuffs_base__slice_u8 a_x) {
25493 if (!self) {
25494 return 0;
25495 }
25496 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
25497 return 0;
25498 }
25499
25500 if (self->private_impl.f_state == 0) {
25501 self->private_impl.choosy_up = (
25502#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
25503 wuffs_base__cpu_arch__have_arm_crc32() ? &wuffs_crc32__ieee_hasher__up_arm_crc32 :
25504#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110025505#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100025506 wuffs_base__cpu_arch__have_x86_avx2() ? &wuffs_crc32__ieee_hasher__up_x86_avx2 :
25507#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110025508#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100025509 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_crc32__ieee_hasher__up_x86_sse42 :
25510#endif
25511 self->private_impl.choosy_up);
25512 }
25513 wuffs_crc32__ieee_hasher__up(self, a_x);
25514 return self->private_impl.f_state;
25515}
25516
25517// -------- func crc32.ieee_hasher.up
25518
25519static wuffs_base__empty_struct
25520wuffs_crc32__ieee_hasher__up(
25521 wuffs_crc32__ieee_hasher* self,
25522 wuffs_base__slice_u8 a_x) {
25523 return (*self->private_impl.choosy_up)(self, a_x);
25524}
25525
25526static wuffs_base__empty_struct
25527wuffs_crc32__ieee_hasher__up__choosy_default(
25528 wuffs_crc32__ieee_hasher* self,
25529 wuffs_base__slice_u8 a_x) {
25530 uint32_t v_s = 0;
25531 wuffs_base__slice_u8 v_p = {0};
25532
25533 v_s = (4294967295 ^ self->private_impl.f_state);
25534 {
25535 wuffs_base__slice_u8 i_slice_p = a_x;
25536 v_p.ptr = i_slice_p.ptr;
25537 v_p.len = 16;
25538 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32);
25539 while (v_p.ptr < i_end0_p) {
25540 v_s ^= ((((uint32_t)(v_p.ptr[0])) << 0) |
25541 (((uint32_t)(v_p.ptr[1])) << 8) |
25542 (((uint32_t)(v_p.ptr[2])) << 16) |
25543 (((uint32_t)(v_p.ptr[3])) << 24));
25544 v_s = (WUFFS_CRC32__IEEE_TABLE[0][v_p.ptr[15]] ^
25545 WUFFS_CRC32__IEEE_TABLE[1][v_p.ptr[14]] ^
25546 WUFFS_CRC32__IEEE_TABLE[2][v_p.ptr[13]] ^
25547 WUFFS_CRC32__IEEE_TABLE[3][v_p.ptr[12]] ^
25548 WUFFS_CRC32__IEEE_TABLE[4][v_p.ptr[11]] ^
25549 WUFFS_CRC32__IEEE_TABLE[5][v_p.ptr[10]] ^
25550 WUFFS_CRC32__IEEE_TABLE[6][v_p.ptr[9]] ^
25551 WUFFS_CRC32__IEEE_TABLE[7][v_p.ptr[8]] ^
25552 WUFFS_CRC32__IEEE_TABLE[8][v_p.ptr[7]] ^
25553 WUFFS_CRC32__IEEE_TABLE[9][v_p.ptr[6]] ^
25554 WUFFS_CRC32__IEEE_TABLE[10][v_p.ptr[5]] ^
25555 WUFFS_CRC32__IEEE_TABLE[11][v_p.ptr[4]] ^
25556 WUFFS_CRC32__IEEE_TABLE[12][(255 & (v_s >> 24))] ^
25557 WUFFS_CRC32__IEEE_TABLE[13][(255 & (v_s >> 16))] ^
25558 WUFFS_CRC32__IEEE_TABLE[14][(255 & (v_s >> 8))] ^
25559 WUFFS_CRC32__IEEE_TABLE[15][(255 & (v_s >> 0))]);
25560 v_p.ptr += 16;
25561 v_s ^= ((((uint32_t)(v_p.ptr[0])) << 0) |
25562 (((uint32_t)(v_p.ptr[1])) << 8) |
25563 (((uint32_t)(v_p.ptr[2])) << 16) |
25564 (((uint32_t)(v_p.ptr[3])) << 24));
25565 v_s = (WUFFS_CRC32__IEEE_TABLE[0][v_p.ptr[15]] ^
25566 WUFFS_CRC32__IEEE_TABLE[1][v_p.ptr[14]] ^
25567 WUFFS_CRC32__IEEE_TABLE[2][v_p.ptr[13]] ^
25568 WUFFS_CRC32__IEEE_TABLE[3][v_p.ptr[12]] ^
25569 WUFFS_CRC32__IEEE_TABLE[4][v_p.ptr[11]] ^
25570 WUFFS_CRC32__IEEE_TABLE[5][v_p.ptr[10]] ^
25571 WUFFS_CRC32__IEEE_TABLE[6][v_p.ptr[9]] ^
25572 WUFFS_CRC32__IEEE_TABLE[7][v_p.ptr[8]] ^
25573 WUFFS_CRC32__IEEE_TABLE[8][v_p.ptr[7]] ^
25574 WUFFS_CRC32__IEEE_TABLE[9][v_p.ptr[6]] ^
25575 WUFFS_CRC32__IEEE_TABLE[10][v_p.ptr[5]] ^
25576 WUFFS_CRC32__IEEE_TABLE[11][v_p.ptr[4]] ^
25577 WUFFS_CRC32__IEEE_TABLE[12][(255 & (v_s >> 24))] ^
25578 WUFFS_CRC32__IEEE_TABLE[13][(255 & (v_s >> 16))] ^
25579 WUFFS_CRC32__IEEE_TABLE[14][(255 & (v_s >> 8))] ^
25580 WUFFS_CRC32__IEEE_TABLE[15][(255 & (v_s >> 0))]);
25581 v_p.ptr += 16;
25582 }
25583 v_p.len = 16;
25584 uint8_t* i_end1_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 16) * 16);
25585 while (v_p.ptr < i_end1_p) {
25586 v_s ^= ((((uint32_t)(v_p.ptr[0])) << 0) |
25587 (((uint32_t)(v_p.ptr[1])) << 8) |
25588 (((uint32_t)(v_p.ptr[2])) << 16) |
25589 (((uint32_t)(v_p.ptr[3])) << 24));
25590 v_s = (WUFFS_CRC32__IEEE_TABLE[0][v_p.ptr[15]] ^
25591 WUFFS_CRC32__IEEE_TABLE[1][v_p.ptr[14]] ^
25592 WUFFS_CRC32__IEEE_TABLE[2][v_p.ptr[13]] ^
25593 WUFFS_CRC32__IEEE_TABLE[3][v_p.ptr[12]] ^
25594 WUFFS_CRC32__IEEE_TABLE[4][v_p.ptr[11]] ^
25595 WUFFS_CRC32__IEEE_TABLE[5][v_p.ptr[10]] ^
25596 WUFFS_CRC32__IEEE_TABLE[6][v_p.ptr[9]] ^
25597 WUFFS_CRC32__IEEE_TABLE[7][v_p.ptr[8]] ^
25598 WUFFS_CRC32__IEEE_TABLE[8][v_p.ptr[7]] ^
25599 WUFFS_CRC32__IEEE_TABLE[9][v_p.ptr[6]] ^
25600 WUFFS_CRC32__IEEE_TABLE[10][v_p.ptr[5]] ^
25601 WUFFS_CRC32__IEEE_TABLE[11][v_p.ptr[4]] ^
25602 WUFFS_CRC32__IEEE_TABLE[12][(255 & (v_s >> 24))] ^
25603 WUFFS_CRC32__IEEE_TABLE[13][(255 & (v_s >> 16))] ^
25604 WUFFS_CRC32__IEEE_TABLE[14][(255 & (v_s >> 8))] ^
25605 WUFFS_CRC32__IEEE_TABLE[15][(255 & (v_s >> 0))]);
25606 v_p.ptr += 16;
25607 }
25608 v_p.len = 1;
25609 uint8_t* i_end2_p = i_slice_p.ptr + i_slice_p.len;
25610 while (v_p.ptr < i_end2_p) {
25611 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
25612 v_p.ptr += 1;
25613 }
25614 v_p.len = 0;
25615 }
25616 self->private_impl.f_state = (4294967295 ^ v_s);
25617 return wuffs_base__make_empty_struct();
25618}
25619
25620// ‼ WUFFS MULTI-FILE SECTION +arm_crc32
25621// -------- func crc32.ieee_hasher.up_arm_crc32
25622
25623#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
25624static wuffs_base__empty_struct
25625wuffs_crc32__ieee_hasher__up_arm_crc32(
25626 wuffs_crc32__ieee_hasher* self,
25627 wuffs_base__slice_u8 a_x) {
25628 wuffs_base__slice_u8 v_p = {0};
25629 uint32_t v_s = 0;
25630
25631 v_s = (4294967295 ^ self->private_impl.f_state);
25632 while ((((uint64_t)(a_x.len)) > 0) && ((15 & ((uint32_t)(0xFFF & (uintptr_t)(a_x.ptr)))) != 0)) {
25633 v_s = __crc32b(v_s, a_x.ptr[0]);
25634 a_x = wuffs_base__slice_u8__subslice_i(a_x, 1);
25635 }
25636 {
25637 wuffs_base__slice_u8 i_slice_p = a_x;
25638 v_p.ptr = i_slice_p.ptr;
25639 v_p.len = 8;
25640 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 128) * 128);
25641 while (v_p.ptr < i_end0_p) {
25642 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25643 v_p.ptr += 8;
25644 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25645 v_p.ptr += 8;
25646 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25647 v_p.ptr += 8;
25648 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25649 v_p.ptr += 8;
25650 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25651 v_p.ptr += 8;
25652 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25653 v_p.ptr += 8;
25654 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25655 v_p.ptr += 8;
25656 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25657 v_p.ptr += 8;
25658 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25659 v_p.ptr += 8;
25660 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25661 v_p.ptr += 8;
25662 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25663 v_p.ptr += 8;
25664 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25665 v_p.ptr += 8;
25666 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25667 v_p.ptr += 8;
25668 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25669 v_p.ptr += 8;
25670 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25671 v_p.ptr += 8;
25672 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25673 v_p.ptr += 8;
25674 }
25675 v_p.len = 8;
25676 uint8_t* i_end1_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8);
25677 while (v_p.ptr < i_end1_p) {
25678 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
25679 v_p.ptr += 8;
25680 }
25681 v_p.len = 1;
25682 uint8_t* i_end2_p = i_slice_p.ptr + i_slice_p.len;
25683 while (v_p.ptr < i_end2_p) {
25684 v_s = __crc32b(v_s, v_p.ptr[0]);
25685 v_p.ptr += 1;
25686 }
25687 v_p.len = 0;
25688 }
25689 self->private_impl.f_state = (4294967295 ^ v_s);
25690 return wuffs_base__make_empty_struct();
25691}
25692#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
25693// ‼ WUFFS MULTI-FILE SECTION -arm_crc32
25694
Nigel Tao5571bfe2021-06-24 22:44:29 +100025695// ‼ WUFFS MULTI-FILE SECTION +x86_avx2
25696// -------- func crc32.ieee_hasher.up_x86_avx2
25697
Nigel Tao7804ffe2021-10-07 21:58:26 +110025698#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100025699WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2")
25700static wuffs_base__empty_struct
25701wuffs_crc32__ieee_hasher__up_x86_avx2(
25702 wuffs_crc32__ieee_hasher* self,
25703 wuffs_base__slice_u8 a_x) {
25704 uint32_t v_s = 0;
25705 wuffs_base__slice_u8 v_p = {0};
25706 __m128i v_k = {0};
25707 __m128i v_x0 = {0};
25708 __m128i v_x1 = {0};
25709 __m128i v_x2 = {0};
25710 __m128i v_x3 = {0};
25711 __m128i v_y0 = {0};
25712 __m128i v_y1 = {0};
25713 __m128i v_y2 = {0};
25714 __m128i v_y3 = {0};
25715 uint64_t v_tail_index = 0;
25716
25717 v_s = (4294967295 ^ self->private_impl.f_state);
25718 while ((((uint64_t)(a_x.len)) > 0) && ((15 & ((uint32_t)(0xFFF & (uintptr_t)(a_x.ptr)))) != 0)) {
25719 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ a_x.ptr[0])] ^ (v_s >> 8));
25720 a_x = wuffs_base__slice_u8__subslice_i(a_x, 1);
25721 }
25722 if (((uint64_t)(a_x.len)) < 64) {
25723 {
25724 wuffs_base__slice_u8 i_slice_p = a_x;
25725 v_p.ptr = i_slice_p.ptr;
25726 v_p.len = 1;
25727 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
25728 while (v_p.ptr < i_end0_p) {
25729 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
25730 v_p.ptr += 1;
25731 }
25732 v_p.len = 0;
25733 }
25734 self->private_impl.f_state = (4294967295 ^ v_s);
25735 return wuffs_base__make_empty_struct();
25736 }
25737 v_x0 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0));
25738 v_x1 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16));
25739 v_x2 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32));
25740 v_x3 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48));
25741 v_x0 = _mm_xor_si128(v_x0, _mm_cvtsi32_si128((int32_t)(v_s)));
25742 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K1K2));
25743 {
25744 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, 64);
25745 v_p.ptr = i_slice_p.ptr;
25746 v_p.len = 64;
25747 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 64) * 64);
25748 while (v_p.ptr < i_end0_p) {
25749 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25750 v_y1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0));
25751 v_y2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(0));
25752 v_y3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(0));
25753 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
25754 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(17));
25755 v_x2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(17));
25756 v_x3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(17));
25757 v_x0 = _mm_xor_si128(_mm_xor_si128(v_x0, v_y0), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 0)));
25758 v_x1 = _mm_xor_si128(_mm_xor_si128(v_x1, v_y1), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16)));
25759 v_x2 = _mm_xor_si128(_mm_xor_si128(v_x2, v_y2), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 32)));
25760 v_x3 = _mm_xor_si128(_mm_xor_si128(v_x3, v_y3), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 48)));
25761 v_p.ptr += 64;
25762 }
25763 v_p.len = 0;
25764 }
25765 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K3K4));
25766 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25767 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
25768 v_x0 = _mm_xor_si128(v_x0, v_x1);
25769 v_x0 = _mm_xor_si128(v_x0, v_y0);
25770 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25771 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
25772 v_x0 = _mm_xor_si128(v_x0, v_x2);
25773 v_x0 = _mm_xor_si128(v_x0, v_y0);
25774 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25775 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
25776 v_x0 = _mm_xor_si128(v_x0, v_x3);
25777 v_x0 = _mm_xor_si128(v_x0, v_y0);
25778 v_x1 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(16));
25779 v_x2 = _mm_set_epi32((int32_t)(0), (int32_t)(4294967295), (int32_t)(0), (int32_t)(4294967295));
25780 v_x0 = _mm_srli_si128(v_x0, (int32_t)(8));
25781 v_x0 = _mm_xor_si128(v_x0, v_x1);
25782 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ));
25783 v_x1 = _mm_srli_si128(v_x0, (int32_t)(4));
25784 v_x0 = _mm_and_si128(v_x0, v_x2);
25785 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25786 v_x0 = _mm_xor_si128(v_x0, v_x1);
25787 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_PXMU));
25788 v_x1 = _mm_and_si128(v_x0, v_x2);
25789 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(16));
25790 v_x1 = _mm_and_si128(v_x1, v_x2);
25791 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0));
25792 v_x0 = _mm_xor_si128(v_x0, v_x1);
25793 v_s = ((uint32_t)(_mm_extract_epi32(v_x0, (int32_t)(1))));
25794 v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551552u);
25795 if (v_tail_index < ((uint64_t)(a_x.len))) {
25796 {
25797 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index);
25798 v_p.ptr = i_slice_p.ptr;
25799 v_p.len = 1;
25800 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
25801 while (v_p.ptr < i_end0_p) {
25802 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
25803 v_p.ptr += 1;
25804 }
25805 v_p.len = 0;
25806 }
25807 }
25808 self->private_impl.f_state = (4294967295 ^ v_s);
25809 return wuffs_base__make_empty_struct();
25810}
Nigel Tao7804ffe2021-10-07 21:58:26 +110025811#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100025812// ‼ WUFFS MULTI-FILE SECTION -x86_avx2
25813
Nigel Taoe360a532021-04-05 22:47:03 +100025814// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
25815// -------- func crc32.ieee_hasher.up_x86_sse42
25816
Nigel Tao7804ffe2021-10-07 21:58:26 +110025817#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100025818WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
25819static wuffs_base__empty_struct
25820wuffs_crc32__ieee_hasher__up_x86_sse42(
25821 wuffs_crc32__ieee_hasher* self,
25822 wuffs_base__slice_u8 a_x) {
25823 uint32_t v_s = 0;
25824 wuffs_base__slice_u8 v_p = {0};
25825 __m128i v_k = {0};
25826 __m128i v_x0 = {0};
25827 __m128i v_x1 = {0};
25828 __m128i v_x2 = {0};
25829 __m128i v_x3 = {0};
25830 __m128i v_y0 = {0};
25831 __m128i v_y1 = {0};
25832 __m128i v_y2 = {0};
25833 __m128i v_y3 = {0};
25834 uint64_t v_tail_index = 0;
25835
25836 v_s = (4294967295 ^ self->private_impl.f_state);
25837 while ((((uint64_t)(a_x.len)) > 0) && ((15 & ((uint32_t)(0xFFF & (uintptr_t)(a_x.ptr)))) != 0)) {
25838 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ a_x.ptr[0])] ^ (v_s >> 8));
25839 a_x = wuffs_base__slice_u8__subslice_i(a_x, 1);
25840 }
25841 if (((uint64_t)(a_x.len)) < 64) {
25842 {
25843 wuffs_base__slice_u8 i_slice_p = a_x;
25844 v_p.ptr = i_slice_p.ptr;
25845 v_p.len = 1;
25846 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
25847 while (v_p.ptr < i_end0_p) {
25848 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
25849 v_p.ptr += 1;
25850 }
25851 v_p.len = 0;
25852 }
25853 self->private_impl.f_state = (4294967295 ^ v_s);
25854 return wuffs_base__make_empty_struct();
25855 }
25856 v_x0 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0));
25857 v_x1 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16));
25858 v_x2 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32));
25859 v_x3 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48));
25860 v_x0 = _mm_xor_si128(v_x0, _mm_cvtsi32_si128((int32_t)(v_s)));
25861 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K1K2));
25862 {
25863 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, 64);
25864 v_p.ptr = i_slice_p.ptr;
25865 v_p.len = 64;
25866 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 64) * 64);
25867 while (v_p.ptr < i_end0_p) {
25868 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25869 v_y1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0));
25870 v_y2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(0));
25871 v_y3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(0));
25872 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
25873 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(17));
25874 v_x2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(17));
25875 v_x3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(17));
25876 v_x0 = _mm_xor_si128(_mm_xor_si128(v_x0, v_y0), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 0)));
25877 v_x1 = _mm_xor_si128(_mm_xor_si128(v_x1, v_y1), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16)));
25878 v_x2 = _mm_xor_si128(_mm_xor_si128(v_x2, v_y2), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 32)));
25879 v_x3 = _mm_xor_si128(_mm_xor_si128(v_x3, v_y3), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 48)));
25880 v_p.ptr += 64;
25881 }
25882 v_p.len = 0;
25883 }
25884 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K3K4));
25885 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25886 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
25887 v_x0 = _mm_xor_si128(v_x0, v_x1);
25888 v_x0 = _mm_xor_si128(v_x0, v_y0);
25889 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25890 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
25891 v_x0 = _mm_xor_si128(v_x0, v_x2);
25892 v_x0 = _mm_xor_si128(v_x0, v_y0);
25893 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25894 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
25895 v_x0 = _mm_xor_si128(v_x0, v_x3);
25896 v_x0 = _mm_xor_si128(v_x0, v_y0);
25897 v_x1 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(16));
25898 v_x2 = _mm_set_epi32((int32_t)(0), (int32_t)(4294967295), (int32_t)(0), (int32_t)(4294967295));
25899 v_x0 = _mm_srli_si128(v_x0, (int32_t)(8));
25900 v_x0 = _mm_xor_si128(v_x0, v_x1);
25901 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ));
25902 v_x1 = _mm_srli_si128(v_x0, (int32_t)(4));
25903 v_x0 = _mm_and_si128(v_x0, v_x2);
25904 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
25905 v_x0 = _mm_xor_si128(v_x0, v_x1);
25906 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_PXMU));
25907 v_x1 = _mm_and_si128(v_x0, v_x2);
25908 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(16));
25909 v_x1 = _mm_and_si128(v_x1, v_x2);
25910 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0));
25911 v_x0 = _mm_xor_si128(v_x0, v_x1);
25912 v_s = ((uint32_t)(_mm_extract_epi32(v_x0, (int32_t)(1))));
25913 v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551552u);
25914 if (v_tail_index < ((uint64_t)(a_x.len))) {
25915 {
25916 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index);
25917 v_p.ptr = i_slice_p.ptr;
25918 v_p.len = 1;
25919 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
25920 while (v_p.ptr < i_end0_p) {
25921 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
25922 v_p.ptr += 1;
25923 }
25924 v_p.len = 0;
25925 }
25926 }
25927 self->private_impl.f_state = (4294967295 ^ v_s);
25928 return wuffs_base__make_empty_struct();
25929}
Nigel Tao7804ffe2021-10-07 21:58:26 +110025930#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100025931// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
25932
25933#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32)
25934
25935#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE)
25936
25937// ---------------- Status Codes Implementations
25938
25939const char wuffs_deflate__error__bad_huffman_code_over_subscribed[] = "#deflate: bad Huffman code (over-subscribed)";
25940const char wuffs_deflate__error__bad_huffman_code_under_subscribed[] = "#deflate: bad Huffman code (under-subscribed)";
25941const char wuffs_deflate__error__bad_huffman_code_length_count[] = "#deflate: bad Huffman code length count";
25942const char wuffs_deflate__error__bad_huffman_code_length_repetition[] = "#deflate: bad Huffman code length repetition";
25943const char wuffs_deflate__error__bad_huffman_code[] = "#deflate: bad Huffman code";
25944const char wuffs_deflate__error__bad_huffman_minimum_code_length[] = "#deflate: bad Huffman minimum code length";
25945const char wuffs_deflate__error__bad_block[] = "#deflate: bad block";
25946const char wuffs_deflate__error__bad_distance[] = "#deflate: bad distance";
25947const char wuffs_deflate__error__bad_distance_code_count[] = "#deflate: bad distance code count";
25948const char wuffs_deflate__error__bad_literal_length_code_count[] = "#deflate: bad literal/length code count";
25949const char wuffs_deflate__error__inconsistent_stored_block_length[] = "#deflate: inconsistent stored block length";
25950const char wuffs_deflate__error__missing_end_of_block_code[] = "#deflate: missing end-of-block code";
25951const char wuffs_deflate__error__no_huffman_codes[] = "#deflate: no Huffman codes";
25952const char wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state[] = "#deflate: internal error: inconsistent Huffman decoder state";
25953const char wuffs_deflate__error__internal_error_inconsistent_i_o[] = "#deflate: internal error: inconsistent I/O";
25954const char wuffs_deflate__error__internal_error_inconsistent_distance[] = "#deflate: internal error: inconsistent distance";
25955const char wuffs_deflate__error__internal_error_inconsistent_n_bits[] = "#deflate: internal error: inconsistent n_bits";
25956
25957// ---------------- Private Consts
25958
25959static const uint8_t
25960WUFFS_DEFLATE__CODE_ORDER[19] WUFFS_BASE__POTENTIALLY_UNUSED = {
25961 16, 17, 18, 0, 8, 7, 9, 6,
25962 10, 5, 11, 4, 12, 3, 13, 2,
25963 14, 1, 15,
25964};
25965
25966static const uint8_t
25967WUFFS_DEFLATE__REVERSE8[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
25968 0, 128, 64, 192, 32, 160, 96, 224,
25969 16, 144, 80, 208, 48, 176, 112, 240,
25970 8, 136, 72, 200, 40, 168, 104, 232,
25971 24, 152, 88, 216, 56, 184, 120, 248,
25972 4, 132, 68, 196, 36, 164, 100, 228,
25973 20, 148, 84, 212, 52, 180, 116, 244,
25974 12, 140, 76, 204, 44, 172, 108, 236,
25975 28, 156, 92, 220, 60, 188, 124, 252,
25976 2, 130, 66, 194, 34, 162, 98, 226,
25977 18, 146, 82, 210, 50, 178, 114, 242,
25978 10, 138, 74, 202, 42, 170, 106, 234,
25979 26, 154, 90, 218, 58, 186, 122, 250,
25980 6, 134, 70, 198, 38, 166, 102, 230,
25981 22, 150, 86, 214, 54, 182, 118, 246,
25982 14, 142, 78, 206, 46, 174, 110, 238,
25983 30, 158, 94, 222, 62, 190, 126, 254,
25984 1, 129, 65, 193, 33, 161, 97, 225,
25985 17, 145, 81, 209, 49, 177, 113, 241,
25986 9, 137, 73, 201, 41, 169, 105, 233,
25987 25, 153, 89, 217, 57, 185, 121, 249,
25988 5, 133, 69, 197, 37, 165, 101, 229,
25989 21, 149, 85, 213, 53, 181, 117, 245,
25990 13, 141, 77, 205, 45, 173, 109, 237,
25991 29, 157, 93, 221, 61, 189, 125, 253,
25992 3, 131, 67, 195, 35, 163, 99, 227,
25993 19, 147, 83, 211, 51, 179, 115, 243,
25994 11, 139, 75, 203, 43, 171, 107, 235,
25995 27, 155, 91, 219, 59, 187, 123, 251,
25996 7, 135, 71, 199, 39, 167, 103, 231,
25997 23, 151, 87, 215, 55, 183, 119, 247,
25998 15, 143, 79, 207, 47, 175, 111, 239,
25999 31, 159, 95, 223, 63, 191, 127, 255,
26000};
26001
26002static const uint32_t
26003WUFFS_DEFLATE__LCODE_MAGIC_NUMBERS[32] WUFFS_BASE__POTENTIALLY_UNUSED = {
26004 1073741824, 1073742080, 1073742336, 1073742592, 1073742848, 1073743104, 1073743360, 1073743616,
26005 1073743888, 1073744400, 1073744912, 1073745424, 1073745952, 1073746976, 1073748000, 1073749024,
26006 1073750064, 1073752112, 1073754160, 1073756208, 1073758272, 1073762368, 1073766464, 1073770560,
26007 1073774672, 1073782864, 1073791056, 1073799248, 1073807104, 134217728, 134217728, 134217728,
26008};
26009
26010static const uint32_t
26011WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[32] WUFFS_BASE__POTENTIALLY_UNUSED = {
26012 1073741824, 1073742080, 1073742336, 1073742592, 1073742864, 1073743376, 1073743904, 1073744928,
26013 1073745968, 1073748016, 1073750080, 1073754176, 1073758288, 1073766480, 1073774688, 1073791072,
26014 1073807472, 1073840240, 1073873024, 1073938560, 1074004112, 1074135184, 1074266272, 1074528416,
26015 1074790576, 1075314864, 1075839168, 1076887744, 1077936336, 1080033488, 134217728, 134217728,
26016};
26017
26018#define WUFFS_DEFLATE__HUFFS_TABLE_SIZE 1024
26019
26020#define WUFFS_DEFLATE__HUFFS_TABLE_MASK 1023
26021
26022// ---------------- Private Initializer Prototypes
26023
26024// ---------------- Private Function Prototypes
26025
26026static wuffs_base__status
26027wuffs_deflate__decoder__decode_blocks(
26028 wuffs_deflate__decoder* self,
26029 wuffs_base__io_buffer* a_dst,
26030 wuffs_base__io_buffer* a_src);
26031
26032static wuffs_base__status
26033wuffs_deflate__decoder__decode_uncompressed(
26034 wuffs_deflate__decoder* self,
26035 wuffs_base__io_buffer* a_dst,
26036 wuffs_base__io_buffer* a_src);
26037
26038static wuffs_base__status
26039wuffs_deflate__decoder__init_fixed_huffman(
26040 wuffs_deflate__decoder* self);
26041
26042static wuffs_base__status
26043wuffs_deflate__decoder__init_dynamic_huffman(
26044 wuffs_deflate__decoder* self,
26045 wuffs_base__io_buffer* a_src);
26046
26047static wuffs_base__status
26048wuffs_deflate__decoder__init_huff(
26049 wuffs_deflate__decoder* self,
26050 uint32_t a_which,
26051 uint32_t a_n_codes0,
26052 uint32_t a_n_codes1,
26053 uint32_t a_base_symbol);
26054
Nigel Tao7804ffe2021-10-07 21:58:26 +110026055#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100026056static wuffs_base__status
26057wuffs_deflate__decoder__decode_huffman_bmi2(
26058 wuffs_deflate__decoder* self,
26059 wuffs_base__io_buffer* a_dst,
26060 wuffs_base__io_buffer* a_src);
Nigel Tao7804ffe2021-10-07 21:58:26 +110026061#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100026062
Nigel Taoe360a532021-04-05 22:47:03 +100026063static wuffs_base__status
26064wuffs_deflate__decoder__decode_huffman_fast32(
26065 wuffs_deflate__decoder* self,
26066 wuffs_base__io_buffer* a_dst,
26067 wuffs_base__io_buffer* a_src);
26068
26069static wuffs_base__status
26070wuffs_deflate__decoder__decode_huffman_fast64(
26071 wuffs_deflate__decoder* self,
26072 wuffs_base__io_buffer* a_dst,
26073 wuffs_base__io_buffer* a_src);
26074
26075static wuffs_base__status
Nigel Tao5571bfe2021-06-24 22:44:29 +100026076wuffs_deflate__decoder__decode_huffman_fast64__choosy_default(
26077 wuffs_deflate__decoder* self,
26078 wuffs_base__io_buffer* a_dst,
26079 wuffs_base__io_buffer* a_src);
26080
26081static wuffs_base__status
Nigel Taoe360a532021-04-05 22:47:03 +100026082wuffs_deflate__decoder__decode_huffman_slow(
26083 wuffs_deflate__decoder* self,
26084 wuffs_base__io_buffer* a_dst,
26085 wuffs_base__io_buffer* a_src);
26086
26087// ---------------- VTables
26088
26089const wuffs_base__io_transformer__func_ptrs
26090wuffs_deflate__decoder__func_ptrs_for__wuffs_base__io_transformer = {
26091 (wuffs_base__empty_struct(*)(void*,
26092 uint32_t,
26093 bool))(&wuffs_deflate__decoder__set_quirk_enabled),
26094 (wuffs_base__status(*)(void*,
26095 wuffs_base__io_buffer*,
26096 wuffs_base__io_buffer*,
26097 wuffs_base__slice_u8))(&wuffs_deflate__decoder__transform_io),
26098 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_deflate__decoder__workbuf_len),
26099};
26100
26101// ---------------- Initializer Implementations
26102
26103wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
26104wuffs_deflate__decoder__initialize(
26105 wuffs_deflate__decoder* self,
26106 size_t sizeof_star_self,
26107 uint64_t wuffs_version,
26108 uint32_t options){
26109 if (!self) {
26110 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
26111 }
26112 if (sizeof(*self) != sizeof_star_self) {
26113 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
26114 }
26115 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
26116 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
26117 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
26118 }
26119
26120 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
26121 // The whole point of this if-check is to detect an uninitialized *self.
26122 // We disable the warning on GCC. Clang-5.0 does not have this warning.
26123#if !defined(__clang__) && defined(__GNUC__)
26124#pragma GCC diagnostic push
26125#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
26126#endif
26127 if (self->private_impl.magic != 0) {
26128 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
26129 }
26130#if !defined(__clang__) && defined(__GNUC__)
26131#pragma GCC diagnostic pop
26132#endif
26133 } else {
26134 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
26135 memset(self, 0, sizeof(*self));
26136 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
26137 } else {
26138 memset(&(self->private_impl), 0, sizeof(self->private_impl));
26139 }
26140 }
26141
Nigel Tao5571bfe2021-06-24 22:44:29 +100026142 self->private_impl.choosy_decode_huffman_fast64 = &wuffs_deflate__decoder__decode_huffman_fast64__choosy_default;
26143
Nigel Taoe360a532021-04-05 22:47:03 +100026144 self->private_impl.magic = WUFFS_BASE__MAGIC;
26145 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
26146 wuffs_base__io_transformer__vtable_name;
26147 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
26148 (const void*)(&wuffs_deflate__decoder__func_ptrs_for__wuffs_base__io_transformer);
26149 return wuffs_base__make_status(NULL);
26150}
26151
26152wuffs_deflate__decoder*
26153wuffs_deflate__decoder__alloc() {
26154 wuffs_deflate__decoder* x =
26155 (wuffs_deflate__decoder*)(calloc(sizeof(wuffs_deflate__decoder), 1));
26156 if (!x) {
26157 return NULL;
26158 }
26159 if (wuffs_deflate__decoder__initialize(
26160 x, sizeof(wuffs_deflate__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
26161 free(x);
26162 return NULL;
26163 }
26164 return x;
26165}
26166
26167size_t
26168sizeof__wuffs_deflate__decoder() {
26169 return sizeof(wuffs_deflate__decoder);
26170}
26171
26172// ---------------- Function Implementations
26173
26174// -------- func deflate.decoder.add_history
26175
26176WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
26177wuffs_deflate__decoder__add_history(
26178 wuffs_deflate__decoder* self,
26179 wuffs_base__slice_u8 a_hist) {
26180 if (!self) {
26181 return wuffs_base__make_empty_struct();
26182 }
26183 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
26184 return wuffs_base__make_empty_struct();
26185 }
26186
26187 wuffs_base__slice_u8 v_s = {0};
26188 uint64_t v_n_copied = 0;
26189 uint32_t v_already_full = 0;
26190
26191 v_s = a_hist;
26192 if (((uint64_t)(v_s.len)) >= 32768) {
26193 v_s = wuffs_base__slice_u8__suffix(v_s, 32768);
26194 wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s);
26195 self->private_impl.f_history_index = 32768;
26196 } else {
26197 v_n_copied = wuffs_base__slice_u8__copy_from_slice(wuffs_base__slice_u8__subslice_i(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), (self->private_impl.f_history_index & 32767)), v_s);
26198 if (v_n_copied < ((uint64_t)(v_s.len))) {
26199 v_s = wuffs_base__slice_u8__subslice_i(v_s, v_n_copied);
26200 v_n_copied = wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s);
26201 self->private_impl.f_history_index = (((uint32_t)((v_n_copied & 32767))) + 32768);
26202 } else {
26203 v_already_full = 0;
26204 if (self->private_impl.f_history_index >= 32768) {
26205 v_already_full = 32768;
26206 }
26207 self->private_impl.f_history_index = ((self->private_impl.f_history_index & 32767) + ((uint32_t)((v_n_copied & 32767))) + v_already_full);
26208 }
26209 }
26210 wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8((self->private_data.f_history) + 32768, 257), wuffs_base__make_slice_u8(self->private_data.f_history, 33025));
26211 return wuffs_base__make_empty_struct();
26212}
26213
26214// -------- func deflate.decoder.set_quirk_enabled
26215
26216WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
26217wuffs_deflate__decoder__set_quirk_enabled(
26218 wuffs_deflate__decoder* self,
26219 uint32_t a_quirk,
26220 bool a_enabled) {
26221 return wuffs_base__make_empty_struct();
26222}
26223
26224// -------- func deflate.decoder.workbuf_len
26225
26226WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
26227wuffs_deflate__decoder__workbuf_len(
26228 const wuffs_deflate__decoder* self) {
26229 if (!self) {
26230 return wuffs_base__utility__empty_range_ii_u64();
26231 }
26232 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
26233 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
26234 return wuffs_base__utility__empty_range_ii_u64();
26235 }
26236
26237 return wuffs_base__utility__make_range_ii_u64(1, 1);
26238}
26239
26240// -------- func deflate.decoder.transform_io
26241
26242WUFFS_BASE__MAYBE_STATIC wuffs_base__status
26243wuffs_deflate__decoder__transform_io(
26244 wuffs_deflate__decoder* self,
26245 wuffs_base__io_buffer* a_dst,
26246 wuffs_base__io_buffer* a_src,
26247 wuffs_base__slice_u8 a_workbuf) {
26248 if (!self) {
26249 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
26250 }
26251 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
26252 return wuffs_base__make_status(
26253 (self->private_impl.magic == WUFFS_BASE__DISABLED)
26254 ? wuffs_base__error__disabled_by_previous_error
26255 : wuffs_base__error__initialize_not_called);
26256 }
26257 if (!a_dst || !a_src) {
26258 self->private_impl.magic = WUFFS_BASE__DISABLED;
26259 return wuffs_base__make_status(wuffs_base__error__bad_argument);
26260 }
26261 if ((self->private_impl.active_coroutine != 0) &&
26262 (self->private_impl.active_coroutine != 1)) {
26263 self->private_impl.magic = WUFFS_BASE__DISABLED;
26264 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
26265 }
26266 self->private_impl.active_coroutine = 0;
26267 wuffs_base__status status = wuffs_base__make_status(NULL);
26268
26269 uint64_t v_mark = 0;
26270 wuffs_base__status v_status = wuffs_base__make_status(NULL);
26271
26272 uint8_t* iop_a_dst = NULL;
26273 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26274 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26275 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26276 if (a_dst) {
26277 io0_a_dst = a_dst->data.ptr;
26278 io1_a_dst = io0_a_dst + a_dst->meta.wi;
26279 iop_a_dst = io1_a_dst;
26280 io2_a_dst = io0_a_dst + a_dst->data.len;
26281 if (a_dst->meta.closed) {
26282 io2_a_dst = iop_a_dst;
26283 }
26284 }
26285
26286 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
26287 switch (coro_susp_point) {
26288 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
26289
Nigel Tao5571bfe2021-06-24 22:44:29 +100026290 self->private_impl.choosy_decode_huffman_fast64 = (
Nigel Tao7804ffe2021-10-07 21:58:26 +110026291#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100026292 wuffs_base__cpu_arch__have_x86_bmi2() ? &wuffs_deflate__decoder__decode_huffman_bmi2 :
26293#endif
26294 self->private_impl.choosy_decode_huffman_fast64);
Nigel Taoe360a532021-04-05 22:47:03 +100026295 while (true) {
26296 v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
26297 {
26298 if (a_dst) {
26299 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
26300 }
26301 wuffs_base__status t_0 = wuffs_deflate__decoder__decode_blocks(self, a_dst, a_src);
26302 v_status = t_0;
26303 if (a_dst) {
26304 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
26305 }
26306 }
26307 if ( ! wuffs_base__status__is_suspension(&v_status)) {
26308 status = v_status;
26309 if (wuffs_base__status__is_error(&status)) {
26310 goto exit;
26311 } else if (wuffs_base__status__is_suspension(&status)) {
26312 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
26313 goto exit;
26314 }
26315 goto ok;
26316 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100026317 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_transformed_history_count, wuffs_base__io__count_since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst))));
Nigel Taoe360a532021-04-05 22:47:03 +100026318 wuffs_deflate__decoder__add_history(self, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst));
26319 status = v_status;
26320 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
26321 }
26322
Nigel Taoe360a532021-04-05 22:47:03 +100026323 ok:
26324 self->private_impl.p_transform_io[0] = 0;
26325 goto exit;
26326 }
26327
26328 goto suspend;
26329 suspend:
26330 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
26331 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
26332
26333 goto exit;
26334 exit:
26335 if (a_dst) {
26336 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
26337 }
26338
26339 if (wuffs_base__status__is_error(&status)) {
26340 self->private_impl.magic = WUFFS_BASE__DISABLED;
26341 }
26342 return status;
26343}
26344
26345// -------- func deflate.decoder.decode_blocks
26346
26347static wuffs_base__status
26348wuffs_deflate__decoder__decode_blocks(
26349 wuffs_deflate__decoder* self,
26350 wuffs_base__io_buffer* a_dst,
26351 wuffs_base__io_buffer* a_src) {
26352 wuffs_base__status status = wuffs_base__make_status(NULL);
26353
26354 uint32_t v_final = 0;
26355 uint32_t v_b0 = 0;
26356 uint32_t v_type = 0;
26357 wuffs_base__status v_status = wuffs_base__make_status(NULL);
26358
26359 const uint8_t* iop_a_src = NULL;
26360 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26361 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26362 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26363 if (a_src) {
26364 io0_a_src = a_src->data.ptr;
26365 io1_a_src = io0_a_src + a_src->meta.ri;
26366 iop_a_src = io1_a_src;
26367 io2_a_src = io0_a_src + a_src->meta.wi;
26368 }
26369
26370 uint32_t coro_susp_point = self->private_impl.p_decode_blocks[0];
26371 if (coro_susp_point) {
26372 v_final = self->private_data.s_decode_blocks[0].v_final;
26373 }
26374 switch (coro_susp_point) {
26375 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
26376
26377 label__outer__continue:;
26378 while (v_final == 0) {
26379 while (self->private_impl.f_n_bits < 3) {
26380 {
26381 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
26382 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
26383 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26384 goto suspend;
26385 }
26386 uint32_t t_0 = *iop_a_src++;
26387 v_b0 = t_0;
26388 }
26389 self->private_impl.f_bits |= (v_b0 << (self->private_impl.f_n_bits & 3));
26390 self->private_impl.f_n_bits = ((self->private_impl.f_n_bits & 3) + 8);
26391 }
26392 v_final = (self->private_impl.f_bits & 1);
26393 v_type = ((self->private_impl.f_bits >> 1) & 3);
26394 self->private_impl.f_bits >>= 3;
26395 self->private_impl.f_n_bits -= 3;
26396 if (v_type == 0) {
26397 if (a_src) {
26398 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26399 }
26400 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
26401 status = wuffs_deflate__decoder__decode_uncompressed(self, a_dst, a_src);
26402 if (a_src) {
26403 iop_a_src = a_src->data.ptr + a_src->meta.ri;
26404 }
26405 if (status.repr) {
26406 goto suspend;
26407 }
26408 goto label__outer__continue;
26409 } else if (v_type == 1) {
26410 v_status = wuffs_deflate__decoder__init_fixed_huffman(self);
26411 if ( ! wuffs_base__status__is_ok(&v_status)) {
26412 status = v_status;
26413 if (wuffs_base__status__is_error(&status)) {
26414 goto exit;
26415 } else if (wuffs_base__status__is_suspension(&status)) {
26416 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
26417 goto exit;
26418 }
26419 goto ok;
26420 }
26421 } else if (v_type == 2) {
26422 if (a_src) {
26423 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26424 }
26425 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
26426 status = wuffs_deflate__decoder__init_dynamic_huffman(self, a_src);
26427 if (a_src) {
26428 iop_a_src = a_src->data.ptr + a_src->meta.ri;
26429 }
26430 if (status.repr) {
26431 goto suspend;
26432 }
26433 } else {
26434 status = wuffs_base__make_status(wuffs_deflate__error__bad_block);
26435 goto exit;
26436 }
26437 self->private_impl.f_end_of_block = false;
26438 while (true) {
26439 if (sizeof(void*) == 4) {
26440 if (a_src) {
26441 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26442 }
26443 v_status = wuffs_deflate__decoder__decode_huffman_fast32(self, a_dst, a_src);
26444 if (a_src) {
26445 iop_a_src = a_src->data.ptr + a_src->meta.ri;
26446 }
26447 } else {
26448 if (a_src) {
26449 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26450 }
26451 v_status = wuffs_deflate__decoder__decode_huffman_fast64(self, a_dst, a_src);
26452 if (a_src) {
26453 iop_a_src = a_src->data.ptr + a_src->meta.ri;
26454 }
26455 }
26456 if (wuffs_base__status__is_error(&v_status)) {
26457 status = v_status;
26458 goto exit;
26459 }
26460 if (self->private_impl.f_end_of_block) {
26461 goto label__outer__continue;
26462 }
26463 if (a_src) {
26464 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26465 }
26466 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
26467 status = wuffs_deflate__decoder__decode_huffman_slow(self, a_dst, a_src);
26468 if (a_src) {
26469 iop_a_src = a_src->data.ptr + a_src->meta.ri;
26470 }
26471 if (status.repr) {
26472 goto suspend;
26473 }
26474 if (self->private_impl.f_end_of_block) {
26475 goto label__outer__continue;
26476 }
26477 }
26478 }
26479
Nigel Taoe360a532021-04-05 22:47:03 +100026480 ok:
26481 self->private_impl.p_decode_blocks[0] = 0;
26482 goto exit;
26483 }
26484
26485 goto suspend;
26486 suspend:
26487 self->private_impl.p_decode_blocks[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
26488 self->private_data.s_decode_blocks[0].v_final = v_final;
26489
26490 goto exit;
26491 exit:
26492 if (a_src) {
26493 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26494 }
26495
26496 return status;
26497}
26498
26499// -------- func deflate.decoder.decode_uncompressed
26500
26501static wuffs_base__status
26502wuffs_deflate__decoder__decode_uncompressed(
26503 wuffs_deflate__decoder* self,
26504 wuffs_base__io_buffer* a_dst,
26505 wuffs_base__io_buffer* a_src) {
26506 wuffs_base__status status = wuffs_base__make_status(NULL);
26507
26508 uint32_t v_length = 0;
26509 uint32_t v_n_copied = 0;
26510
26511 uint8_t* iop_a_dst = NULL;
26512 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26513 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26514 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26515 if (a_dst) {
26516 io0_a_dst = a_dst->data.ptr;
26517 io1_a_dst = io0_a_dst + a_dst->meta.wi;
26518 iop_a_dst = io1_a_dst;
26519 io2_a_dst = io0_a_dst + a_dst->data.len;
26520 if (a_dst->meta.closed) {
26521 io2_a_dst = iop_a_dst;
26522 }
26523 }
26524 const uint8_t* iop_a_src = NULL;
26525 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26526 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26527 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26528 if (a_src) {
26529 io0_a_src = a_src->data.ptr;
26530 io1_a_src = io0_a_src + a_src->meta.ri;
26531 iop_a_src = io1_a_src;
26532 io2_a_src = io0_a_src + a_src->meta.wi;
26533 }
26534
26535 uint32_t coro_susp_point = self->private_impl.p_decode_uncompressed[0];
26536 if (coro_susp_point) {
26537 v_length = self->private_data.s_decode_uncompressed[0].v_length;
26538 }
26539 switch (coro_susp_point) {
26540 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
26541
26542 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
26543 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
26544 goto exit;
26545 }
26546 self->private_impl.f_n_bits = 0;
26547 self->private_impl.f_bits = 0;
26548 {
26549 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
26550 uint32_t t_0;
26551 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
26552 t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
26553 iop_a_src += 4;
26554 } else {
26555 self->private_data.s_decode_uncompressed[0].scratch = 0;
26556 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
26557 while (true) {
26558 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
26559 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26560 goto suspend;
26561 }
26562 uint64_t* scratch = &self->private_data.s_decode_uncompressed[0].scratch;
26563 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
26564 *scratch <<= 8;
26565 *scratch >>= 8;
26566 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
26567 if (num_bits_0 == 24) {
26568 t_0 = ((uint32_t)(*scratch));
26569 break;
26570 }
26571 num_bits_0 += 8;
26572 *scratch |= ((uint64_t)(num_bits_0)) << 56;
26573 }
26574 }
26575 v_length = t_0;
26576 }
26577 if ((((v_length) & 0xFFFF) + ((v_length) >> (32 - (16)))) != 65535) {
26578 status = wuffs_base__make_status(wuffs_deflate__error__inconsistent_stored_block_length);
26579 goto exit;
26580 }
26581 v_length = ((v_length) & 0xFFFF);
26582 while (true) {
26583 v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_reader(
26584 &iop_a_dst, io2_a_dst,v_length, &iop_a_src, io2_a_src);
26585 if (v_length <= v_n_copied) {
26586 status = wuffs_base__make_status(NULL);
26587 goto ok;
26588 }
26589 v_length -= v_n_copied;
26590 if (((uint64_t)(io2_a_dst - iop_a_dst)) == 0) {
26591 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
26592 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
26593 } else {
26594 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26595 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
26596 }
26597 }
26598
Nigel Taoe360a532021-04-05 22:47:03 +100026599 ok:
26600 self->private_impl.p_decode_uncompressed[0] = 0;
26601 goto exit;
26602 }
26603
26604 goto suspend;
26605 suspend:
26606 self->private_impl.p_decode_uncompressed[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
26607 self->private_data.s_decode_uncompressed[0].v_length = v_length;
26608
26609 goto exit;
26610 exit:
26611 if (a_dst) {
26612 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
26613 }
26614 if (a_src) {
26615 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26616 }
26617
26618 return status;
26619}
26620
26621// -------- func deflate.decoder.init_fixed_huffman
26622
26623static wuffs_base__status
26624wuffs_deflate__decoder__init_fixed_huffman(
26625 wuffs_deflate__decoder* self) {
26626 uint32_t v_i = 0;
26627 wuffs_base__status v_status = wuffs_base__make_status(NULL);
26628
26629 while (v_i < 144) {
26630 self->private_data.f_code_lengths[v_i] = 8;
26631 v_i += 1;
26632 }
26633 while (v_i < 256) {
26634 self->private_data.f_code_lengths[v_i] = 9;
26635 v_i += 1;
26636 }
26637 while (v_i < 280) {
26638 self->private_data.f_code_lengths[v_i] = 7;
26639 v_i += 1;
26640 }
26641 while (v_i < 288) {
26642 self->private_data.f_code_lengths[v_i] = 8;
26643 v_i += 1;
26644 }
26645 while (v_i < 320) {
26646 self->private_data.f_code_lengths[v_i] = 5;
26647 v_i += 1;
26648 }
26649 v_status = wuffs_deflate__decoder__init_huff(self,
26650 0,
26651 0,
26652 288,
26653 257);
26654 if (wuffs_base__status__is_error(&v_status)) {
26655 return v_status;
26656 }
26657 v_status = wuffs_deflate__decoder__init_huff(self,
26658 1,
26659 288,
26660 320,
26661 0);
26662 if (wuffs_base__status__is_error(&v_status)) {
26663 return v_status;
26664 }
26665 return wuffs_base__make_status(NULL);
26666}
26667
26668// -------- func deflate.decoder.init_dynamic_huffman
26669
26670static wuffs_base__status
26671wuffs_deflate__decoder__init_dynamic_huffman(
26672 wuffs_deflate__decoder* self,
26673 wuffs_base__io_buffer* a_src) {
26674 wuffs_base__status status = wuffs_base__make_status(NULL);
26675
26676 uint32_t v_bits = 0;
26677 uint32_t v_n_bits = 0;
26678 uint32_t v_b0 = 0;
26679 uint32_t v_n_lit = 0;
26680 uint32_t v_n_dist = 0;
26681 uint32_t v_n_clen = 0;
26682 uint32_t v_i = 0;
26683 uint32_t v_b1 = 0;
26684 wuffs_base__status v_status = wuffs_base__make_status(NULL);
26685 uint32_t v_mask = 0;
26686 uint32_t v_table_entry = 0;
26687 uint32_t v_table_entry_n_bits = 0;
26688 uint32_t v_b2 = 0;
26689 uint32_t v_n_extra_bits = 0;
26690 uint8_t v_rep_symbol = 0;
26691 uint32_t v_rep_count = 0;
26692 uint32_t v_b3 = 0;
26693
26694 const uint8_t* iop_a_src = NULL;
26695 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26696 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26697 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26698 if (a_src) {
26699 io0_a_src = a_src->data.ptr;
26700 io1_a_src = io0_a_src + a_src->meta.ri;
26701 iop_a_src = io1_a_src;
26702 io2_a_src = io0_a_src + a_src->meta.wi;
26703 }
26704
26705 uint32_t coro_susp_point = self->private_impl.p_init_dynamic_huffman[0];
26706 if (coro_susp_point) {
26707 v_bits = self->private_data.s_init_dynamic_huffman[0].v_bits;
26708 v_n_bits = self->private_data.s_init_dynamic_huffman[0].v_n_bits;
26709 v_n_lit = self->private_data.s_init_dynamic_huffman[0].v_n_lit;
26710 v_n_dist = self->private_data.s_init_dynamic_huffman[0].v_n_dist;
26711 v_n_clen = self->private_data.s_init_dynamic_huffman[0].v_n_clen;
26712 v_i = self->private_data.s_init_dynamic_huffman[0].v_i;
26713 v_mask = self->private_data.s_init_dynamic_huffman[0].v_mask;
26714 v_table_entry = self->private_data.s_init_dynamic_huffman[0].v_table_entry;
26715 v_n_extra_bits = self->private_data.s_init_dynamic_huffman[0].v_n_extra_bits;
26716 v_rep_symbol = self->private_data.s_init_dynamic_huffman[0].v_rep_symbol;
26717 v_rep_count = self->private_data.s_init_dynamic_huffman[0].v_rep_count;
26718 }
26719 switch (coro_susp_point) {
26720 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
26721
26722 v_bits = self->private_impl.f_bits;
26723 v_n_bits = self->private_impl.f_n_bits;
26724 while (v_n_bits < 14) {
26725 {
26726 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
26727 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
26728 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26729 goto suspend;
26730 }
26731 uint32_t t_0 = *iop_a_src++;
26732 v_b0 = t_0;
26733 }
26734 v_bits |= (v_b0 << v_n_bits);
26735 v_n_bits += 8;
26736 }
26737 v_n_lit = (((v_bits) & 0x1F) + 257);
26738 if (v_n_lit > 286) {
26739 status = wuffs_base__make_status(wuffs_deflate__error__bad_literal_length_code_count);
26740 goto exit;
26741 }
26742 v_bits >>= 5;
26743 v_n_dist = (((v_bits) & 0x1F) + 1);
26744 if (v_n_dist > 30) {
26745 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance_code_count);
26746 goto exit;
26747 }
26748 v_bits >>= 5;
26749 v_n_clen = (((v_bits) & 0xF) + 4);
26750 v_bits >>= 4;
26751 v_n_bits -= 14;
26752 v_i = 0;
26753 while (v_i < v_n_clen) {
26754 while (v_n_bits < 3) {
26755 {
26756 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
26757 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
26758 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26759 goto suspend;
26760 }
26761 uint32_t t_1 = *iop_a_src++;
26762 v_b1 = t_1;
26763 }
26764 v_bits |= (v_b1 << v_n_bits);
26765 v_n_bits += 8;
26766 }
26767 self->private_data.f_code_lengths[WUFFS_DEFLATE__CODE_ORDER[v_i]] = ((uint8_t)((v_bits & 7)));
26768 v_bits >>= 3;
26769 v_n_bits -= 3;
26770 v_i += 1;
26771 }
26772 while (v_i < 19) {
26773 self->private_data.f_code_lengths[WUFFS_DEFLATE__CODE_ORDER[v_i]] = 0;
26774 v_i += 1;
26775 }
26776 v_status = wuffs_deflate__decoder__init_huff(self,
26777 0,
26778 0,
26779 19,
26780 4095);
26781 if (wuffs_base__status__is_error(&v_status)) {
26782 status = v_status;
26783 goto exit;
26784 }
26785 v_mask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
26786 v_i = 0;
26787 label__0__continue:;
26788 while (v_i < (v_n_lit + v_n_dist)) {
26789 while (true) {
26790 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_mask)];
26791 v_table_entry_n_bits = (v_table_entry & 15);
26792 if (v_n_bits >= v_table_entry_n_bits) {
26793 v_bits >>= v_table_entry_n_bits;
26794 v_n_bits -= v_table_entry_n_bits;
26795 goto label__1__break;
26796 }
26797 {
26798 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
26799 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
26800 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26801 goto suspend;
26802 }
26803 uint32_t t_2 = *iop_a_src++;
26804 v_b2 = t_2;
26805 }
26806 v_bits |= (v_b2 << v_n_bits);
26807 v_n_bits += 8;
26808 }
26809 label__1__break:;
26810 if ((v_table_entry >> 24) != 128) {
26811 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
26812 goto exit;
26813 }
26814 v_table_entry = ((v_table_entry >> 8) & 255);
26815 if (v_table_entry < 16) {
26816 self->private_data.f_code_lengths[v_i] = ((uint8_t)(v_table_entry));
26817 v_i += 1;
26818 goto label__0__continue;
26819 }
26820 v_n_extra_bits = 0;
26821 v_rep_symbol = 0;
26822 v_rep_count = 0;
26823 if (v_table_entry == 16) {
26824 v_n_extra_bits = 2;
26825 if (v_i <= 0) {
26826 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_repetition);
26827 goto exit;
26828 }
26829 v_rep_symbol = (self->private_data.f_code_lengths[(v_i - 1)] & 15);
26830 v_rep_count = 3;
26831 } else if (v_table_entry == 17) {
26832 v_n_extra_bits = 3;
26833 v_rep_symbol = 0;
26834 v_rep_count = 3;
26835 } else if (v_table_entry == 18) {
26836 v_n_extra_bits = 7;
26837 v_rep_symbol = 0;
26838 v_rep_count = 11;
26839 } else {
26840 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
26841 goto exit;
26842 }
26843 while (v_n_bits < v_n_extra_bits) {
26844 {
26845 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
26846 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
26847 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26848 goto suspend;
26849 }
26850 uint32_t t_3 = *iop_a_src++;
26851 v_b3 = t_3;
26852 }
26853 v_bits |= (v_b3 << v_n_bits);
26854 v_n_bits += 8;
26855 }
26856 v_rep_count += ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_n_extra_bits));
26857 v_bits >>= v_n_extra_bits;
26858 v_n_bits -= v_n_extra_bits;
26859 while (v_rep_count > 0) {
26860 if (v_i >= (v_n_lit + v_n_dist)) {
26861 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_count);
26862 goto exit;
26863 }
26864 self->private_data.f_code_lengths[v_i] = v_rep_symbol;
26865 v_i += 1;
26866 v_rep_count -= 1;
26867 }
26868 }
26869 if (v_i != (v_n_lit + v_n_dist)) {
26870 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_count);
26871 goto exit;
26872 }
26873 if (self->private_data.f_code_lengths[256] == 0) {
26874 status = wuffs_base__make_status(wuffs_deflate__error__missing_end_of_block_code);
26875 goto exit;
26876 }
26877 v_status = wuffs_deflate__decoder__init_huff(self,
26878 0,
26879 0,
26880 v_n_lit,
26881 257);
26882 if (wuffs_base__status__is_error(&v_status)) {
26883 status = v_status;
26884 goto exit;
26885 }
26886 v_status = wuffs_deflate__decoder__init_huff(self,
26887 1,
26888 v_n_lit,
26889 (v_n_lit + v_n_dist),
26890 0);
26891 if (wuffs_base__status__is_error(&v_status)) {
26892 status = v_status;
26893 goto exit;
26894 }
26895 self->private_impl.f_bits = v_bits;
26896 self->private_impl.f_n_bits = v_n_bits;
26897
26898 goto ok;
26899 ok:
26900 self->private_impl.p_init_dynamic_huffman[0] = 0;
26901 goto exit;
26902 }
26903
26904 goto suspend;
26905 suspend:
26906 self->private_impl.p_init_dynamic_huffman[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
26907 self->private_data.s_init_dynamic_huffman[0].v_bits = v_bits;
26908 self->private_data.s_init_dynamic_huffman[0].v_n_bits = v_n_bits;
26909 self->private_data.s_init_dynamic_huffman[0].v_n_lit = v_n_lit;
26910 self->private_data.s_init_dynamic_huffman[0].v_n_dist = v_n_dist;
26911 self->private_data.s_init_dynamic_huffman[0].v_n_clen = v_n_clen;
26912 self->private_data.s_init_dynamic_huffman[0].v_i = v_i;
26913 self->private_data.s_init_dynamic_huffman[0].v_mask = v_mask;
26914 self->private_data.s_init_dynamic_huffman[0].v_table_entry = v_table_entry;
26915 self->private_data.s_init_dynamic_huffman[0].v_n_extra_bits = v_n_extra_bits;
26916 self->private_data.s_init_dynamic_huffman[0].v_rep_symbol = v_rep_symbol;
26917 self->private_data.s_init_dynamic_huffman[0].v_rep_count = v_rep_count;
26918
26919 goto exit;
26920 exit:
26921 if (a_src) {
26922 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26923 }
26924
26925 return status;
26926}
26927
26928// -------- func deflate.decoder.init_huff
26929
26930static wuffs_base__status
26931wuffs_deflate__decoder__init_huff(
26932 wuffs_deflate__decoder* self,
26933 uint32_t a_which,
26934 uint32_t a_n_codes0,
26935 uint32_t a_n_codes1,
26936 uint32_t a_base_symbol) {
26937 uint16_t v_counts[16] = {0};
26938 uint32_t v_i = 0;
26939 uint32_t v_remaining = 0;
26940 uint16_t v_offsets[16] = {0};
26941 uint32_t v_n_symbols = 0;
26942 uint32_t v_count = 0;
26943 uint16_t v_symbols[320] = {0};
26944 uint32_t v_min_cl = 0;
26945 uint32_t v_max_cl = 0;
26946 uint32_t v_initial_high_bits = 0;
26947 uint32_t v_prev_cl = 0;
26948 uint32_t v_prev_redirect_key = 0;
26949 uint32_t v_top = 0;
26950 uint32_t v_next_top = 0;
26951 uint32_t v_code = 0;
26952 uint32_t v_key = 0;
26953 uint32_t v_value = 0;
26954 uint32_t v_cl = 0;
26955 uint32_t v_redirect_key = 0;
26956 uint32_t v_j = 0;
26957 uint32_t v_reversed_key = 0;
26958 uint32_t v_symbol = 0;
26959 uint32_t v_high_bits = 0;
26960 uint32_t v_delta = 0;
26961
26962 v_i = a_n_codes0;
26963 while (v_i < a_n_codes1) {
26964 if (v_counts[(self->private_data.f_code_lengths[v_i] & 15)] >= 320) {
26965 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
26966 }
26967#if defined(__GNUC__)
26968#pragma GCC diagnostic push
26969#pragma GCC diagnostic ignored "-Wconversion"
26970#endif
26971 v_counts[(self->private_data.f_code_lengths[v_i] & 15)] += 1;
26972#if defined(__GNUC__)
26973#pragma GCC diagnostic pop
26974#endif
26975 v_i += 1;
26976 }
26977 if ((((uint32_t)(v_counts[0])) + a_n_codes0) == a_n_codes1) {
26978 return wuffs_base__make_status(wuffs_deflate__error__no_huffman_codes);
26979 }
26980 v_remaining = 1;
26981 v_i = 1;
26982 while (v_i <= 15) {
26983 if (v_remaining > 1073741824) {
26984 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
26985 }
26986 v_remaining <<= 1;
26987 if (v_remaining < ((uint32_t)(v_counts[v_i]))) {
26988 return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_over_subscribed);
26989 }
26990 v_remaining -= ((uint32_t)(v_counts[v_i]));
26991 v_i += 1;
26992 }
26993 if (v_remaining != 0) {
26994 if ((a_which == 1) &&
26995 (v_counts[1] == 1) &&
26996 (self->private_data.f_code_lengths[a_n_codes0] == 1) &&
26997 ((((uint32_t)(v_counts[0])) + a_n_codes0 + 1) == a_n_codes1)) {
26998 self->private_impl.f_n_huffs_bits[1] = 1;
26999 self->private_data.f_huffs[1][0] = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[0] | 1);
27000 self->private_data.f_huffs[1][1] = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[31] | 1);
27001 return wuffs_base__make_status(NULL);
27002 }
27003 return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_under_subscribed);
27004 }
27005 v_i = 1;
27006 while (v_i <= 15) {
27007 v_offsets[v_i] = ((uint16_t)(v_n_symbols));
27008 v_count = ((uint32_t)(v_counts[v_i]));
27009 if (v_n_symbols > (320 - v_count)) {
27010 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27011 }
27012 v_n_symbols = (v_n_symbols + v_count);
27013 v_i += 1;
27014 }
27015 if (v_n_symbols > 288) {
27016 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27017 }
27018 v_i = a_n_codes0;
27019 while (v_i < a_n_codes1) {
27020 if (v_i < a_n_codes0) {
27021 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27022 }
27023 if (self->private_data.f_code_lengths[v_i] != 0) {
27024 if (v_offsets[(self->private_data.f_code_lengths[v_i] & 15)] >= 320) {
27025 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27026 }
27027 v_symbols[v_offsets[(self->private_data.f_code_lengths[v_i] & 15)]] = ((uint16_t)((v_i - a_n_codes0)));
27028#if defined(__GNUC__)
27029#pragma GCC diagnostic push
27030#pragma GCC diagnostic ignored "-Wconversion"
27031#endif
27032 v_offsets[(self->private_data.f_code_lengths[v_i] & 15)] += 1;
27033#if defined(__GNUC__)
27034#pragma GCC diagnostic pop
27035#endif
27036 }
27037 v_i += 1;
27038 }
27039 v_min_cl = 1;
27040 while (true) {
27041 if (v_counts[v_min_cl] != 0) {
27042 goto label__0__break;
27043 }
27044 if (v_min_cl >= 9) {
27045 return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_minimum_code_length);
27046 }
27047 v_min_cl += 1;
27048 }
27049 label__0__break:;
27050 v_max_cl = 15;
27051 while (true) {
27052 if (v_counts[v_max_cl] != 0) {
27053 goto label__1__break;
27054 }
27055 if (v_max_cl <= 1) {
27056 return wuffs_base__make_status(wuffs_deflate__error__no_huffman_codes);
27057 }
27058 v_max_cl -= 1;
27059 }
27060 label__1__break:;
27061 if (v_max_cl <= 9) {
27062 self->private_impl.f_n_huffs_bits[a_which] = v_max_cl;
27063 } else {
27064 self->private_impl.f_n_huffs_bits[a_which] = 9;
27065 }
27066 v_i = 0;
27067 if ((v_n_symbols != ((uint32_t)(v_offsets[v_max_cl]))) || (v_n_symbols != ((uint32_t)(v_offsets[15])))) {
27068 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27069 }
27070 if ((a_n_codes0 + ((uint32_t)(v_symbols[0]))) >= 320) {
27071 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27072 }
27073 v_initial_high_bits = 512;
27074 if (v_max_cl < 9) {
27075 v_initial_high_bits = (((uint32_t)(1)) << v_max_cl);
27076 }
27077 v_prev_cl = ((uint32_t)((self->private_data.f_code_lengths[(a_n_codes0 + ((uint32_t)(v_symbols[0])))] & 15)));
27078 v_prev_redirect_key = 4294967295;
27079 v_top = 0;
27080 v_next_top = 512;
27081 v_code = 0;
27082 v_key = 0;
27083 v_value = 0;
27084 while (true) {
27085 if ((a_n_codes0 + ((uint32_t)(v_symbols[v_i]))) >= 320) {
27086 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27087 }
27088 v_cl = ((uint32_t)((self->private_data.f_code_lengths[(a_n_codes0 + ((uint32_t)(v_symbols[v_i])))] & 15)));
27089 if (v_cl > v_prev_cl) {
27090 v_code <<= (v_cl - v_prev_cl);
27091 if (v_code >= 32768) {
27092 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27093 }
27094 }
27095 v_prev_cl = v_cl;
27096 v_key = v_code;
27097 if (v_cl > 9) {
27098 v_cl -= 9;
27099 v_redirect_key = ((v_key >> v_cl) & 511);
27100 v_key = ((v_key) & WUFFS_BASE__LOW_BITS_MASK__U32(v_cl));
27101 if (v_prev_redirect_key != v_redirect_key) {
27102 v_prev_redirect_key = v_redirect_key;
27103 v_remaining = (((uint32_t)(1)) << v_cl);
27104 v_j = v_prev_cl;
27105 while (v_j <= 15) {
27106 if (v_remaining <= ((uint32_t)(v_counts[v_j]))) {
27107 goto label__2__break;
27108 }
27109 v_remaining -= ((uint32_t)(v_counts[v_j]));
27110 if (v_remaining > 1073741824) {
27111 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27112 }
27113 v_remaining <<= 1;
27114 v_j += 1;
27115 }
27116 label__2__break:;
27117 if ((v_j <= 9) || (15 < v_j)) {
27118 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27119 }
27120 v_j -= 9;
27121 v_initial_high_bits = (((uint32_t)(1)) << v_j);
27122 v_top = v_next_top;
27123 if ((v_top + (((uint32_t)(1)) << v_j)) > 1024) {
27124 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27125 }
27126 v_next_top = (v_top + (((uint32_t)(1)) << v_j));
27127 v_redirect_key = (((uint32_t)(WUFFS_DEFLATE__REVERSE8[(v_redirect_key >> 1)])) | ((v_redirect_key & 1) << 8));
27128 self->private_data.f_huffs[a_which][v_redirect_key] = (268435465 | (v_top << 8) | (v_j << 4));
27129 }
27130 }
27131 if ((v_key >= 512) || (v_counts[v_prev_cl] <= 0)) {
27132 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27133 }
27134#if defined(__GNUC__)
27135#pragma GCC diagnostic push
27136#pragma GCC diagnostic ignored "-Wconversion"
27137#endif
27138 v_counts[v_prev_cl] -= 1;
27139#if defined(__GNUC__)
27140#pragma GCC diagnostic pop
27141#endif
27142 v_reversed_key = (((uint32_t)(WUFFS_DEFLATE__REVERSE8[(v_key >> 1)])) | ((v_key & 1) << 8));
27143 v_reversed_key >>= (9 - v_cl);
27144 v_symbol = ((uint32_t)(v_symbols[v_i]));
27145 if (v_symbol == 256) {
27146 v_value = (536870912 | v_cl);
27147 } else if ((v_symbol < 256) && (a_which == 0)) {
27148 v_value = (2147483648 | (v_symbol << 8) | v_cl);
27149 } else if (v_symbol >= a_base_symbol) {
27150 v_symbol -= a_base_symbol;
27151 if (a_which == 0) {
27152 v_value = (WUFFS_DEFLATE__LCODE_MAGIC_NUMBERS[(v_symbol & 31)] | v_cl);
27153 } else {
27154 v_value = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[(v_symbol & 31)] | v_cl);
27155 }
27156 } else {
27157 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27158 }
27159 v_high_bits = v_initial_high_bits;
27160 v_delta = (((uint32_t)(1)) << v_cl);
27161 while (v_high_bits >= v_delta) {
27162 v_high_bits -= v_delta;
27163 if ((v_top + ((v_high_bits | v_reversed_key) & 511)) >= 1024) {
27164 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27165 }
27166 self->private_data.f_huffs[a_which][(v_top + ((v_high_bits | v_reversed_key) & 511))] = v_value;
27167 }
27168 v_i += 1;
27169 if (v_i >= v_n_symbols) {
27170 goto label__3__break;
27171 }
27172 v_code += 1;
27173 if (v_code >= 32768) {
27174 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27175 }
27176 }
27177 label__3__break:;
27178 return wuffs_base__make_status(NULL);
27179}
27180
Nigel Tao5571bfe2021-06-24 22:44:29 +100027181// ‼ WUFFS MULTI-FILE SECTION +x86_bmi2
27182// -------- func deflate.decoder.decode_huffman_bmi2
27183
Nigel Tao7804ffe2021-10-07 21:58:26 +110027184#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100027185WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("bmi2")
27186static wuffs_base__status
27187wuffs_deflate__decoder__decode_huffman_bmi2(
27188 wuffs_deflate__decoder* self,
27189 wuffs_base__io_buffer* a_dst,
27190 wuffs_base__io_buffer* a_src) {
27191 wuffs_base__status status = wuffs_base__make_status(NULL);
27192
27193 uint64_t v_bits = 0;
27194 uint32_t v_n_bits = 0;
27195 uint32_t v_table_entry = 0;
27196 uint32_t v_table_entry_n_bits = 0;
27197 uint64_t v_lmask = 0;
27198 uint64_t v_dmask = 0;
27199 uint32_t v_redir_top = 0;
27200 uint32_t v_redir_mask = 0;
27201 uint32_t v_length = 0;
27202 uint32_t v_dist_minus_1 = 0;
27203 uint32_t v_hlen = 0;
27204 uint32_t v_hdist = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027205 uint32_t v_hdist_adjustment = 0;
Nigel Tao5571bfe2021-06-24 22:44:29 +100027206
27207 uint8_t* iop_a_dst = NULL;
27208 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27209 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27210 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27211 if (a_dst) {
27212 io0_a_dst = a_dst->data.ptr;
27213 io1_a_dst = io0_a_dst + a_dst->meta.wi;
27214 iop_a_dst = io1_a_dst;
27215 io2_a_dst = io0_a_dst + a_dst->data.len;
27216 if (a_dst->meta.closed) {
27217 io2_a_dst = iop_a_dst;
27218 }
27219 }
27220 const uint8_t* iop_a_src = NULL;
27221 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27222 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27223 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27224 if (a_src) {
27225 io0_a_src = a_src->data.ptr;
27226 io1_a_src = io0_a_src + a_src->meta.ri;
27227 iop_a_src = io1_a_src;
27228 io2_a_src = io0_a_src + a_src->meta.wi;
27229 }
27230
27231 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
27232 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27233 goto exit;
27234 }
27235 v_bits = ((uint64_t)(self->private_impl.f_bits));
27236 v_n_bits = self->private_impl.f_n_bits;
27237 v_lmask = ((((uint64_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
27238 v_dmask = ((((uint64_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027239 if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0)) {
27240 status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position);
27241 goto exit;
27242 }
27243 v_hdist_adjustment = ((uint32_t)(((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0)) & 4294967295)));
Nigel Tao5571bfe2021-06-24 22:44:29 +100027244 label__loop__continue:;
27245 while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266) && (((uint64_t)(io2_a_src - iop_a_src)) >= 8)) {
27246 v_bits |= ((uint64_t)(wuffs_base__peek_u64le__no_bounds_check(iop_a_src) << (v_n_bits & 63)));
27247 iop_a_src += ((63 - (v_n_bits & 63)) >> 3);
27248 v_n_bits |= 56;
27249 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_lmask)];
27250 v_table_entry_n_bits = (v_table_entry & 15);
27251 v_bits >>= v_table_entry_n_bits;
27252 v_n_bits -= v_table_entry_n_bits;
27253 if ((v_table_entry >> 31) != 0) {
27254 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
27255 goto label__loop__continue;
27256 } else if ((v_table_entry >> 30) != 0) {
27257 } else if ((v_table_entry >> 29) != 0) {
27258 self->private_impl.f_end_of_block = true;
27259 goto label__loop__break;
27260 } else if ((v_table_entry >> 28) != 0) {
27261 v_redir_top = ((v_table_entry >> 8) & 65535);
27262 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
27263 v_table_entry = self->private_data.f_huffs[0][((v_redir_top + (((uint32_t)((v_bits & 4294967295))) & v_redir_mask)) & 1023)];
27264 v_table_entry_n_bits = (v_table_entry & 15);
27265 v_bits >>= v_table_entry_n_bits;
27266 v_n_bits -= v_table_entry_n_bits;
27267 if ((v_table_entry >> 31) != 0) {
27268 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
27269 goto label__loop__continue;
27270 } else if ((v_table_entry >> 30) != 0) {
27271 } else if ((v_table_entry >> 29) != 0) {
27272 self->private_impl.f_end_of_block = true;
27273 goto label__loop__break;
27274 } else if ((v_table_entry >> 28) != 0) {
27275 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27276 goto exit;
27277 } else if ((v_table_entry >> 27) != 0) {
27278 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27279 goto exit;
27280 } else {
27281 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27282 goto exit;
27283 }
27284 } else if ((v_table_entry >> 27) != 0) {
27285 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27286 goto exit;
27287 } else {
27288 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27289 goto exit;
27290 }
27291 v_length = (((v_table_entry >> 8) & 255) + 3);
27292 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
27293 if (v_table_entry_n_bits > 0) {
27294 v_length = (((v_length + 253 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 255) + 3);
27295 v_bits >>= v_table_entry_n_bits;
27296 v_n_bits -= v_table_entry_n_bits;
27297 }
27298 v_table_entry = self->private_data.f_huffs[1][(v_bits & v_dmask)];
27299 v_table_entry_n_bits = (v_table_entry & 15);
27300 v_bits >>= v_table_entry_n_bits;
27301 v_n_bits -= v_table_entry_n_bits;
27302 if ((v_table_entry >> 28) == 1) {
27303 v_redir_top = ((v_table_entry >> 8) & 65535);
27304 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
27305 v_table_entry = self->private_data.f_huffs[1][((v_redir_top + (((uint32_t)((v_bits & 4294967295))) & v_redir_mask)) & 1023)];
27306 v_table_entry_n_bits = (v_table_entry & 15);
27307 v_bits >>= v_table_entry_n_bits;
27308 v_n_bits -= v_table_entry_n_bits;
27309 }
27310 if ((v_table_entry >> 24) != 64) {
27311 if ((v_table_entry >> 24) == 8) {
27312 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27313 goto exit;
27314 }
27315 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27316 goto exit;
27317 }
27318 v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
27319 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
27320 v_dist_minus_1 = ((v_dist_minus_1 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 32767);
27321 v_bits >>= v_table_entry_n_bits;
27322 v_n_bits -= v_table_entry_n_bits;
27323 while (true) {
27324 if (((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) {
27325 v_hlen = 0;
27326 v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) - ((uint64_t)(iop_a_dst - io0_a_dst)))));
27327 if (v_length > v_hdist) {
27328 v_length -= v_hdist;
27329 v_hlen = v_hdist;
27330 } else {
27331 v_hlen = v_length;
27332 v_length = 0;
27333 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027334 v_hdist += v_hdist_adjustment;
Nigel Tao5571bfe2021-06-24 22:44:29 +100027335 if (self->private_impl.f_history_index < v_hdist) {
27336 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance);
27337 goto exit;
27338 }
27339 v_hdist = (self->private_impl.f_history_index - v_hdist);
27340 wuffs_base__io_writer__limited_copy_u32_from_slice(
27341 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__slice_u8__subslice_i(wuffs_base__make_slice_u8(self->private_data.f_history, 33025), (v_hdist & 32767)));
27342 if (v_length == 0) {
27343 goto label__loop__continue;
27344 }
27345 if ((((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) {
27346 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance);
27347 goto exit;
27348 }
27349 }
27350 if ((v_dist_minus_1 + 1) >= 8) {
27351 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast(
27352 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
27353 } else if ((v_dist_minus_1 + 1) == 1) {
27354 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast(
27355 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
27356 } else {
27357 wuffs_base__io_writer__limited_copy_u32_from_history_fast(
27358 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
27359 }
27360 goto label__0__break;
27361 }
27362 label__0__break:;
27363 }
27364 label__loop__break:;
27365 if (v_n_bits > 63) {
27366 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27367 goto exit;
27368 }
27369 while (v_n_bits >= 8) {
27370 v_n_bits -= 8;
27371 if (iop_a_src > io1_a_src) {
27372 iop_a_src--;
27373 } else {
27374 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o);
27375 goto exit;
27376 }
27377 }
27378 self->private_impl.f_bits = ((uint32_t)((v_bits & ((((uint64_t)(1)) << v_n_bits) - 1))));
27379 self->private_impl.f_n_bits = v_n_bits;
27380 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
27381 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27382 goto exit;
27383 }
27384 goto exit;
27385 exit:
27386 if (a_dst) {
27387 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
27388 }
27389 if (a_src) {
27390 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
27391 }
27392
27393 return status;
27394}
Nigel Tao7804ffe2021-10-07 21:58:26 +110027395#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100027396// ‼ WUFFS MULTI-FILE SECTION -x86_bmi2
27397
Nigel Taoe360a532021-04-05 22:47:03 +100027398// -------- func deflate.decoder.decode_huffman_fast32
27399
27400static wuffs_base__status
27401wuffs_deflate__decoder__decode_huffman_fast32(
27402 wuffs_deflate__decoder* self,
27403 wuffs_base__io_buffer* a_dst,
27404 wuffs_base__io_buffer* a_src) {
27405 wuffs_base__status status = wuffs_base__make_status(NULL);
27406
27407 uint32_t v_bits = 0;
27408 uint32_t v_n_bits = 0;
27409 uint32_t v_table_entry = 0;
27410 uint32_t v_table_entry_n_bits = 0;
27411 uint32_t v_lmask = 0;
27412 uint32_t v_dmask = 0;
27413 uint32_t v_redir_top = 0;
27414 uint32_t v_redir_mask = 0;
27415 uint32_t v_length = 0;
27416 uint32_t v_dist_minus_1 = 0;
27417 uint32_t v_hlen = 0;
27418 uint32_t v_hdist = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027419 uint32_t v_hdist_adjustment = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100027420
27421 uint8_t* iop_a_dst = NULL;
27422 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27423 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27424 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27425 if (a_dst) {
27426 io0_a_dst = a_dst->data.ptr;
27427 io1_a_dst = io0_a_dst + a_dst->meta.wi;
27428 iop_a_dst = io1_a_dst;
27429 io2_a_dst = io0_a_dst + a_dst->data.len;
27430 if (a_dst->meta.closed) {
27431 io2_a_dst = iop_a_dst;
27432 }
27433 }
27434 const uint8_t* iop_a_src = NULL;
27435 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27436 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27437 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27438 if (a_src) {
27439 io0_a_src = a_src->data.ptr;
27440 io1_a_src = io0_a_src + a_src->meta.ri;
27441 iop_a_src = io1_a_src;
27442 io2_a_src = io0_a_src + a_src->meta.wi;
27443 }
27444
27445 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
27446 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27447 goto exit;
27448 }
27449 v_bits = self->private_impl.f_bits;
27450 v_n_bits = self->private_impl.f_n_bits;
27451 v_lmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
27452 v_dmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027453 if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0)) {
27454 status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position);
27455 goto exit;
27456 }
27457 v_hdist_adjustment = ((uint32_t)(((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0)) & 4294967295)));
Nigel Taoe360a532021-04-05 22:47:03 +100027458 label__loop__continue:;
27459 while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266) && (((uint64_t)(io2_a_src - iop_a_src)) >= 12)) {
27460 if (v_n_bits < 15) {
27461 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27462 iop_a_src += 1;
27463 v_n_bits += 8;
27464 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27465 iop_a_src += 1;
27466 v_n_bits += 8;
27467 } else {
27468 }
27469 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_lmask)];
27470 v_table_entry_n_bits = (v_table_entry & 15);
27471 v_bits >>= v_table_entry_n_bits;
27472 v_n_bits -= v_table_entry_n_bits;
27473 if ((v_table_entry >> 31) != 0) {
27474 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
27475 goto label__loop__continue;
27476 } else if ((v_table_entry >> 30) != 0) {
27477 } else if ((v_table_entry >> 29) != 0) {
27478 self->private_impl.f_end_of_block = true;
27479 goto label__loop__break;
27480 } else if ((v_table_entry >> 28) != 0) {
27481 if (v_n_bits < 15) {
27482 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27483 iop_a_src += 1;
27484 v_n_bits += 8;
27485 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27486 iop_a_src += 1;
27487 v_n_bits += 8;
27488 } else {
27489 }
27490 v_redir_top = ((v_table_entry >> 8) & 65535);
27491 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
27492 v_table_entry = self->private_data.f_huffs[0][((v_redir_top + (v_bits & v_redir_mask)) & 1023)];
27493 v_table_entry_n_bits = (v_table_entry & 15);
27494 v_bits >>= v_table_entry_n_bits;
27495 v_n_bits -= v_table_entry_n_bits;
27496 if ((v_table_entry >> 31) != 0) {
27497 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
27498 goto label__loop__continue;
27499 } else if ((v_table_entry >> 30) != 0) {
27500 } else if ((v_table_entry >> 29) != 0) {
27501 self->private_impl.f_end_of_block = true;
27502 goto label__loop__break;
27503 } else if ((v_table_entry >> 28) != 0) {
27504 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27505 goto exit;
27506 } else if ((v_table_entry >> 27) != 0) {
27507 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27508 goto exit;
27509 } else {
27510 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27511 goto exit;
27512 }
27513 } else if ((v_table_entry >> 27) != 0) {
27514 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27515 goto exit;
27516 } else {
27517 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27518 goto exit;
27519 }
27520 v_length = (((v_table_entry >> 8) & 255) + 3);
27521 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
27522 if (v_table_entry_n_bits > 0) {
27523 if (v_n_bits < 15) {
27524 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27525 iop_a_src += 1;
27526 v_n_bits += 8;
27527 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27528 iop_a_src += 1;
27529 v_n_bits += 8;
27530 } else {
27531 }
27532 v_length = (((v_length + 253 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 255) + 3);
27533 v_bits >>= v_table_entry_n_bits;
27534 v_n_bits -= v_table_entry_n_bits;
27535 } else {
27536 }
27537 if (v_n_bits < 15) {
27538 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27539 iop_a_src += 1;
27540 v_n_bits += 8;
27541 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27542 iop_a_src += 1;
27543 v_n_bits += 8;
27544 } else {
27545 }
27546 v_table_entry = self->private_data.f_huffs[1][(v_bits & v_dmask)];
27547 v_table_entry_n_bits = (v_table_entry & 15);
27548 v_bits >>= v_table_entry_n_bits;
27549 v_n_bits -= v_table_entry_n_bits;
27550 if ((v_table_entry >> 28) == 1) {
27551 if (v_n_bits < 15) {
27552 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27553 iop_a_src += 1;
27554 v_n_bits += 8;
27555 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27556 iop_a_src += 1;
27557 v_n_bits += 8;
27558 } else {
27559 }
27560 v_redir_top = ((v_table_entry >> 8) & 65535);
27561 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
27562 v_table_entry = self->private_data.f_huffs[1][((v_redir_top + (v_bits & v_redir_mask)) & 1023)];
27563 v_table_entry_n_bits = (v_table_entry & 15);
27564 v_bits >>= v_table_entry_n_bits;
27565 v_n_bits -= v_table_entry_n_bits;
27566 } else {
27567 }
27568 if ((v_table_entry >> 24) != 64) {
27569 if ((v_table_entry >> 24) == 8) {
27570 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27571 goto exit;
27572 }
27573 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27574 goto exit;
27575 }
27576 v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
27577 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
27578 if (v_n_bits < v_table_entry_n_bits) {
27579 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27580 iop_a_src += 1;
27581 v_n_bits += 8;
27582 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
27583 iop_a_src += 1;
27584 v_n_bits += 8;
27585 }
27586 v_dist_minus_1 = ((v_dist_minus_1 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 32767);
27587 v_bits >>= v_table_entry_n_bits;
27588 v_n_bits -= v_table_entry_n_bits;
27589 while (true) {
27590 if (((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) {
27591 v_hlen = 0;
27592 v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) - ((uint64_t)(iop_a_dst - io0_a_dst)))));
27593 if (v_length > v_hdist) {
27594 v_length -= v_hdist;
27595 v_hlen = v_hdist;
27596 } else {
27597 v_hlen = v_length;
27598 v_length = 0;
27599 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027600 v_hdist += v_hdist_adjustment;
Nigel Taoe360a532021-04-05 22:47:03 +100027601 if (self->private_impl.f_history_index < v_hdist) {
27602 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance);
27603 goto exit;
27604 }
27605 v_hdist = (self->private_impl.f_history_index - v_hdist);
27606 wuffs_base__io_writer__limited_copy_u32_from_slice(
27607 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__slice_u8__subslice_i(wuffs_base__make_slice_u8(self->private_data.f_history, 33025), (v_hdist & 32767)));
27608 if (v_length == 0) {
27609 goto label__loop__continue;
27610 }
27611 if ((((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) {
27612 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance);
27613 goto exit;
27614 }
27615 }
27616 if ((v_dist_minus_1 + 1) >= 8) {
27617 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast(
27618 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
27619 } else {
27620 wuffs_base__io_writer__limited_copy_u32_from_history_fast(
27621 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
27622 }
27623 goto label__0__break;
27624 }
27625 label__0__break:;
27626 }
27627 label__loop__break:;
27628 while (v_n_bits >= 8) {
27629 v_n_bits -= 8;
27630 if (iop_a_src > io1_a_src) {
27631 iop_a_src--;
27632 } else {
27633 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o);
27634 goto exit;
27635 }
27636 }
27637 self->private_impl.f_bits = (v_bits & ((((uint32_t)(1)) << v_n_bits) - 1));
27638 self->private_impl.f_n_bits = v_n_bits;
27639 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
27640 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27641 goto exit;
27642 }
27643 goto exit;
27644 exit:
27645 if (a_dst) {
27646 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
27647 }
27648 if (a_src) {
27649 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
27650 }
27651
27652 return status;
27653}
27654
27655// -------- func deflate.decoder.decode_huffman_fast64
27656
27657static wuffs_base__status
27658wuffs_deflate__decoder__decode_huffman_fast64(
27659 wuffs_deflate__decoder* self,
27660 wuffs_base__io_buffer* a_dst,
27661 wuffs_base__io_buffer* a_src) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100027662 return (*self->private_impl.choosy_decode_huffman_fast64)(self, a_dst, a_src);
27663}
27664
27665static wuffs_base__status
27666wuffs_deflate__decoder__decode_huffman_fast64__choosy_default(
27667 wuffs_deflate__decoder* self,
27668 wuffs_base__io_buffer* a_dst,
27669 wuffs_base__io_buffer* a_src) {
Nigel Taoe360a532021-04-05 22:47:03 +100027670 wuffs_base__status status = wuffs_base__make_status(NULL);
27671
27672 uint64_t v_bits = 0;
27673 uint32_t v_n_bits = 0;
27674 uint32_t v_table_entry = 0;
27675 uint32_t v_table_entry_n_bits = 0;
27676 uint64_t v_lmask = 0;
27677 uint64_t v_dmask = 0;
27678 uint32_t v_redir_top = 0;
27679 uint32_t v_redir_mask = 0;
27680 uint32_t v_length = 0;
27681 uint32_t v_dist_minus_1 = 0;
27682 uint32_t v_hlen = 0;
27683 uint32_t v_hdist = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027684 uint32_t v_hdist_adjustment = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100027685
27686 uint8_t* iop_a_dst = NULL;
27687 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27688 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27689 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27690 if (a_dst) {
27691 io0_a_dst = a_dst->data.ptr;
27692 io1_a_dst = io0_a_dst + a_dst->meta.wi;
27693 iop_a_dst = io1_a_dst;
27694 io2_a_dst = io0_a_dst + a_dst->data.len;
27695 if (a_dst->meta.closed) {
27696 io2_a_dst = iop_a_dst;
27697 }
27698 }
27699 const uint8_t* iop_a_src = NULL;
27700 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27701 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27702 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27703 if (a_src) {
27704 io0_a_src = a_src->data.ptr;
27705 io1_a_src = io0_a_src + a_src->meta.ri;
27706 iop_a_src = io1_a_src;
27707 io2_a_src = io0_a_src + a_src->meta.wi;
27708 }
27709
27710 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
27711 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27712 goto exit;
27713 }
27714 v_bits = ((uint64_t)(self->private_impl.f_bits));
27715 v_n_bits = self->private_impl.f_n_bits;
27716 v_lmask = ((((uint64_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
27717 v_dmask = ((((uint64_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027718 if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0)) {
27719 status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position);
27720 goto exit;
27721 }
27722 v_hdist_adjustment = ((uint32_t)(((self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0)) & 4294967295)));
Nigel Taoe360a532021-04-05 22:47:03 +100027723 label__loop__continue:;
27724 while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266) && (((uint64_t)(io2_a_src - iop_a_src)) >= 8)) {
27725 v_bits |= ((uint64_t)(wuffs_base__peek_u64le__no_bounds_check(iop_a_src) << (v_n_bits & 63)));
27726 iop_a_src += ((63 - (v_n_bits & 63)) >> 3);
27727 v_n_bits |= 56;
27728 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_lmask)];
27729 v_table_entry_n_bits = (v_table_entry & 15);
27730 v_bits >>= v_table_entry_n_bits;
27731 v_n_bits -= v_table_entry_n_bits;
27732 if ((v_table_entry >> 31) != 0) {
27733 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
27734 goto label__loop__continue;
27735 } else if ((v_table_entry >> 30) != 0) {
27736 } else if ((v_table_entry >> 29) != 0) {
27737 self->private_impl.f_end_of_block = true;
27738 goto label__loop__break;
27739 } else if ((v_table_entry >> 28) != 0) {
27740 v_redir_top = ((v_table_entry >> 8) & 65535);
27741 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
27742 v_table_entry = self->private_data.f_huffs[0][((v_redir_top + (((uint32_t)((v_bits & 4294967295))) & v_redir_mask)) & 1023)];
27743 v_table_entry_n_bits = (v_table_entry & 15);
27744 v_bits >>= v_table_entry_n_bits;
27745 v_n_bits -= v_table_entry_n_bits;
27746 if ((v_table_entry >> 31) != 0) {
27747 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
27748 goto label__loop__continue;
27749 } else if ((v_table_entry >> 30) != 0) {
27750 } else if ((v_table_entry >> 29) != 0) {
27751 self->private_impl.f_end_of_block = true;
27752 goto label__loop__break;
27753 } else if ((v_table_entry >> 28) != 0) {
27754 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27755 goto exit;
27756 } else if ((v_table_entry >> 27) != 0) {
27757 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27758 goto exit;
27759 } else {
27760 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27761 goto exit;
27762 }
27763 } else if ((v_table_entry >> 27) != 0) {
27764 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27765 goto exit;
27766 } else {
27767 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27768 goto exit;
27769 }
27770 v_length = (((v_table_entry >> 8) & 255) + 3);
27771 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
27772 if (v_table_entry_n_bits > 0) {
27773 v_length = (((v_length + 253 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 255) + 3);
27774 v_bits >>= v_table_entry_n_bits;
27775 v_n_bits -= v_table_entry_n_bits;
27776 }
27777 v_table_entry = self->private_data.f_huffs[1][(v_bits & v_dmask)];
27778 v_table_entry_n_bits = (v_table_entry & 15);
27779 v_bits >>= v_table_entry_n_bits;
27780 v_n_bits -= v_table_entry_n_bits;
27781 if ((v_table_entry >> 28) == 1) {
27782 v_redir_top = ((v_table_entry >> 8) & 65535);
27783 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
27784 v_table_entry = self->private_data.f_huffs[1][((v_redir_top + (((uint32_t)((v_bits & 4294967295))) & v_redir_mask)) & 1023)];
27785 v_table_entry_n_bits = (v_table_entry & 15);
27786 v_bits >>= v_table_entry_n_bits;
27787 v_n_bits -= v_table_entry_n_bits;
27788 }
27789 if ((v_table_entry >> 24) != 64) {
27790 if ((v_table_entry >> 24) == 8) {
27791 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
27792 goto exit;
27793 }
27794 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
27795 goto exit;
27796 }
27797 v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
27798 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
27799 v_dist_minus_1 = ((v_dist_minus_1 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 32767);
27800 v_bits >>= v_table_entry_n_bits;
27801 v_n_bits -= v_table_entry_n_bits;
27802 while (true) {
27803 if (((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) {
27804 v_hlen = 0;
27805 v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) - ((uint64_t)(iop_a_dst - io0_a_dst)))));
27806 if (v_length > v_hdist) {
27807 v_length -= v_hdist;
27808 v_hlen = v_hdist;
27809 } else {
27810 v_hlen = v_length;
27811 v_length = 0;
27812 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100027813 v_hdist += v_hdist_adjustment;
Nigel Taoe360a532021-04-05 22:47:03 +100027814 if (self->private_impl.f_history_index < v_hdist) {
27815 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance);
27816 goto exit;
27817 }
27818 v_hdist = (self->private_impl.f_history_index - v_hdist);
27819 wuffs_base__io_writer__limited_copy_u32_from_slice(
27820 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__slice_u8__subslice_i(wuffs_base__make_slice_u8(self->private_data.f_history, 33025), (v_hdist & 32767)));
27821 if (v_length == 0) {
27822 goto label__loop__continue;
27823 }
27824 if ((((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) || (((uint64_t)(v_length)) > ((uint64_t)(io2_a_dst - iop_a_dst))) || (((uint64_t)((v_length + 8))) > ((uint64_t)(io2_a_dst - iop_a_dst)))) {
27825 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance);
27826 goto exit;
27827 }
27828 }
27829 if ((v_dist_minus_1 + 1) >= 8) {
27830 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast(
27831 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
Nigel Tao5571bfe2021-06-24 22:44:29 +100027832 } else if ((v_dist_minus_1 + 1) == 1) {
27833 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast(
27834 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
Nigel Taoe360a532021-04-05 22:47:03 +100027835 } else {
27836 wuffs_base__io_writer__limited_copy_u32_from_history_fast(
27837 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
27838 }
27839 goto label__0__break;
27840 }
27841 label__0__break:;
27842 }
27843 label__loop__break:;
27844 if (v_n_bits > 63) {
27845 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27846 goto exit;
27847 }
27848 while (v_n_bits >= 8) {
27849 v_n_bits -= 8;
27850 if (iop_a_src > io1_a_src) {
27851 iop_a_src--;
27852 } else {
27853 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o);
27854 goto exit;
27855 }
27856 }
27857 self->private_impl.f_bits = ((uint32_t)((v_bits & ((((uint64_t)(1)) << v_n_bits) - 1))));
27858 self->private_impl.f_n_bits = v_n_bits;
27859 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
27860 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27861 goto exit;
27862 }
27863 goto exit;
27864 exit:
27865 if (a_dst) {
27866 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
27867 }
27868 if (a_src) {
27869 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
27870 }
27871
27872 return status;
27873}
27874
27875// -------- func deflate.decoder.decode_huffman_slow
27876
27877static wuffs_base__status
27878wuffs_deflate__decoder__decode_huffman_slow(
27879 wuffs_deflate__decoder* self,
27880 wuffs_base__io_buffer* a_dst,
27881 wuffs_base__io_buffer* a_src) {
27882 wuffs_base__status status = wuffs_base__make_status(NULL);
27883
27884 uint32_t v_bits = 0;
27885 uint32_t v_n_bits = 0;
27886 uint32_t v_table_entry = 0;
27887 uint32_t v_table_entry_n_bits = 0;
27888 uint32_t v_lmask = 0;
27889 uint32_t v_dmask = 0;
27890 uint32_t v_b0 = 0;
27891 uint32_t v_redir_top = 0;
27892 uint32_t v_redir_mask = 0;
27893 uint32_t v_b1 = 0;
27894 uint32_t v_length = 0;
27895 uint32_t v_b2 = 0;
27896 uint32_t v_b3 = 0;
27897 uint32_t v_b4 = 0;
27898 uint32_t v_dist_minus_1 = 0;
27899 uint32_t v_b5 = 0;
27900 uint32_t v_n_copied = 0;
27901 uint32_t v_hlen = 0;
27902 uint32_t v_hdist = 0;
27903
27904 uint8_t* iop_a_dst = NULL;
27905 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27906 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27907 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27908 if (a_dst) {
27909 io0_a_dst = a_dst->data.ptr;
27910 io1_a_dst = io0_a_dst + a_dst->meta.wi;
27911 iop_a_dst = io1_a_dst;
27912 io2_a_dst = io0_a_dst + a_dst->data.len;
27913 if (a_dst->meta.closed) {
27914 io2_a_dst = iop_a_dst;
27915 }
27916 }
27917 const uint8_t* iop_a_src = NULL;
27918 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27919 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27920 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
27921 if (a_src) {
27922 io0_a_src = a_src->data.ptr;
27923 io1_a_src = io0_a_src + a_src->meta.ri;
27924 iop_a_src = io1_a_src;
27925 io2_a_src = io0_a_src + a_src->meta.wi;
27926 }
27927
27928 uint32_t coro_susp_point = self->private_impl.p_decode_huffman_slow[0];
27929 if (coro_susp_point) {
27930 v_bits = self->private_data.s_decode_huffman_slow[0].v_bits;
27931 v_n_bits = self->private_data.s_decode_huffman_slow[0].v_n_bits;
27932 v_table_entry = self->private_data.s_decode_huffman_slow[0].v_table_entry;
27933 v_table_entry_n_bits = self->private_data.s_decode_huffman_slow[0].v_table_entry_n_bits;
27934 v_lmask = self->private_data.s_decode_huffman_slow[0].v_lmask;
27935 v_dmask = self->private_data.s_decode_huffman_slow[0].v_dmask;
27936 v_redir_top = self->private_data.s_decode_huffman_slow[0].v_redir_top;
27937 v_redir_mask = self->private_data.s_decode_huffman_slow[0].v_redir_mask;
27938 v_length = self->private_data.s_decode_huffman_slow[0].v_length;
27939 v_dist_minus_1 = self->private_data.s_decode_huffman_slow[0].v_dist_minus_1;
27940 v_hlen = self->private_data.s_decode_huffman_slow[0].v_hlen;
27941 v_hdist = self->private_data.s_decode_huffman_slow[0].v_hdist;
27942 }
27943 switch (coro_susp_point) {
27944 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
27945
27946 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
27947 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
27948 goto exit;
27949 }
27950 v_bits = self->private_impl.f_bits;
27951 v_n_bits = self->private_impl.f_n_bits;
27952 v_lmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
27953 v_dmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
27954 label__loop__continue:;
27955 while ( ! (self->private_impl.p_decode_huffman_slow[0] != 0)) {
27956 while (true) {
27957 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_lmask)];
27958 v_table_entry_n_bits = (v_table_entry & 15);
27959 if (v_n_bits >= v_table_entry_n_bits) {
27960 v_bits >>= v_table_entry_n_bits;
27961 v_n_bits -= v_table_entry_n_bits;
27962 goto label__0__break;
27963 }
27964 {
27965 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
27966 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
27967 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
27968 goto suspend;
27969 }
27970 uint32_t t_0 = *iop_a_src++;
27971 v_b0 = t_0;
27972 }
27973 v_bits |= (v_b0 << v_n_bits);
27974 v_n_bits += 8;
27975 }
27976 label__0__break:;
27977 if ((v_table_entry >> 31) != 0) {
27978 self->private_data.s_decode_huffman_slow[0].scratch = ((uint8_t)(((v_table_entry >> 8) & 255)));
27979 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
27980 if (iop_a_dst == io2_a_dst) {
27981 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
27982 goto suspend;
27983 }
27984 *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_huffman_slow[0].scratch));
27985 goto label__loop__continue;
27986 } else if ((v_table_entry >> 30) != 0) {
27987 } else if ((v_table_entry >> 29) != 0) {
27988 self->private_impl.f_end_of_block = true;
27989 goto label__loop__break;
27990 } else if ((v_table_entry >> 28) != 0) {
27991 v_redir_top = ((v_table_entry >> 8) & 65535);
27992 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
27993 while (true) {
27994 v_table_entry = self->private_data.f_huffs[0][((v_redir_top + (v_bits & v_redir_mask)) & 1023)];
27995 v_table_entry_n_bits = (v_table_entry & 15);
27996 if (v_n_bits >= v_table_entry_n_bits) {
27997 v_bits >>= v_table_entry_n_bits;
27998 v_n_bits -= v_table_entry_n_bits;
27999 goto label__1__break;
28000 }
28001 {
28002 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
28003 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
28004 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
28005 goto suspend;
28006 }
28007 uint32_t t_1 = *iop_a_src++;
28008 v_b1 = t_1;
28009 }
28010 v_bits |= (v_b1 << v_n_bits);
28011 v_n_bits += 8;
28012 }
28013 label__1__break:;
28014 if ((v_table_entry >> 31) != 0) {
28015 self->private_data.s_decode_huffman_slow[0].scratch = ((uint8_t)(((v_table_entry >> 8) & 255)));
28016 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
28017 if (iop_a_dst == io2_a_dst) {
28018 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
28019 goto suspend;
28020 }
28021 *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_huffman_slow[0].scratch));
28022 goto label__loop__continue;
28023 } else if ((v_table_entry >> 30) != 0) {
28024 } else if ((v_table_entry >> 29) != 0) {
28025 self->private_impl.f_end_of_block = true;
28026 goto label__loop__break;
28027 } else if ((v_table_entry >> 28) != 0) {
28028 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
28029 goto exit;
28030 } else if ((v_table_entry >> 27) != 0) {
28031 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
28032 goto exit;
28033 } else {
28034 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
28035 goto exit;
28036 }
28037 } else if ((v_table_entry >> 27) != 0) {
28038 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
28039 goto exit;
28040 } else {
28041 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
28042 goto exit;
28043 }
28044 v_length = (((v_table_entry >> 8) & 255) + 3);
28045 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
28046 if (v_table_entry_n_bits > 0) {
28047 while (v_n_bits < v_table_entry_n_bits) {
28048 {
28049 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
28050 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
28051 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
28052 goto suspend;
28053 }
28054 uint32_t t_2 = *iop_a_src++;
28055 v_b2 = t_2;
28056 }
28057 v_bits |= (v_b2 << v_n_bits);
28058 v_n_bits += 8;
28059 }
28060 v_length = (((v_length + 253 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 255) + 3);
28061 v_bits >>= v_table_entry_n_bits;
28062 v_n_bits -= v_table_entry_n_bits;
28063 }
28064 while (true) {
28065 v_table_entry = self->private_data.f_huffs[1][(v_bits & v_dmask)];
28066 v_table_entry_n_bits = (v_table_entry & 15);
28067 if (v_n_bits >= v_table_entry_n_bits) {
28068 v_bits >>= v_table_entry_n_bits;
28069 v_n_bits -= v_table_entry_n_bits;
28070 goto label__2__break;
28071 }
28072 {
28073 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
28074 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
28075 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
28076 goto suspend;
28077 }
28078 uint32_t t_3 = *iop_a_src++;
28079 v_b3 = t_3;
28080 }
28081 v_bits |= (v_b3 << v_n_bits);
28082 v_n_bits += 8;
28083 }
28084 label__2__break:;
28085 if ((v_table_entry >> 28) == 1) {
28086 v_redir_top = ((v_table_entry >> 8) & 65535);
28087 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
28088 while (true) {
28089 v_table_entry = self->private_data.f_huffs[1][((v_redir_top + (v_bits & v_redir_mask)) & 1023)];
28090 v_table_entry_n_bits = (v_table_entry & 15);
28091 if (v_n_bits >= v_table_entry_n_bits) {
28092 v_bits >>= v_table_entry_n_bits;
28093 v_n_bits -= v_table_entry_n_bits;
28094 goto label__3__break;
28095 }
28096 {
28097 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
28098 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
28099 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
28100 goto suspend;
28101 }
28102 uint32_t t_4 = *iop_a_src++;
28103 v_b4 = t_4;
28104 }
28105 v_bits |= (v_b4 << v_n_bits);
28106 v_n_bits += 8;
28107 }
28108 label__3__break:;
28109 }
28110 if ((v_table_entry >> 24) != 64) {
28111 if ((v_table_entry >> 24) == 8) {
28112 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
28113 goto exit;
28114 }
28115 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
28116 goto exit;
28117 }
28118 v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
28119 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
28120 if (v_table_entry_n_bits > 0) {
28121 while (v_n_bits < v_table_entry_n_bits) {
28122 {
28123 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
28124 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
28125 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
28126 goto suspend;
28127 }
28128 uint32_t t_5 = *iop_a_src++;
28129 v_b5 = t_5;
28130 }
28131 v_bits |= (v_b5 << v_n_bits);
28132 v_n_bits += 8;
28133 }
28134 v_dist_minus_1 = ((v_dist_minus_1 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 32767);
28135 v_bits >>= v_table_entry_n_bits;
28136 v_n_bits -= v_table_entry_n_bits;
28137 }
28138 while (true) {
28139 if (((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) {
28140 v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) - ((uint64_t)(iop_a_dst - io0_a_dst)))));
28141 if (v_length > v_hdist) {
28142 v_length -= v_hdist;
28143 v_hlen = v_hdist;
28144 } else {
28145 v_hlen = v_length;
28146 v_length = 0;
28147 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100028148 v_hdist += ((uint32_t)((((uint64_t)(self->private_impl.f_transformed_history_count - (a_dst ? a_dst->meta.pos : 0))) & 4294967295)));
Nigel Taoe360a532021-04-05 22:47:03 +100028149 if (self->private_impl.f_history_index < v_hdist) {
28150 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance);
28151 goto exit;
28152 }
28153 v_hdist = (self->private_impl.f_history_index - v_hdist);
28154 while (true) {
28155 v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_slice(
28156 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__slice_u8__subslice_i(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), (v_hdist & 32767)));
28157 if (v_hlen <= v_n_copied) {
28158 v_hlen = 0;
28159 goto label__4__break;
28160 }
28161 if (v_n_copied > 0) {
28162 v_hlen -= v_n_copied;
28163 v_hdist = (((uint32_t)(v_hdist + v_n_copied)) & 32767);
28164 if (v_hdist == 0) {
28165 goto label__4__break;
28166 }
28167 }
28168 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
28169 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
28170 }
28171 label__4__break:;
28172 if (v_hlen > 0) {
28173 while (true) {
28174 v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_slice(
28175 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__slice_u8__subslice_i(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), (v_hdist & 32767)));
28176 if (v_hlen <= v_n_copied) {
28177 v_hlen = 0;
28178 goto label__5__break;
28179 }
28180 v_hlen -= v_n_copied;
28181 v_hdist += v_n_copied;
28182 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
28183 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
28184 }
28185 label__5__break:;
28186 }
28187 if (v_length == 0) {
28188 goto label__loop__continue;
28189 }
28190 }
28191 v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_history(
28192 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
28193 if (v_length <= v_n_copied) {
28194 v_length = 0;
28195 goto label__6__break;
28196 }
28197 v_length -= v_n_copied;
28198 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
28199 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
28200 }
28201 label__6__break:;
28202 }
28203 label__loop__break:;
28204 self->private_impl.f_bits = v_bits;
28205 self->private_impl.f_n_bits = v_n_bits;
28206 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
28207 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
28208 goto exit;
28209 }
28210
Nigel Taoe360a532021-04-05 22:47:03 +100028211 ok:
28212 self->private_impl.p_decode_huffman_slow[0] = 0;
28213 goto exit;
28214 }
28215
28216 goto suspend;
28217 suspend:
28218 self->private_impl.p_decode_huffman_slow[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
28219 self->private_data.s_decode_huffman_slow[0].v_bits = v_bits;
28220 self->private_data.s_decode_huffman_slow[0].v_n_bits = v_n_bits;
28221 self->private_data.s_decode_huffman_slow[0].v_table_entry = v_table_entry;
28222 self->private_data.s_decode_huffman_slow[0].v_table_entry_n_bits = v_table_entry_n_bits;
28223 self->private_data.s_decode_huffman_slow[0].v_lmask = v_lmask;
28224 self->private_data.s_decode_huffman_slow[0].v_dmask = v_dmask;
28225 self->private_data.s_decode_huffman_slow[0].v_redir_top = v_redir_top;
28226 self->private_data.s_decode_huffman_slow[0].v_redir_mask = v_redir_mask;
28227 self->private_data.s_decode_huffman_slow[0].v_length = v_length;
28228 self->private_data.s_decode_huffman_slow[0].v_dist_minus_1 = v_dist_minus_1;
28229 self->private_data.s_decode_huffman_slow[0].v_hlen = v_hlen;
28230 self->private_data.s_decode_huffman_slow[0].v_hdist = v_hdist;
28231
28232 goto exit;
28233 exit:
28234 if (a_dst) {
28235 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
28236 }
28237 if (a_src) {
28238 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
28239 }
28240
28241 return status;
28242}
28243
28244#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE)
28245
28246#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW)
28247
28248// ---------------- Status Codes Implementations
28249
28250const char wuffs_lzw__error__bad_code[] = "#lzw: bad code";
28251const char wuffs_lzw__error__internal_error_inconsistent_i_o[] = "#lzw: internal error: inconsistent I/O";
28252
28253// ---------------- Private Consts
28254
28255// ---------------- Private Initializer Prototypes
28256
28257// ---------------- Private Function Prototypes
28258
28259static wuffs_base__empty_struct
28260wuffs_lzw__decoder__read_from(
28261 wuffs_lzw__decoder* self,
28262 wuffs_base__io_buffer* a_src);
28263
28264static wuffs_base__status
28265wuffs_lzw__decoder__write_to(
28266 wuffs_lzw__decoder* self,
28267 wuffs_base__io_buffer* a_dst);
28268
28269// ---------------- VTables
28270
28271const wuffs_base__io_transformer__func_ptrs
28272wuffs_lzw__decoder__func_ptrs_for__wuffs_base__io_transformer = {
28273 (wuffs_base__empty_struct(*)(void*,
28274 uint32_t,
28275 bool))(&wuffs_lzw__decoder__set_quirk_enabled),
28276 (wuffs_base__status(*)(void*,
28277 wuffs_base__io_buffer*,
28278 wuffs_base__io_buffer*,
28279 wuffs_base__slice_u8))(&wuffs_lzw__decoder__transform_io),
28280 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_lzw__decoder__workbuf_len),
28281};
28282
28283// ---------------- Initializer Implementations
28284
28285wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
28286wuffs_lzw__decoder__initialize(
28287 wuffs_lzw__decoder* self,
28288 size_t sizeof_star_self,
28289 uint64_t wuffs_version,
28290 uint32_t options){
28291 if (!self) {
28292 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
28293 }
28294 if (sizeof(*self) != sizeof_star_self) {
28295 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
28296 }
28297 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
28298 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
28299 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
28300 }
28301
28302 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
28303 // The whole point of this if-check is to detect an uninitialized *self.
28304 // We disable the warning on GCC. Clang-5.0 does not have this warning.
28305#if !defined(__clang__) && defined(__GNUC__)
28306#pragma GCC diagnostic push
28307#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
28308#endif
28309 if (self->private_impl.magic != 0) {
28310 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
28311 }
28312#if !defined(__clang__) && defined(__GNUC__)
28313#pragma GCC diagnostic pop
28314#endif
28315 } else {
28316 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
28317 memset(self, 0, sizeof(*self));
28318 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
28319 } else {
28320 memset(&(self->private_impl), 0, sizeof(self->private_impl));
28321 }
28322 }
28323
28324 self->private_impl.magic = WUFFS_BASE__MAGIC;
28325 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
28326 wuffs_base__io_transformer__vtable_name;
28327 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
28328 (const void*)(&wuffs_lzw__decoder__func_ptrs_for__wuffs_base__io_transformer);
28329 return wuffs_base__make_status(NULL);
28330}
28331
28332wuffs_lzw__decoder*
28333wuffs_lzw__decoder__alloc() {
28334 wuffs_lzw__decoder* x =
28335 (wuffs_lzw__decoder*)(calloc(sizeof(wuffs_lzw__decoder), 1));
28336 if (!x) {
28337 return NULL;
28338 }
28339 if (wuffs_lzw__decoder__initialize(
28340 x, sizeof(wuffs_lzw__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
28341 free(x);
28342 return NULL;
28343 }
28344 return x;
28345}
28346
28347size_t
28348sizeof__wuffs_lzw__decoder() {
28349 return sizeof(wuffs_lzw__decoder);
28350}
28351
28352// ---------------- Function Implementations
28353
28354// -------- func lzw.decoder.set_quirk_enabled
28355
28356WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
28357wuffs_lzw__decoder__set_quirk_enabled(
28358 wuffs_lzw__decoder* self,
28359 uint32_t a_quirk,
28360 bool a_enabled) {
28361 return wuffs_base__make_empty_struct();
28362}
28363
28364// -------- func lzw.decoder.set_literal_width
28365
28366WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
28367wuffs_lzw__decoder__set_literal_width(
28368 wuffs_lzw__decoder* self,
28369 uint32_t a_lw) {
28370 if (!self) {
28371 return wuffs_base__make_empty_struct();
28372 }
28373 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
28374 return wuffs_base__make_empty_struct();
28375 }
28376 if (a_lw > 8) {
28377 self->private_impl.magic = WUFFS_BASE__DISABLED;
28378 return wuffs_base__make_empty_struct();
28379 }
28380
28381 self->private_impl.f_set_literal_width_arg = (a_lw + 1);
28382 return wuffs_base__make_empty_struct();
28383}
28384
28385// -------- func lzw.decoder.workbuf_len
28386
28387WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
28388wuffs_lzw__decoder__workbuf_len(
28389 const wuffs_lzw__decoder* self) {
28390 if (!self) {
28391 return wuffs_base__utility__empty_range_ii_u64();
28392 }
28393 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
28394 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
28395 return wuffs_base__utility__empty_range_ii_u64();
28396 }
28397
28398 return wuffs_base__utility__make_range_ii_u64(0, 0);
28399}
28400
28401// -------- func lzw.decoder.transform_io
28402
28403WUFFS_BASE__MAYBE_STATIC wuffs_base__status
28404wuffs_lzw__decoder__transform_io(
28405 wuffs_lzw__decoder* self,
28406 wuffs_base__io_buffer* a_dst,
28407 wuffs_base__io_buffer* a_src,
28408 wuffs_base__slice_u8 a_workbuf) {
28409 if (!self) {
28410 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
28411 }
28412 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
28413 return wuffs_base__make_status(
28414 (self->private_impl.magic == WUFFS_BASE__DISABLED)
28415 ? wuffs_base__error__disabled_by_previous_error
28416 : wuffs_base__error__initialize_not_called);
28417 }
28418 if (!a_dst || !a_src) {
28419 self->private_impl.magic = WUFFS_BASE__DISABLED;
28420 return wuffs_base__make_status(wuffs_base__error__bad_argument);
28421 }
28422 if ((self->private_impl.active_coroutine != 0) &&
28423 (self->private_impl.active_coroutine != 1)) {
28424 self->private_impl.magic = WUFFS_BASE__DISABLED;
28425 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
28426 }
28427 self->private_impl.active_coroutine = 0;
28428 wuffs_base__status status = wuffs_base__make_status(NULL);
28429
28430 uint32_t v_i = 0;
28431
28432 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
28433 switch (coro_susp_point) {
28434 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
28435
28436 self->private_impl.f_literal_width = 8;
28437 if (self->private_impl.f_set_literal_width_arg > 0) {
28438 self->private_impl.f_literal_width = (self->private_impl.f_set_literal_width_arg - 1);
28439 }
28440 self->private_impl.f_clear_code = (((uint32_t)(1)) << self->private_impl.f_literal_width);
28441 self->private_impl.f_end_code = (self->private_impl.f_clear_code + 1);
28442 self->private_impl.f_save_code = self->private_impl.f_end_code;
28443 self->private_impl.f_prev_code = self->private_impl.f_end_code;
28444 self->private_impl.f_width = (self->private_impl.f_literal_width + 1);
28445 self->private_impl.f_bits = 0;
28446 self->private_impl.f_n_bits = 0;
28447 self->private_impl.f_output_ri = 0;
28448 self->private_impl.f_output_wi = 0;
28449 v_i = 0;
28450 while (v_i < self->private_impl.f_clear_code) {
28451 self->private_data.f_lm1s[v_i] = 0;
28452 self->private_data.f_suffixes[v_i][0] = ((uint8_t)(v_i));
28453 v_i += 1;
28454 }
28455 label__0__continue:;
28456 while (true) {
28457 wuffs_lzw__decoder__read_from(self, a_src);
28458 if (self->private_impl.f_output_wi > 0) {
28459 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
28460 status = wuffs_lzw__decoder__write_to(self, a_dst);
28461 if (status.repr) {
28462 goto suspend;
28463 }
28464 }
28465 if (self->private_impl.f_read_from_return_value == 0) {
28466 goto label__0__break;
28467 } else if (self->private_impl.f_read_from_return_value == 1) {
28468 goto label__0__continue;
28469 } else if (self->private_impl.f_read_from_return_value == 2) {
28470 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
28471 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
28472 } else if (self->private_impl.f_read_from_return_value == 3) {
28473 status = wuffs_base__make_status(wuffs_lzw__error__bad_code);
28474 goto exit;
28475 } else {
28476 status = wuffs_base__make_status(wuffs_lzw__error__internal_error_inconsistent_i_o);
28477 goto exit;
28478 }
28479 }
28480 label__0__break:;
28481
Nigel Taoe360a532021-04-05 22:47:03 +100028482 ok:
28483 self->private_impl.p_transform_io[0] = 0;
28484 goto exit;
28485 }
28486
28487 goto suspend;
28488 suspend:
28489 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
28490 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
28491
28492 goto exit;
28493 exit:
28494 if (wuffs_base__status__is_error(&status)) {
28495 self->private_impl.magic = WUFFS_BASE__DISABLED;
28496 }
28497 return status;
28498}
28499
28500// -------- func lzw.decoder.read_from
28501
28502static wuffs_base__empty_struct
28503wuffs_lzw__decoder__read_from(
28504 wuffs_lzw__decoder* self,
28505 wuffs_base__io_buffer* a_src) {
28506 uint32_t v_clear_code = 0;
28507 uint32_t v_end_code = 0;
28508 uint32_t v_save_code = 0;
28509 uint32_t v_prev_code = 0;
28510 uint32_t v_width = 0;
28511 uint32_t v_bits = 0;
28512 uint32_t v_n_bits = 0;
28513 uint32_t v_output_wi = 0;
28514 uint32_t v_code = 0;
28515 uint32_t v_c = 0;
28516 uint32_t v_o = 0;
28517 uint32_t v_steps = 0;
28518 uint8_t v_first_byte = 0;
28519 uint16_t v_lm1_b = 0;
28520 uint16_t v_lm1_a = 0;
28521
28522 const uint8_t* iop_a_src = NULL;
28523 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28524 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28525 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28526 if (a_src) {
28527 io0_a_src = a_src->data.ptr;
28528 io1_a_src = io0_a_src + a_src->meta.ri;
28529 iop_a_src = io1_a_src;
28530 io2_a_src = io0_a_src + a_src->meta.wi;
28531 }
28532
28533 v_clear_code = self->private_impl.f_clear_code;
28534 v_end_code = self->private_impl.f_end_code;
28535 v_save_code = self->private_impl.f_save_code;
28536 v_prev_code = self->private_impl.f_prev_code;
28537 v_width = self->private_impl.f_width;
28538 v_bits = self->private_impl.f_bits;
28539 v_n_bits = self->private_impl.f_n_bits;
28540 v_output_wi = self->private_impl.f_output_wi;
28541 while (true) {
28542 if (v_n_bits < v_width) {
28543 if (((uint64_t)(io2_a_src - iop_a_src)) >= 4) {
28544 v_bits |= ((uint32_t)(wuffs_base__peek_u32le__no_bounds_check(iop_a_src) << v_n_bits));
28545 iop_a_src += ((31 - v_n_bits) >> 3);
28546 v_n_bits |= 24;
28547 } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
28548 self->private_impl.f_read_from_return_value = 2;
28549 goto label__0__break;
28550 } else {
28551 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
28552 iop_a_src += 1;
28553 v_n_bits += 8;
28554 if (v_n_bits >= v_width) {
28555 } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
28556 self->private_impl.f_read_from_return_value = 2;
28557 goto label__0__break;
28558 } else {
28559 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
28560 iop_a_src += 1;
28561 v_n_bits += 8;
28562 if (v_n_bits < v_width) {
28563 self->private_impl.f_read_from_return_value = 4;
28564 goto label__0__break;
28565 }
28566 }
28567 }
28568 }
28569 v_code = ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_width));
28570 v_bits >>= v_width;
28571 v_n_bits -= v_width;
28572 if (v_code < v_clear_code) {
28573 self->private_data.f_output[v_output_wi] = ((uint8_t)(v_code));
28574 v_output_wi = ((v_output_wi + 1) & 8191);
28575 if (v_save_code <= 4095) {
28576 v_lm1_a = (((uint16_t)(self->private_data.f_lm1s[v_prev_code] + 1)) & 4095);
28577 self->private_data.f_lm1s[v_save_code] = v_lm1_a;
28578 if ((v_lm1_a % 8) != 0) {
28579 self->private_impl.f_prefixes[v_save_code] = self->private_impl.f_prefixes[v_prev_code];
28580 memcpy(self->private_data.f_suffixes[v_save_code],self->private_data.f_suffixes[v_prev_code], sizeof(self->private_data.f_suffixes[v_save_code]));
28581 self->private_data.f_suffixes[v_save_code][(v_lm1_a % 8)] = ((uint8_t)(v_code));
28582 } else {
28583 self->private_impl.f_prefixes[v_save_code] = ((uint16_t)(v_prev_code));
28584 self->private_data.f_suffixes[v_save_code][0] = ((uint8_t)(v_code));
28585 }
28586 v_save_code += 1;
28587 if (v_width < 12) {
28588 v_width += (1 & (v_save_code >> v_width));
28589 }
28590 v_prev_code = v_code;
28591 }
28592 } else if (v_code <= v_end_code) {
28593 if (v_code == v_end_code) {
28594 self->private_impl.f_read_from_return_value = 0;
28595 goto label__0__break;
28596 }
28597 v_save_code = v_end_code;
28598 v_prev_code = v_end_code;
28599 v_width = (self->private_impl.f_literal_width + 1);
28600 } else if (v_code <= v_save_code) {
28601 v_c = v_code;
28602 if (v_code == v_save_code) {
28603 v_c = v_prev_code;
28604 }
28605 v_o = ((v_output_wi + (((uint32_t)(self->private_data.f_lm1s[v_c])) & 4294967288)) & 8191);
28606 v_output_wi = ((v_output_wi + 1 + ((uint32_t)(self->private_data.f_lm1s[v_c]))) & 8191);
28607 v_steps = (((uint32_t)(self->private_data.f_lm1s[v_c])) >> 3);
28608 while (true) {
28609 memcpy((self->private_data.f_output)+(v_o), (self->private_data.f_suffixes[v_c]), 8);
28610 if (v_steps <= 0) {
28611 goto label__1__break;
28612 }
28613 v_steps -= 1;
28614 v_o = (((uint32_t)(v_o - 8)) & 8191);
28615 v_c = ((uint32_t)(self->private_impl.f_prefixes[v_c]));
28616 }
28617 label__1__break:;
28618 v_first_byte = self->private_data.f_suffixes[v_c][0];
28619 if (v_code == v_save_code) {
28620 self->private_data.f_output[v_output_wi] = v_first_byte;
28621 v_output_wi = ((v_output_wi + 1) & 8191);
28622 }
28623 if (v_save_code <= 4095) {
28624 v_lm1_b = (((uint16_t)(self->private_data.f_lm1s[v_prev_code] + 1)) & 4095);
28625 self->private_data.f_lm1s[v_save_code] = v_lm1_b;
28626 if ((v_lm1_b % 8) != 0) {
28627 self->private_impl.f_prefixes[v_save_code] = self->private_impl.f_prefixes[v_prev_code];
28628 memcpy(self->private_data.f_suffixes[v_save_code],self->private_data.f_suffixes[v_prev_code], sizeof(self->private_data.f_suffixes[v_save_code]));
28629 self->private_data.f_suffixes[v_save_code][(v_lm1_b % 8)] = v_first_byte;
28630 } else {
28631 self->private_impl.f_prefixes[v_save_code] = ((uint16_t)(v_prev_code));
28632 self->private_data.f_suffixes[v_save_code][0] = ((uint8_t)(v_first_byte));
28633 }
28634 v_save_code += 1;
28635 if (v_width < 12) {
28636 v_width += (1 & (v_save_code >> v_width));
28637 }
28638 v_prev_code = v_code;
28639 }
28640 } else {
28641 self->private_impl.f_read_from_return_value = 3;
28642 goto label__0__break;
28643 }
28644 if (v_output_wi > 4095) {
28645 self->private_impl.f_read_from_return_value = 1;
28646 goto label__0__break;
28647 }
28648 }
28649 label__0__break:;
28650 if (self->private_impl.f_read_from_return_value != 2) {
28651 while (v_n_bits >= 8) {
28652 v_n_bits -= 8;
28653 if (iop_a_src > io1_a_src) {
28654 iop_a_src--;
28655 } else {
28656 self->private_impl.f_read_from_return_value = 4;
28657 goto label__2__break;
28658 }
28659 }
28660 label__2__break:;
28661 }
28662 self->private_impl.f_save_code = v_save_code;
28663 self->private_impl.f_prev_code = v_prev_code;
28664 self->private_impl.f_width = v_width;
28665 self->private_impl.f_bits = v_bits;
28666 self->private_impl.f_n_bits = v_n_bits;
28667 self->private_impl.f_output_wi = v_output_wi;
28668 if (a_src) {
28669 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
28670 }
28671
28672 return wuffs_base__make_empty_struct();
28673}
28674
28675// -------- func lzw.decoder.write_to
28676
28677static wuffs_base__status
28678wuffs_lzw__decoder__write_to(
28679 wuffs_lzw__decoder* self,
28680 wuffs_base__io_buffer* a_dst) {
28681 wuffs_base__status status = wuffs_base__make_status(NULL);
28682
28683 wuffs_base__slice_u8 v_s = {0};
28684 uint64_t v_n = 0;
28685
28686 uint8_t* iop_a_dst = NULL;
28687 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28688 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28689 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28690 if (a_dst) {
28691 io0_a_dst = a_dst->data.ptr;
28692 io1_a_dst = io0_a_dst + a_dst->meta.wi;
28693 iop_a_dst = io1_a_dst;
28694 io2_a_dst = io0_a_dst + a_dst->data.len;
28695 if (a_dst->meta.closed) {
28696 io2_a_dst = iop_a_dst;
28697 }
28698 }
28699
28700 uint32_t coro_susp_point = self->private_impl.p_write_to[0];
28701 switch (coro_susp_point) {
28702 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
28703
28704 while (self->private_impl.f_output_wi > 0) {
28705 if (self->private_impl.f_output_ri > self->private_impl.f_output_wi) {
28706 status = wuffs_base__make_status(wuffs_lzw__error__internal_error_inconsistent_i_o);
28707 goto exit;
28708 }
28709 v_s = wuffs_base__slice_u8__subslice_ij(wuffs_base__make_slice_u8(self->private_data.f_output,
28710 8199),
28711 self->private_impl.f_output_ri,
28712 self->private_impl.f_output_wi);
28713 v_n = wuffs_base__io_writer__copy_from_slice(&iop_a_dst, io2_a_dst,v_s);
28714 if (v_n == ((uint64_t)(v_s.len))) {
28715 self->private_impl.f_output_ri = 0;
28716 self->private_impl.f_output_wi = 0;
28717 status = wuffs_base__make_status(NULL);
28718 goto ok;
28719 }
28720 self->private_impl.f_output_ri = (((uint32_t)(self->private_impl.f_output_ri + ((uint32_t)((v_n & 4294967295))))) & 8191);
28721 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
28722 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
28723 }
28724
Nigel Taoe360a532021-04-05 22:47:03 +100028725 ok:
28726 self->private_impl.p_write_to[0] = 0;
28727 goto exit;
28728 }
28729
28730 goto suspend;
28731 suspend:
28732 self->private_impl.p_write_to[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
28733
28734 goto exit;
28735 exit:
28736 if (a_dst) {
28737 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
28738 }
28739
28740 return status;
28741}
28742
28743// -------- func lzw.decoder.flush
28744
28745WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8
28746wuffs_lzw__decoder__flush(
28747 wuffs_lzw__decoder* self) {
28748 if (!self) {
28749 return wuffs_base__make_slice_u8(NULL, 0);
28750 }
28751 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
28752 return wuffs_base__make_slice_u8(NULL, 0);
28753 }
28754
28755 wuffs_base__slice_u8 v_s = {0};
28756
28757 if (self->private_impl.f_output_ri <= self->private_impl.f_output_wi) {
28758 v_s = wuffs_base__slice_u8__subslice_ij(wuffs_base__make_slice_u8(self->private_data.f_output,
28759 8199),
28760 self->private_impl.f_output_ri,
28761 self->private_impl.f_output_wi);
28762 }
28763 self->private_impl.f_output_ri = 0;
28764 self->private_impl.f_output_wi = 0;
28765 return v_s;
28766}
28767
28768#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW)
28769
28770#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF)
28771
28772// ---------------- Status Codes Implementations
28773
28774const char wuffs_gif__error__bad_extension_label[] = "#gif: bad extension label";
28775const char wuffs_gif__error__bad_frame_size[] = "#gif: bad frame size";
28776const char wuffs_gif__error__bad_graphic_control[] = "#gif: bad graphic control";
28777const char wuffs_gif__error__bad_header[] = "#gif: bad header";
28778const char wuffs_gif__error__bad_literal_width[] = "#gif: bad literal width";
28779const char wuffs_gif__error__bad_palette[] = "#gif: bad palette";
28780const char wuffs_gif__error__internal_error_inconsistent_ri_wi[] = "#gif: internal error: inconsistent ri/wi";
28781
28782// ---------------- Private Consts
28783
28784static const uint32_t
28785WUFFS_GIF__INTERLACE_START[5] WUFFS_BASE__POTENTIALLY_UNUSED = {
28786 4294967295, 1, 2, 4, 0,
28787};
28788
28789static const uint8_t
28790WUFFS_GIF__INTERLACE_DELTA[5] WUFFS_BASE__POTENTIALLY_UNUSED = {
28791 1, 2, 4, 8, 8,
28792};
28793
28794static const uint8_t
28795WUFFS_GIF__INTERLACE_COUNT[5] WUFFS_BASE__POTENTIALLY_UNUSED = {
28796 0, 1, 2, 4, 8,
28797};
28798
28799static const uint8_t
28800WUFFS_GIF__ANIMEXTS1DOT0[11] WUFFS_BASE__POTENTIALLY_UNUSED = {
28801 65, 78, 73, 77, 69, 88, 84, 83,
28802 49, 46, 48,
28803};
28804
28805static const uint8_t
28806WUFFS_GIF__NETSCAPE2DOT0[11] WUFFS_BASE__POTENTIALLY_UNUSED = {
28807 78, 69, 84, 83, 67, 65, 80, 69,
28808 50, 46, 48,
28809};
28810
28811static const uint8_t
28812WUFFS_GIF__ICCRGBG1012[11] WUFFS_BASE__POTENTIALLY_UNUSED = {
28813 73, 67, 67, 82, 71, 66, 71, 49,
28814 48, 49, 50,
28815};
28816
28817static const uint8_t
28818WUFFS_GIF__XMPDATAXMP[11] WUFFS_BASE__POTENTIALLY_UNUSED = {
28819 88, 77, 80, 32, 68, 97, 116, 97,
28820 88, 77, 80,
28821};
28822
28823#define WUFFS_GIF__QUIRKS_BASE 1041635328
28824
28825#define WUFFS_GIF__QUIRKS_COUNT 7
28826
28827// ---------------- Private Initializer Prototypes
28828
28829// ---------------- Private Function Prototypes
28830
28831static wuffs_base__status
28832wuffs_gif__decoder__skip_frame(
28833 wuffs_gif__decoder* self,
28834 wuffs_base__io_buffer* a_src);
28835
28836static wuffs_base__empty_struct
28837wuffs_gif__decoder__reset_gc(
28838 wuffs_gif__decoder* self);
28839
28840static wuffs_base__status
28841wuffs_gif__decoder__decode_up_to_id_part1(
28842 wuffs_gif__decoder* self,
28843 wuffs_base__io_buffer* a_src);
28844
28845static wuffs_base__status
28846wuffs_gif__decoder__decode_header(
28847 wuffs_gif__decoder* self,
28848 wuffs_base__io_buffer* a_src);
28849
28850static wuffs_base__status
28851wuffs_gif__decoder__decode_lsd(
28852 wuffs_gif__decoder* self,
28853 wuffs_base__io_buffer* a_src);
28854
28855static wuffs_base__status
28856wuffs_gif__decoder__decode_extension(
28857 wuffs_gif__decoder* self,
28858 wuffs_base__io_buffer* a_src);
28859
28860static wuffs_base__status
28861wuffs_gif__decoder__skip_blocks(
28862 wuffs_gif__decoder* self,
28863 wuffs_base__io_buffer* a_src);
28864
28865static wuffs_base__status
28866wuffs_gif__decoder__decode_ae(
28867 wuffs_gif__decoder* self,
28868 wuffs_base__io_buffer* a_src);
28869
28870static wuffs_base__status
28871wuffs_gif__decoder__decode_gc(
28872 wuffs_gif__decoder* self,
28873 wuffs_base__io_buffer* a_src);
28874
28875static wuffs_base__status
28876wuffs_gif__decoder__decode_id_part0(
28877 wuffs_gif__decoder* self,
28878 wuffs_base__io_buffer* a_src);
28879
28880static wuffs_base__status
28881wuffs_gif__decoder__decode_id_part1(
28882 wuffs_gif__decoder* self,
28883 wuffs_base__pixel_buffer* a_dst,
28884 wuffs_base__io_buffer* a_src,
28885 wuffs_base__pixel_blend a_blend);
28886
28887static wuffs_base__status
28888wuffs_gif__decoder__decode_id_part2(
28889 wuffs_gif__decoder* self,
28890 wuffs_base__pixel_buffer* a_dst,
28891 wuffs_base__io_buffer* a_src,
28892 wuffs_base__slice_u8 a_workbuf);
28893
28894static wuffs_base__status
28895wuffs_gif__decoder__copy_to_image_buffer(
28896 wuffs_gif__decoder* self,
28897 wuffs_base__pixel_buffer* a_pb,
28898 wuffs_base__slice_u8 a_src);
28899
28900// ---------------- VTables
28901
28902const wuffs_base__image_decoder__func_ptrs
28903wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder = {
28904 (wuffs_base__status(*)(void*,
28905 wuffs_base__pixel_buffer*,
28906 wuffs_base__io_buffer*,
28907 wuffs_base__pixel_blend,
28908 wuffs_base__slice_u8,
28909 wuffs_base__decode_frame_options*))(&wuffs_gif__decoder__decode_frame),
28910 (wuffs_base__status(*)(void*,
28911 wuffs_base__frame_config*,
28912 wuffs_base__io_buffer*))(&wuffs_gif__decoder__decode_frame_config),
28913 (wuffs_base__status(*)(void*,
28914 wuffs_base__image_config*,
28915 wuffs_base__io_buffer*))(&wuffs_gif__decoder__decode_image_config),
28916 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_gif__decoder__frame_dirty_rect),
28917 (uint32_t(*)(const void*))(&wuffs_gif__decoder__num_animation_loops),
28918 (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frame_configs),
28919 (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frames),
28920 (wuffs_base__status(*)(void*,
28921 uint64_t,
28922 uint64_t))(&wuffs_gif__decoder__restart_frame),
28923 (wuffs_base__empty_struct(*)(void*,
28924 uint32_t,
28925 bool))(&wuffs_gif__decoder__set_quirk_enabled),
28926 (wuffs_base__empty_struct(*)(void*,
28927 uint32_t,
28928 bool))(&wuffs_gif__decoder__set_report_metadata),
28929 (wuffs_base__status(*)(void*,
28930 wuffs_base__io_buffer*,
28931 wuffs_base__more_information*,
28932 wuffs_base__io_buffer*))(&wuffs_gif__decoder__tell_me_more),
28933 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_gif__decoder__workbuf_len),
28934};
28935
28936// ---------------- Initializer Implementations
28937
28938wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
28939wuffs_gif__decoder__initialize(
28940 wuffs_gif__decoder* self,
28941 size_t sizeof_star_self,
28942 uint64_t wuffs_version,
28943 uint32_t options){
28944 if (!self) {
28945 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
28946 }
28947 if (sizeof(*self) != sizeof_star_self) {
28948 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
28949 }
28950 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
28951 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
28952 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
28953 }
28954
28955 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
28956 // The whole point of this if-check is to detect an uninitialized *self.
28957 // We disable the warning on GCC. Clang-5.0 does not have this warning.
28958#if !defined(__clang__) && defined(__GNUC__)
28959#pragma GCC diagnostic push
28960#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
28961#endif
28962 if (self->private_impl.magic != 0) {
28963 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
28964 }
28965#if !defined(__clang__) && defined(__GNUC__)
28966#pragma GCC diagnostic pop
28967#endif
28968 } else {
28969 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
28970 memset(self, 0, sizeof(*self));
28971 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
28972 } else {
28973 memset(&(self->private_impl), 0, sizeof(self->private_impl));
28974 }
28975 }
28976
28977 {
28978 wuffs_base__status z = wuffs_lzw__decoder__initialize(
28979 &self->private_data.f_lzw, sizeof(self->private_data.f_lzw), WUFFS_VERSION, options);
28980 if (z.repr) {
28981 return z;
28982 }
28983 }
28984 self->private_impl.magic = WUFFS_BASE__MAGIC;
28985 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
28986 wuffs_base__image_decoder__vtable_name;
28987 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
28988 (const void*)(&wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder);
28989 return wuffs_base__make_status(NULL);
28990}
28991
28992wuffs_gif__decoder*
28993wuffs_gif__decoder__alloc() {
28994 wuffs_gif__decoder* x =
28995 (wuffs_gif__decoder*)(calloc(sizeof(wuffs_gif__decoder), 1));
28996 if (!x) {
28997 return NULL;
28998 }
28999 if (wuffs_gif__decoder__initialize(
29000 x, sizeof(wuffs_gif__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
29001 free(x);
29002 return NULL;
29003 }
29004 return x;
29005}
29006
29007size_t
29008sizeof__wuffs_gif__decoder() {
29009 return sizeof(wuffs_gif__decoder);
29010}
29011
29012// ---------------- Function Implementations
29013
29014// -------- func gif.decoder.set_quirk_enabled
29015
29016WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
29017wuffs_gif__decoder__set_quirk_enabled(
29018 wuffs_gif__decoder* self,
29019 uint32_t a_quirk,
29020 bool a_enabled) {
29021 if (!self) {
29022 return wuffs_base__make_empty_struct();
29023 }
29024 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
29025 return wuffs_base__make_empty_struct();
29026 }
29027
29028 if ((self->private_impl.f_call_sequence == 0) && (a_quirk >= 1041635328)) {
29029 a_quirk -= 1041635328;
29030 if (a_quirk < 7) {
29031 self->private_impl.f_quirks[a_quirk] = a_enabled;
29032 }
29033 }
29034 return wuffs_base__make_empty_struct();
29035}
29036
29037// -------- func gif.decoder.decode_image_config
29038
29039WUFFS_BASE__MAYBE_STATIC wuffs_base__status
29040wuffs_gif__decoder__decode_image_config(
29041 wuffs_gif__decoder* self,
29042 wuffs_base__image_config* a_dst,
29043 wuffs_base__io_buffer* a_src) {
29044 if (!self) {
29045 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
29046 }
29047 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
29048 return wuffs_base__make_status(
29049 (self->private_impl.magic == WUFFS_BASE__DISABLED)
29050 ? wuffs_base__error__disabled_by_previous_error
29051 : wuffs_base__error__initialize_not_called);
29052 }
29053 if (!a_src) {
29054 self->private_impl.magic = WUFFS_BASE__DISABLED;
29055 return wuffs_base__make_status(wuffs_base__error__bad_argument);
29056 }
29057 if ((self->private_impl.active_coroutine != 0) &&
29058 (self->private_impl.active_coroutine != 1)) {
29059 self->private_impl.magic = WUFFS_BASE__DISABLED;
29060 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
29061 }
29062 self->private_impl.active_coroutine = 0;
29063 wuffs_base__status status = wuffs_base__make_status(NULL);
29064
29065 bool v_ffio = false;
29066
29067 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
29068 switch (coro_susp_point) {
29069 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29070
29071 if (self->private_impl.f_call_sequence == 0) {
29072 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29073 status = wuffs_gif__decoder__decode_header(self, a_src);
29074 if (status.repr) {
29075 goto suspend;
29076 }
29077 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
29078 status = wuffs_gif__decoder__decode_lsd(self, a_src);
29079 if (status.repr) {
29080 goto suspend;
29081 }
29082 } else if (self->private_impl.f_call_sequence != 2) {
29083 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
29084 goto exit;
29085 }
29086 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
29087 status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src);
29088 if (status.repr) {
29089 goto suspend;
29090 }
29091 v_ffio = ! self->private_impl.f_gc_has_transparent_index;
29092 if ( ! self->private_impl.f_quirks[2]) {
29093 v_ffio = (v_ffio &&
29094 (self->private_impl.f_frame_rect_x0 == 0) &&
29095 (self->private_impl.f_frame_rect_y0 == 0) &&
29096 (self->private_impl.f_frame_rect_x1 == self->private_impl.f_width) &&
29097 (self->private_impl.f_frame_rect_y1 == self->private_impl.f_height));
29098 } else if (v_ffio) {
29099 self->private_impl.f_black_color_u32_argb_premul = 4278190080;
29100 }
29101 if (self->private_impl.f_background_color_u32_argb_premul == 77) {
29102 self->private_impl.f_background_color_u32_argb_premul = self->private_impl.f_black_color_u32_argb_premul;
29103 }
29104 if (a_dst != NULL) {
29105 wuffs_base__image_config__set(
29106 a_dst,
29107 2198077448,
29108 0,
29109 self->private_impl.f_width,
29110 self->private_impl.f_height,
29111 self->private_impl.f_frame_config_io_position,
29112 v_ffio);
29113 }
29114 self->private_impl.f_call_sequence = 3;
29115
29116 goto ok;
29117 ok:
29118 self->private_impl.p_decode_image_config[0] = 0;
29119 goto exit;
29120 }
29121
29122 goto suspend;
29123 suspend:
29124 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29125 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
29126
29127 goto exit;
29128 exit:
29129 if (wuffs_base__status__is_error(&status)) {
29130 self->private_impl.magic = WUFFS_BASE__DISABLED;
29131 }
29132 return status;
29133}
29134
29135// -------- func gif.decoder.set_report_metadata
29136
29137WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
29138wuffs_gif__decoder__set_report_metadata(
29139 wuffs_gif__decoder* self,
29140 uint32_t a_fourcc,
29141 bool a_report) {
29142 if (!self) {
29143 return wuffs_base__make_empty_struct();
29144 }
29145 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
29146 return wuffs_base__make_empty_struct();
29147 }
29148
29149 if (a_fourcc == 1229144912) {
29150 self->private_impl.f_report_metadata_iccp = a_report;
29151 } else if (a_fourcc == 1481461792) {
29152 self->private_impl.f_report_metadata_xmp = a_report;
29153 }
29154 return wuffs_base__make_empty_struct();
29155}
29156
29157// -------- func gif.decoder.tell_me_more
29158
29159WUFFS_BASE__MAYBE_STATIC wuffs_base__status
29160wuffs_gif__decoder__tell_me_more(
29161 wuffs_gif__decoder* self,
29162 wuffs_base__io_buffer* a_dst,
29163 wuffs_base__more_information* a_minfo,
29164 wuffs_base__io_buffer* a_src) {
29165 if (!self) {
29166 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
29167 }
29168 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
29169 return wuffs_base__make_status(
29170 (self->private_impl.magic == WUFFS_BASE__DISABLED)
29171 ? wuffs_base__error__disabled_by_previous_error
29172 : wuffs_base__error__initialize_not_called);
29173 }
29174 if (!a_dst || !a_src) {
29175 self->private_impl.magic = WUFFS_BASE__DISABLED;
29176 return wuffs_base__make_status(wuffs_base__error__bad_argument);
29177 }
29178 if ((self->private_impl.active_coroutine != 0) &&
29179 (self->private_impl.active_coroutine != 2)) {
29180 self->private_impl.magic = WUFFS_BASE__DISABLED;
29181 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
29182 }
29183 self->private_impl.active_coroutine = 0;
29184 wuffs_base__status status = wuffs_base__make_status(NULL);
29185
29186 uint64_t v_chunk_length = 0;
29187
29188 const uint8_t* iop_a_src = NULL;
29189 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29190 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29191 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29192 if (a_src) {
29193 io0_a_src = a_src->data.ptr;
29194 io1_a_src = io0_a_src + a_src->meta.ri;
29195 iop_a_src = io1_a_src;
29196 io2_a_src = io0_a_src + a_src->meta.wi;
29197 }
29198
29199 uint32_t coro_susp_point = self->private_impl.p_tell_me_more[0];
29200 switch (coro_susp_point) {
29201 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29202
29203 if (self->private_impl.f_call_sequence != 1) {
29204 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
29205 goto exit;
29206 }
29207 if (self->private_impl.f_metadata_fourcc == 0) {
29208 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
29209 goto exit;
29210 }
29211 while (true) {
29212 label__0__continue:;
29213 while (true) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029214 if (wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) != self->private_impl.f_metadata_io_position) {
Nigel Taoe360a532021-04-05 22:47:03 +100029215 if (a_minfo != NULL) {
29216 wuffs_base__more_information__set(a_minfo,
29217 2,
29218 0,
29219 self->private_impl.f_metadata_io_position,
29220 0,
29221 0);
29222 }
29223 status = wuffs_base__make_status(wuffs_base__suspension__mispositioned_read);
29224 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
29225 goto label__0__continue;
29226 }
29227 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
29228 if (a_minfo != NULL) {
29229 wuffs_base__more_information__set(a_minfo,
29230 0,
29231 0,
29232 0,
29233 0,
29234 0);
29235 }
29236 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29237 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
29238 goto label__0__continue;
29239 }
29240 goto label__0__break;
29241 }
29242 label__0__break:;
29243 v_chunk_length = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src)));
29244 if (v_chunk_length <= 0) {
29245 iop_a_src += 1;
29246 goto label__1__break;
29247 }
29248 if (self->private_impl.f_metadata_fourcc == 1481461792) {
29249 v_chunk_length += 1;
29250 } else {
29251 iop_a_src += 1;
29252 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029253 self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))), v_chunk_length);
Nigel Taoe360a532021-04-05 22:47:03 +100029254 if (a_minfo != NULL) {
29255 wuffs_base__more_information__set(a_minfo,
29256 3,
29257 self->private_impl.f_metadata_fourcc,
29258 0,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029259 wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))),
Nigel Taoe360a532021-04-05 22:47:03 +100029260 self->private_impl.f_metadata_io_position);
29261 }
29262 status = wuffs_base__make_status(wuffs_base__suspension__even_more_information);
29263 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
29264 }
29265 label__1__break:;
29266 if (a_minfo != NULL) {
29267 wuffs_base__more_information__set(a_minfo,
29268 3,
29269 self->private_impl.f_metadata_fourcc,
29270 0,
29271 self->private_impl.f_metadata_io_position,
29272 self->private_impl.f_metadata_io_position);
29273 }
29274 self->private_impl.f_call_sequence = 2;
29275 self->private_impl.f_metadata_fourcc = 0;
29276 self->private_impl.f_metadata_io_position = 0;
29277 status = wuffs_base__make_status(NULL);
29278 goto ok;
29279
Nigel Taoe360a532021-04-05 22:47:03 +100029280 ok:
29281 self->private_impl.p_tell_me_more[0] = 0;
29282 goto exit;
29283 }
29284
29285 goto suspend;
29286 suspend:
29287 self->private_impl.p_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29288 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
29289
29290 goto exit;
29291 exit:
29292 if (a_src) {
29293 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29294 }
29295
29296 if (wuffs_base__status__is_error(&status)) {
29297 self->private_impl.magic = WUFFS_BASE__DISABLED;
29298 }
29299 return status;
29300}
29301
29302// -------- func gif.decoder.num_animation_loops
29303
29304WUFFS_BASE__MAYBE_STATIC uint32_t
29305wuffs_gif__decoder__num_animation_loops(
29306 const wuffs_gif__decoder* self) {
29307 if (!self) {
29308 return 0;
29309 }
29310 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
29311 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
29312 return 0;
29313 }
29314
Nigel Taobf9dab32021-11-18 19:19:55 +110029315 if (self->private_impl.f_seen_num_animation_loops_value) {
29316 return self->private_impl.f_num_animation_loops_value;
Nigel Taoe360a532021-04-05 22:47:03 +100029317 }
29318 return 1;
29319}
29320
29321// -------- func gif.decoder.num_decoded_frame_configs
29322
29323WUFFS_BASE__MAYBE_STATIC uint64_t
29324wuffs_gif__decoder__num_decoded_frame_configs(
29325 const wuffs_gif__decoder* self) {
29326 if (!self) {
29327 return 0;
29328 }
29329 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
29330 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
29331 return 0;
29332 }
29333
29334 return self->private_impl.f_num_decoded_frame_configs_value;
29335}
29336
29337// -------- func gif.decoder.num_decoded_frames
29338
29339WUFFS_BASE__MAYBE_STATIC uint64_t
29340wuffs_gif__decoder__num_decoded_frames(
29341 const wuffs_gif__decoder* self) {
29342 if (!self) {
29343 return 0;
29344 }
29345 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
29346 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
29347 return 0;
29348 }
29349
29350 return self->private_impl.f_num_decoded_frames_value;
29351}
29352
29353// -------- func gif.decoder.frame_dirty_rect
29354
29355WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
29356wuffs_gif__decoder__frame_dirty_rect(
29357 const wuffs_gif__decoder* self) {
29358 if (!self) {
29359 return wuffs_base__utility__empty_rect_ie_u32();
29360 }
29361 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
29362 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
29363 return wuffs_base__utility__empty_rect_ie_u32();
29364 }
29365
29366 return wuffs_base__utility__make_rect_ie_u32(
29367 wuffs_base__u32__min(self->private_impl.f_frame_rect_x0, self->private_impl.f_width),
29368 wuffs_base__u32__min(self->private_impl.f_frame_rect_y0, self->private_impl.f_height),
29369 wuffs_base__u32__min(self->private_impl.f_frame_rect_x1, self->private_impl.f_width),
29370 wuffs_base__u32__min(self->private_impl.f_dirty_max_excl_y, self->private_impl.f_height));
29371}
29372
29373// -------- func gif.decoder.workbuf_len
29374
29375WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
29376wuffs_gif__decoder__workbuf_len(
29377 const wuffs_gif__decoder* self) {
29378 if (!self) {
29379 return wuffs_base__utility__empty_range_ii_u64();
29380 }
29381 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
29382 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
29383 return wuffs_base__utility__empty_range_ii_u64();
29384 }
29385
29386 return wuffs_base__utility__make_range_ii_u64(0, 0);
29387}
29388
29389// -------- func gif.decoder.restart_frame
29390
29391WUFFS_BASE__MAYBE_STATIC wuffs_base__status
29392wuffs_gif__decoder__restart_frame(
29393 wuffs_gif__decoder* self,
29394 uint64_t a_index,
29395 uint64_t a_io_position) {
29396 if (!self) {
29397 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
29398 }
29399 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
29400 return wuffs_base__make_status(
29401 (self->private_impl.magic == WUFFS_BASE__DISABLED)
29402 ? wuffs_base__error__disabled_by_previous_error
29403 : wuffs_base__error__initialize_not_called);
29404 }
29405
29406 if (self->private_impl.f_call_sequence < 3) {
29407 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
29408 }
29409 self->private_impl.f_delayed_num_decoded_frames = false;
29410 self->private_impl.f_end_of_data = false;
29411 self->private_impl.f_restarted = true;
29412 self->private_impl.f_frame_config_io_position = a_io_position;
29413 self->private_impl.f_num_decoded_frame_configs_value = a_index;
29414 self->private_impl.f_num_decoded_frames_value = a_index;
29415 wuffs_gif__decoder__reset_gc(self);
29416 return wuffs_base__make_status(NULL);
29417}
29418
29419// -------- func gif.decoder.decode_frame_config
29420
29421WUFFS_BASE__MAYBE_STATIC wuffs_base__status
29422wuffs_gif__decoder__decode_frame_config(
29423 wuffs_gif__decoder* self,
29424 wuffs_base__frame_config* a_dst,
29425 wuffs_base__io_buffer* a_src) {
29426 if (!self) {
29427 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
29428 }
29429 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
29430 return wuffs_base__make_status(
29431 (self->private_impl.magic == WUFFS_BASE__DISABLED)
29432 ? wuffs_base__error__disabled_by_previous_error
29433 : wuffs_base__error__initialize_not_called);
29434 }
29435 if (!a_src) {
29436 self->private_impl.magic = WUFFS_BASE__DISABLED;
29437 return wuffs_base__make_status(wuffs_base__error__bad_argument);
29438 }
29439 if ((self->private_impl.active_coroutine != 0) &&
29440 (self->private_impl.active_coroutine != 3)) {
29441 self->private_impl.magic = WUFFS_BASE__DISABLED;
29442 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
29443 }
29444 self->private_impl.active_coroutine = 0;
29445 wuffs_base__status status = wuffs_base__make_status(NULL);
29446
29447 uint32_t v_background_color = 0;
29448 uint8_t v_flags = 0;
29449
29450 const uint8_t* iop_a_src = NULL;
29451 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29452 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29453 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29454 if (a_src) {
29455 io0_a_src = a_src->data.ptr;
29456 io1_a_src = io0_a_src + a_src->meta.ri;
29457 iop_a_src = io1_a_src;
29458 io2_a_src = io0_a_src + a_src->meta.wi;
29459 }
29460
29461 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
29462 if (coro_susp_point) {
29463 v_background_color = self->private_data.s_decode_frame_config[0].v_background_color;
29464 }
29465 switch (coro_susp_point) {
29466 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29467
29468 self->private_impl.f_ignore_metadata = true;
29469 self->private_impl.f_dirty_max_excl_y = 0;
29470 if ( ! self->private_impl.f_end_of_data) {
29471 if (self->private_impl.f_call_sequence == 0) {
29472 if (a_src) {
29473 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29474 }
29475 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29476 status = wuffs_gif__decoder__decode_image_config(self, NULL, a_src);
29477 if (a_src) {
29478 iop_a_src = a_src->data.ptr + a_src->meta.ri;
29479 }
29480 if (status.repr) {
29481 goto suspend;
29482 }
29483 } else if (self->private_impl.f_call_sequence != 3) {
29484 if (self->private_impl.f_call_sequence == 4) {
29485 if (a_src) {
29486 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29487 }
29488 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
29489 status = wuffs_gif__decoder__skip_frame(self, a_src);
29490 if (a_src) {
29491 iop_a_src = a_src->data.ptr + a_src->meta.ri;
29492 }
29493 if (status.repr) {
29494 goto suspend;
29495 }
29496 }
29497 if (a_src) {
29498 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29499 }
29500 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
29501 status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src);
29502 if (a_src) {
29503 iop_a_src = a_src->data.ptr + a_src->meta.ri;
29504 }
29505 if (status.repr) {
29506 goto suspend;
29507 }
29508 }
29509 }
29510 if (self->private_impl.f_end_of_data) {
29511 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
29512 goto ok;
29513 }
29514 v_background_color = self->private_impl.f_black_color_u32_argb_premul;
29515 if ( ! self->private_impl.f_gc_has_transparent_index) {
29516 v_background_color = self->private_impl.f_background_color_u32_argb_premul;
29517 if (self->private_impl.f_quirks[1] && (self->private_impl.f_num_decoded_frame_configs_value == 0)) {
29518 while (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
29519 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29520 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
29521 }
29522 v_flags = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
29523 if ((v_flags & 128) != 0) {
29524 v_background_color = self->private_impl.f_black_color_u32_argb_premul;
29525 }
29526 }
29527 }
29528 if (a_dst != NULL) {
29529 wuffs_base__frame_config__set(
29530 a_dst,
29531 wuffs_base__utility__make_rect_ie_u32(
29532 wuffs_base__u32__min(self->private_impl.f_frame_rect_x0, self->private_impl.f_width),
29533 wuffs_base__u32__min(self->private_impl.f_frame_rect_y0, self->private_impl.f_height),
29534 wuffs_base__u32__min(self->private_impl.f_frame_rect_x1, self->private_impl.f_width),
29535 wuffs_base__u32__min(self->private_impl.f_frame_rect_y1, self->private_impl.f_height)),
29536 ((wuffs_base__flicks)(self->private_impl.f_gc_duration)),
29537 self->private_impl.f_num_decoded_frame_configs_value,
29538 self->private_impl.f_frame_config_io_position,
29539 self->private_impl.f_gc_disposal,
29540 ! self->private_impl.f_gc_has_transparent_index,
29541 false,
29542 v_background_color);
29543 }
29544 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frame_configs_value, 1);
29545 self->private_impl.f_call_sequence = 4;
29546
Nigel Taoe360a532021-04-05 22:47:03 +100029547 ok:
29548 self->private_impl.p_decode_frame_config[0] = 0;
29549 goto exit;
29550 }
29551
29552 goto suspend;
29553 suspend:
29554 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29555 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
29556 self->private_data.s_decode_frame_config[0].v_background_color = v_background_color;
29557
29558 goto exit;
29559 exit:
29560 if (a_src) {
29561 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29562 }
29563
29564 if (wuffs_base__status__is_error(&status)) {
29565 self->private_impl.magic = WUFFS_BASE__DISABLED;
29566 }
29567 return status;
29568}
29569
29570// -------- func gif.decoder.skip_frame
29571
29572static wuffs_base__status
29573wuffs_gif__decoder__skip_frame(
29574 wuffs_gif__decoder* self,
29575 wuffs_base__io_buffer* a_src) {
29576 wuffs_base__status status = wuffs_base__make_status(NULL);
29577
29578 uint8_t v_flags = 0;
29579 uint8_t v_lw = 0;
29580
29581 const uint8_t* iop_a_src = NULL;
29582 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29583 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29584 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29585 if (a_src) {
29586 io0_a_src = a_src->data.ptr;
29587 io1_a_src = io0_a_src + a_src->meta.ri;
29588 iop_a_src = io1_a_src;
29589 io2_a_src = io0_a_src + a_src->meta.wi;
29590 }
29591
29592 uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
29593 switch (coro_susp_point) {
29594 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29595
29596 {
29597 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29598 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29599 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29600 goto suspend;
29601 }
29602 uint8_t t_0 = *iop_a_src++;
29603 v_flags = t_0;
29604 }
29605 if ((v_flags & 128) != 0) {
29606 self->private_data.s_skip_frame[0].scratch = (((uint32_t)(3)) << (1 + (v_flags & 7)));
29607 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
29608 if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
29609 self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
29610 iop_a_src = io2_a_src;
29611 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29612 goto suspend;
29613 }
29614 iop_a_src += self->private_data.s_skip_frame[0].scratch;
29615 }
29616 {
29617 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
29618 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29619 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29620 goto suspend;
29621 }
29622 uint8_t t_1 = *iop_a_src++;
29623 v_lw = t_1;
29624 }
29625 if (v_lw > 8) {
29626 status = wuffs_base__make_status(wuffs_gif__error__bad_literal_width);
29627 goto exit;
29628 }
29629 if (a_src) {
29630 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29631 }
29632 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
29633 status = wuffs_gif__decoder__skip_blocks(self, a_src);
29634 if (a_src) {
29635 iop_a_src = a_src->data.ptr + a_src->meta.ri;
29636 }
29637 if (status.repr) {
29638 goto suspend;
29639 }
29640 if (self->private_impl.f_quirks[0]) {
29641 self->private_impl.f_delayed_num_decoded_frames = true;
29642 } else {
29643 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
29644 }
29645 wuffs_gif__decoder__reset_gc(self);
29646
29647 goto ok;
29648 ok:
29649 self->private_impl.p_skip_frame[0] = 0;
29650 goto exit;
29651 }
29652
29653 goto suspend;
29654 suspend:
29655 self->private_impl.p_skip_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29656
29657 goto exit;
29658 exit:
29659 if (a_src) {
29660 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29661 }
29662
29663 return status;
29664}
29665
29666// -------- func gif.decoder.decode_frame
29667
29668WUFFS_BASE__MAYBE_STATIC wuffs_base__status
29669wuffs_gif__decoder__decode_frame(
29670 wuffs_gif__decoder* self,
29671 wuffs_base__pixel_buffer* a_dst,
29672 wuffs_base__io_buffer* a_src,
29673 wuffs_base__pixel_blend a_blend,
29674 wuffs_base__slice_u8 a_workbuf,
29675 wuffs_base__decode_frame_options* a_opts) {
29676 if (!self) {
29677 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
29678 }
29679 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
29680 return wuffs_base__make_status(
29681 (self->private_impl.magic == WUFFS_BASE__DISABLED)
29682 ? wuffs_base__error__disabled_by_previous_error
29683 : wuffs_base__error__initialize_not_called);
29684 }
29685 if (!a_dst || !a_src) {
29686 self->private_impl.magic = WUFFS_BASE__DISABLED;
29687 return wuffs_base__make_status(wuffs_base__error__bad_argument);
29688 }
29689 if ((self->private_impl.active_coroutine != 0) &&
29690 (self->private_impl.active_coroutine != 4)) {
29691 self->private_impl.magic = WUFFS_BASE__DISABLED;
29692 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
29693 }
29694 self->private_impl.active_coroutine = 0;
29695 wuffs_base__status status = wuffs_base__make_status(NULL);
29696
29697 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
29698 switch (coro_susp_point) {
29699 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29700
29701 self->private_impl.f_ignore_metadata = true;
29702 if (self->private_impl.f_call_sequence != 4) {
29703 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29704 status = wuffs_gif__decoder__decode_frame_config(self, NULL, a_src);
29705 if (status.repr) {
29706 goto suspend;
29707 }
29708 }
29709 if (self->private_impl.f_quirks[5] && ((self->private_impl.f_frame_rect_x0 == self->private_impl.f_frame_rect_x1) || (self->private_impl.f_frame_rect_y0 == self->private_impl.f_frame_rect_y1))) {
29710 status = wuffs_base__make_status(wuffs_gif__error__bad_frame_size);
29711 goto exit;
29712 }
29713 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
29714 status = wuffs_gif__decoder__decode_id_part1(self, a_dst, a_src, a_blend);
29715 if (status.repr) {
29716 goto suspend;
29717 }
29718 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
29719 status = wuffs_gif__decoder__decode_id_part2(self, a_dst, a_src, a_workbuf);
29720 if (status.repr) {
29721 goto suspend;
29722 }
29723 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
29724 wuffs_gif__decoder__reset_gc(self);
29725
29726 goto ok;
29727 ok:
29728 self->private_impl.p_decode_frame[0] = 0;
29729 goto exit;
29730 }
29731
29732 goto suspend;
29733 suspend:
29734 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29735 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0;
29736
29737 goto exit;
29738 exit:
29739 if (wuffs_base__status__is_error(&status)) {
29740 self->private_impl.magic = WUFFS_BASE__DISABLED;
29741 }
29742 return status;
29743}
29744
29745// -------- func gif.decoder.reset_gc
29746
29747static wuffs_base__empty_struct
29748wuffs_gif__decoder__reset_gc(
29749 wuffs_gif__decoder* self) {
29750 self->private_impl.f_call_sequence = 5;
29751 self->private_impl.f_gc_has_transparent_index = false;
29752 self->private_impl.f_gc_transparent_index = 0;
29753 self->private_impl.f_gc_disposal = 0;
29754 self->private_impl.f_gc_duration = 0;
29755 return wuffs_base__make_empty_struct();
29756}
29757
29758// -------- func gif.decoder.decode_up_to_id_part1
29759
29760static wuffs_base__status
29761wuffs_gif__decoder__decode_up_to_id_part1(
29762 wuffs_gif__decoder* self,
29763 wuffs_base__io_buffer* a_src) {
29764 wuffs_base__status status = wuffs_base__make_status(NULL);
29765
29766 uint8_t v_block_type = 0;
29767
29768 const uint8_t* iop_a_src = NULL;
29769 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29770 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29771 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29772 if (a_src) {
29773 io0_a_src = a_src->data.ptr;
29774 io1_a_src = io0_a_src + a_src->meta.ri;
29775 iop_a_src = io1_a_src;
29776 io2_a_src = io0_a_src + a_src->meta.wi;
29777 }
29778
29779 uint32_t coro_susp_point = self->private_impl.p_decode_up_to_id_part1[0];
29780 switch (coro_susp_point) {
29781 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29782
29783 if ( ! self->private_impl.f_restarted) {
29784 if (self->private_impl.f_call_sequence != 2) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029785 self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)));
Nigel Taoe360a532021-04-05 22:47:03 +100029786 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029787 } else if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) {
Nigel Taoe360a532021-04-05 22:47:03 +100029788 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
29789 goto exit;
29790 } else {
29791 self->private_impl.f_restarted = false;
29792 }
29793 while (true) {
29794 {
29795 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29796 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29797 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29798 goto suspend;
29799 }
29800 uint8_t t_0 = *iop_a_src++;
29801 v_block_type = t_0;
29802 }
29803 if (v_block_type == 33) {
29804 if (a_src) {
29805 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29806 }
29807 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
29808 status = wuffs_gif__decoder__decode_extension(self, a_src);
29809 if (a_src) {
29810 iop_a_src = a_src->data.ptr + a_src->meta.ri;
29811 }
29812 if (status.repr) {
29813 goto suspend;
29814 }
29815 } else if (v_block_type == 44) {
29816 if (self->private_impl.f_delayed_num_decoded_frames) {
29817 self->private_impl.f_delayed_num_decoded_frames = false;
29818 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
29819 }
29820 if (a_src) {
29821 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29822 }
29823 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
29824 status = wuffs_gif__decoder__decode_id_part0(self, a_src);
29825 if (a_src) {
29826 iop_a_src = a_src->data.ptr + a_src->meta.ri;
29827 }
29828 if (status.repr) {
29829 goto suspend;
29830 }
29831 goto label__0__break;
29832 } else {
29833 if (self->private_impl.f_delayed_num_decoded_frames) {
29834 self->private_impl.f_delayed_num_decoded_frames = false;
29835 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
29836 }
29837 self->private_impl.f_end_of_data = true;
29838 goto label__0__break;
29839 }
29840 }
29841 label__0__break:;
29842
29843 goto ok;
29844 ok:
29845 self->private_impl.p_decode_up_to_id_part1[0] = 0;
29846 goto exit;
29847 }
29848
29849 goto suspend;
29850 suspend:
29851 self->private_impl.p_decode_up_to_id_part1[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29852
29853 goto exit;
29854 exit:
29855 if (a_src) {
29856 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29857 }
29858
29859 return status;
29860}
29861
29862// -------- func gif.decoder.decode_header
29863
29864static wuffs_base__status
29865wuffs_gif__decoder__decode_header(
29866 wuffs_gif__decoder* self,
29867 wuffs_base__io_buffer* a_src) {
29868 wuffs_base__status status = wuffs_base__make_status(NULL);
29869
29870 uint8_t v_c[6] = {0};
29871 uint32_t v_i = 0;
29872
29873 const uint8_t* iop_a_src = NULL;
29874 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29875 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29876 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29877 if (a_src) {
29878 io0_a_src = a_src->data.ptr;
29879 io1_a_src = io0_a_src + a_src->meta.ri;
29880 iop_a_src = io1_a_src;
29881 io2_a_src = io0_a_src + a_src->meta.wi;
29882 }
29883
29884 uint32_t coro_susp_point = self->private_impl.p_decode_header[0];
29885 if (coro_susp_point) {
29886 memcpy(v_c, self->private_data.s_decode_header[0].v_c, sizeof(v_c));
29887 v_i = self->private_data.s_decode_header[0].v_i;
29888 }
29889 switch (coro_susp_point) {
29890 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29891
29892 while (v_i < 6) {
29893 {
29894 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29895 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29896 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29897 goto suspend;
29898 }
29899 uint8_t t_0 = *iop_a_src++;
29900 v_c[v_i] = t_0;
29901 }
29902 v_i += 1;
29903 }
29904 if ((v_c[0] != 71) ||
29905 (v_c[1] != 73) ||
29906 (v_c[2] != 70) ||
29907 (v_c[3] != 56) ||
29908 ((v_c[4] != 55) && (v_c[4] != 57)) ||
29909 (v_c[5] != 97)) {
29910 status = wuffs_base__make_status(wuffs_gif__error__bad_header);
29911 goto exit;
29912 }
29913
29914 goto ok;
29915 ok:
29916 self->private_impl.p_decode_header[0] = 0;
29917 goto exit;
29918 }
29919
29920 goto suspend;
29921 suspend:
29922 self->private_impl.p_decode_header[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29923 memcpy(self->private_data.s_decode_header[0].v_c, v_c, sizeof(v_c));
29924 self->private_data.s_decode_header[0].v_i = v_i;
29925
29926 goto exit;
29927 exit:
29928 if (a_src) {
29929 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29930 }
29931
29932 return status;
29933}
29934
29935// -------- func gif.decoder.decode_lsd
29936
29937static wuffs_base__status
29938wuffs_gif__decoder__decode_lsd(
29939 wuffs_gif__decoder* self,
29940 wuffs_base__io_buffer* a_src) {
29941 wuffs_base__status status = wuffs_base__make_status(NULL);
29942
29943 uint8_t v_flags = 0;
29944 uint8_t v_background_color_index = 0;
29945 uint32_t v_num_palette_entries = 0;
29946 uint32_t v_i = 0;
29947 uint32_t v_j = 0;
29948 uint32_t v_argb = 0;
29949
29950 const uint8_t* iop_a_src = NULL;
29951 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29952 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29953 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29954 if (a_src) {
29955 io0_a_src = a_src->data.ptr;
29956 io1_a_src = io0_a_src + a_src->meta.ri;
29957 iop_a_src = io1_a_src;
29958 io2_a_src = io0_a_src + a_src->meta.wi;
29959 }
29960
29961 uint32_t coro_susp_point = self->private_impl.p_decode_lsd[0];
29962 if (coro_susp_point) {
29963 v_flags = self->private_data.s_decode_lsd[0].v_flags;
29964 v_background_color_index = self->private_data.s_decode_lsd[0].v_background_color_index;
29965 v_num_palette_entries = self->private_data.s_decode_lsd[0].v_num_palette_entries;
29966 v_i = self->private_data.s_decode_lsd[0].v_i;
29967 }
29968 switch (coro_susp_point) {
29969 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29970
29971 {
29972 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29973 uint32_t t_0;
29974 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
29975 t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
29976 iop_a_src += 2;
29977 } else {
29978 self->private_data.s_decode_lsd[0].scratch = 0;
29979 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
29980 while (true) {
29981 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29982 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29983 goto suspend;
29984 }
29985 uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch;
29986 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
29987 *scratch <<= 8;
29988 *scratch >>= 8;
29989 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
29990 if (num_bits_0 == 8) {
29991 t_0 = ((uint32_t)(*scratch));
29992 break;
29993 }
29994 num_bits_0 += 8;
29995 *scratch |= ((uint64_t)(num_bits_0)) << 56;
29996 }
29997 }
29998 self->private_impl.f_width = t_0;
29999 }
30000 {
30001 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
30002 uint32_t t_1;
30003 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
30004 t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
30005 iop_a_src += 2;
30006 } else {
30007 self->private_data.s_decode_lsd[0].scratch = 0;
30008 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
30009 while (true) {
30010 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30011 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30012 goto suspend;
30013 }
30014 uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch;
30015 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
30016 *scratch <<= 8;
30017 *scratch >>= 8;
30018 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
30019 if (num_bits_1 == 8) {
30020 t_1 = ((uint32_t)(*scratch));
30021 break;
30022 }
30023 num_bits_1 += 8;
30024 *scratch |= ((uint64_t)(num_bits_1)) << 56;
30025 }
30026 }
30027 self->private_impl.f_height = t_1;
30028 }
30029 {
30030 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
30031 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30032 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30033 goto suspend;
30034 }
30035 uint8_t t_2 = *iop_a_src++;
30036 v_flags = t_2;
30037 }
30038 {
30039 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
30040 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30041 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30042 goto suspend;
30043 }
30044 uint8_t t_3 = *iop_a_src++;
30045 v_background_color_index = t_3;
30046 }
30047 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
30048 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30049 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30050 goto suspend;
30051 }
30052 iop_a_src++;
30053 v_i = 0;
30054 self->private_impl.f_has_global_palette = ((v_flags & 128) != 0);
30055 if (self->private_impl.f_has_global_palette) {
30056 v_num_palette_entries = (((uint32_t)(1)) << (1 + (v_flags & 7)));
30057 while (v_i < v_num_palette_entries) {
30058 {
30059 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
30060 uint32_t t_4;
30061 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
30062 t_4 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src)));
30063 iop_a_src += 3;
30064 } else {
30065 self->private_data.s_decode_lsd[0].scratch = 0;
30066 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
30067 while (true) {
30068 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30069 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30070 goto suspend;
30071 }
30072 uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch;
30073 uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFF));
30074 *scratch >>= 8;
30075 *scratch <<= 8;
30076 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4);
30077 if (num_bits_4 == 16) {
30078 t_4 = ((uint32_t)(*scratch >> 40));
30079 break;
30080 }
30081 num_bits_4 += 8;
30082 *scratch |= ((uint64_t)(num_bits_4));
30083 }
30084 }
30085 v_argb = t_4;
30086 }
30087 v_argb |= 4278190080;
30088 self->private_data.f_palettes[0][((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
30089 self->private_data.f_palettes[0][((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
30090 self->private_data.f_palettes[0][((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
30091 self->private_data.f_palettes[0][((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
30092 v_i += 1;
30093 }
30094 if (self->private_impl.f_quirks[2]) {
30095 if ((v_background_color_index != 0) && (((uint32_t)(v_background_color_index)) < v_num_palette_entries)) {
30096 v_j = (4 * ((uint32_t)(v_background_color_index)));
30097 self->private_impl.f_background_color_u32_argb_premul = ((((uint32_t)(self->private_data.f_palettes[0][(v_j + 0)])) << 0) |
30098 (((uint32_t)(self->private_data.f_palettes[0][(v_j + 1)])) << 8) |
30099 (((uint32_t)(self->private_data.f_palettes[0][(v_j + 2)])) << 16) |
30100 (((uint32_t)(self->private_data.f_palettes[0][(v_j + 3)])) << 24));
30101 } else {
30102 self->private_impl.f_background_color_u32_argb_premul = 77;
30103 }
30104 }
30105 }
30106 while (v_i < 256) {
30107 self->private_data.f_palettes[0][((4 * v_i) + 0)] = 0;
30108 self->private_data.f_palettes[0][((4 * v_i) + 1)] = 0;
30109 self->private_data.f_palettes[0][((4 * v_i) + 2)] = 0;
30110 self->private_data.f_palettes[0][((4 * v_i) + 3)] = 255;
30111 v_i += 1;
30112 }
30113
30114 goto ok;
30115 ok:
30116 self->private_impl.p_decode_lsd[0] = 0;
30117 goto exit;
30118 }
30119
30120 goto suspend;
30121 suspend:
30122 self->private_impl.p_decode_lsd[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30123 self->private_data.s_decode_lsd[0].v_flags = v_flags;
30124 self->private_data.s_decode_lsd[0].v_background_color_index = v_background_color_index;
30125 self->private_data.s_decode_lsd[0].v_num_palette_entries = v_num_palette_entries;
30126 self->private_data.s_decode_lsd[0].v_i = v_i;
30127
30128 goto exit;
30129 exit:
30130 if (a_src) {
30131 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30132 }
30133
30134 return status;
30135}
30136
30137// -------- func gif.decoder.decode_extension
30138
30139static wuffs_base__status
30140wuffs_gif__decoder__decode_extension(
30141 wuffs_gif__decoder* self,
30142 wuffs_base__io_buffer* a_src) {
30143 wuffs_base__status status = wuffs_base__make_status(NULL);
30144
30145 uint8_t v_label = 0;
30146
30147 const uint8_t* iop_a_src = NULL;
30148 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30149 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30150 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30151 if (a_src) {
30152 io0_a_src = a_src->data.ptr;
30153 io1_a_src = io0_a_src + a_src->meta.ri;
30154 iop_a_src = io1_a_src;
30155 io2_a_src = io0_a_src + a_src->meta.wi;
30156 }
30157
30158 uint32_t coro_susp_point = self->private_impl.p_decode_extension[0];
30159 switch (coro_susp_point) {
30160 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
30161
30162 {
30163 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
30164 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30165 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30166 goto suspend;
30167 }
30168 uint8_t t_0 = *iop_a_src++;
30169 v_label = t_0;
30170 }
30171 if (v_label == 249) {
30172 if (a_src) {
30173 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30174 }
30175 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
30176 status = wuffs_gif__decoder__decode_gc(self, a_src);
30177 if (a_src) {
30178 iop_a_src = a_src->data.ptr + a_src->meta.ri;
30179 }
30180 if (status.repr) {
30181 goto suspend;
30182 }
30183 status = wuffs_base__make_status(NULL);
30184 goto ok;
30185 } else if (v_label == 255) {
30186 if (a_src) {
30187 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30188 }
30189 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
30190 status = wuffs_gif__decoder__decode_ae(self, a_src);
30191 if (a_src) {
30192 iop_a_src = a_src->data.ptr + a_src->meta.ri;
30193 }
30194 if (status.repr) {
30195 goto suspend;
30196 }
30197 status = wuffs_base__make_status(NULL);
30198 goto ok;
30199 }
30200 if (a_src) {
30201 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30202 }
30203 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
30204 status = wuffs_gif__decoder__skip_blocks(self, a_src);
30205 if (a_src) {
30206 iop_a_src = a_src->data.ptr + a_src->meta.ri;
30207 }
30208 if (status.repr) {
30209 goto suspend;
30210 }
30211
Nigel Taoe360a532021-04-05 22:47:03 +100030212 ok:
30213 self->private_impl.p_decode_extension[0] = 0;
30214 goto exit;
30215 }
30216
30217 goto suspend;
30218 suspend:
30219 self->private_impl.p_decode_extension[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30220
30221 goto exit;
30222 exit:
30223 if (a_src) {
30224 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30225 }
30226
30227 return status;
30228}
30229
30230// -------- func gif.decoder.skip_blocks
30231
30232static wuffs_base__status
30233wuffs_gif__decoder__skip_blocks(
30234 wuffs_gif__decoder* self,
30235 wuffs_base__io_buffer* a_src) {
30236 wuffs_base__status status = wuffs_base__make_status(NULL);
30237
30238 uint8_t v_block_size = 0;
30239
30240 const uint8_t* iop_a_src = NULL;
30241 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30242 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30243 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30244 if (a_src) {
30245 io0_a_src = a_src->data.ptr;
30246 io1_a_src = io0_a_src + a_src->meta.ri;
30247 iop_a_src = io1_a_src;
30248 io2_a_src = io0_a_src + a_src->meta.wi;
30249 }
30250
30251 uint32_t coro_susp_point = self->private_impl.p_skip_blocks[0];
30252 switch (coro_susp_point) {
30253 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
30254
30255 while (true) {
30256 {
30257 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
30258 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30259 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30260 goto suspend;
30261 }
30262 uint8_t t_0 = *iop_a_src++;
30263 v_block_size = t_0;
30264 }
30265 if (v_block_size == 0) {
30266 status = wuffs_base__make_status(NULL);
30267 goto ok;
30268 }
30269 self->private_data.s_skip_blocks[0].scratch = ((uint32_t)(v_block_size));
30270 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
30271 if (self->private_data.s_skip_blocks[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
30272 self->private_data.s_skip_blocks[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
30273 iop_a_src = io2_a_src;
30274 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30275 goto suspend;
30276 }
30277 iop_a_src += self->private_data.s_skip_blocks[0].scratch;
30278 }
30279
Nigel Taoe360a532021-04-05 22:47:03 +100030280 ok:
30281 self->private_impl.p_skip_blocks[0] = 0;
30282 goto exit;
30283 }
30284
30285 goto suspend;
30286 suspend:
30287 self->private_impl.p_skip_blocks[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30288
30289 goto exit;
30290 exit:
30291 if (a_src) {
30292 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30293 }
30294
30295 return status;
30296}
30297
30298// -------- func gif.decoder.decode_ae
30299
30300static wuffs_base__status
30301wuffs_gif__decoder__decode_ae(
30302 wuffs_gif__decoder* self,
30303 wuffs_base__io_buffer* a_src) {
30304 wuffs_base__status status = wuffs_base__make_status(NULL);
30305
30306 uint8_t v_c = 0;
30307 uint8_t v_block_size = 0;
30308 bool v_is_animexts = false;
30309 bool v_is_netscape = false;
30310 bool v_is_iccp = false;
30311 bool v_is_xmp = false;
30312
30313 const uint8_t* iop_a_src = NULL;
30314 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30315 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30316 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30317 if (a_src) {
30318 io0_a_src = a_src->data.ptr;
30319 io1_a_src = io0_a_src + a_src->meta.ri;
30320 iop_a_src = io1_a_src;
30321 io2_a_src = io0_a_src + a_src->meta.wi;
30322 }
30323
30324 uint32_t coro_susp_point = self->private_impl.p_decode_ae[0];
30325 if (coro_susp_point) {
30326 v_block_size = self->private_data.s_decode_ae[0].v_block_size;
30327 v_is_animexts = self->private_data.s_decode_ae[0].v_is_animexts;
30328 v_is_netscape = self->private_data.s_decode_ae[0].v_is_netscape;
30329 v_is_iccp = self->private_data.s_decode_ae[0].v_is_iccp;
30330 v_is_xmp = self->private_data.s_decode_ae[0].v_is_xmp;
30331 }
30332 switch (coro_susp_point) {
30333 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
30334
30335 while (true) {
30336 if (self->private_impl.f_metadata_fourcc != 0) {
30337 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
30338 goto ok;
30339 }
30340 {
30341 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
30342 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30343 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30344 goto suspend;
30345 }
30346 uint8_t t_0 = *iop_a_src++;
30347 v_block_size = t_0;
30348 }
30349 if (v_block_size == 0) {
30350 status = wuffs_base__make_status(NULL);
30351 goto ok;
30352 }
30353 if (v_block_size != 11) {
30354 self->private_data.s_decode_ae[0].scratch = ((uint32_t)(v_block_size));
30355 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
30356 if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
30357 self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
30358 iop_a_src = io2_a_src;
30359 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30360 goto suspend;
30361 }
30362 iop_a_src += self->private_data.s_decode_ae[0].scratch;
30363 goto label__goto_done__break;
30364 }
30365 v_is_animexts = true;
30366 v_is_netscape = true;
30367 v_is_iccp = true;
30368 v_is_xmp = true;
30369 v_block_size = 0;
30370 while (v_block_size < 11) {
30371 {
30372 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
30373 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30374 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30375 goto suspend;
30376 }
30377 uint8_t t_1 = *iop_a_src++;
30378 v_c = t_1;
30379 }
30380 v_is_animexts = (v_is_animexts && (v_c == WUFFS_GIF__ANIMEXTS1DOT0[v_block_size]));
30381 v_is_netscape = (v_is_netscape && (v_c == WUFFS_GIF__NETSCAPE2DOT0[v_block_size]));
30382 v_is_iccp = (v_is_iccp && (v_c == WUFFS_GIF__ICCRGBG1012[v_block_size]));
30383 v_is_xmp = (v_is_xmp && (v_c == WUFFS_GIF__XMPDATAXMP[v_block_size]));
30384#if defined(__GNUC__)
30385#pragma GCC diagnostic push
30386#pragma GCC diagnostic ignored "-Wconversion"
30387#endif
30388 v_block_size += 1;
30389#if defined(__GNUC__)
30390#pragma GCC diagnostic pop
30391#endif
30392 }
30393 if (v_is_animexts || v_is_netscape) {
30394 {
30395 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
30396 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30397 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30398 goto suspend;
30399 }
30400 uint8_t t_2 = *iop_a_src++;
30401 v_block_size = t_2;
30402 }
30403 if (v_block_size != 3) {
30404 self->private_data.s_decode_ae[0].scratch = ((uint32_t)(v_block_size));
30405 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
30406 if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
30407 self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
30408 iop_a_src = io2_a_src;
30409 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30410 goto suspend;
30411 }
30412 iop_a_src += self->private_data.s_decode_ae[0].scratch;
30413 goto label__goto_done__break;
30414 }
30415 {
30416 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
30417 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30418 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30419 goto suspend;
30420 }
30421 uint8_t t_3 = *iop_a_src++;
30422 v_c = t_3;
30423 }
30424 if (v_c != 1) {
30425 self->private_data.s_decode_ae[0].scratch = 2;
30426 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
30427 if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
30428 self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
30429 iop_a_src = io2_a_src;
30430 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30431 goto suspend;
30432 }
30433 iop_a_src += self->private_data.s_decode_ae[0].scratch;
30434 goto label__goto_done__break;
30435 }
30436 {
30437 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
30438 uint32_t t_4;
30439 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
30440 t_4 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
30441 iop_a_src += 2;
30442 } else {
30443 self->private_data.s_decode_ae[0].scratch = 0;
30444 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
30445 while (true) {
30446 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30447 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30448 goto suspend;
30449 }
30450 uint64_t* scratch = &self->private_data.s_decode_ae[0].scratch;
30451 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
30452 *scratch <<= 8;
30453 *scratch >>= 8;
30454 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
30455 if (num_bits_4 == 8) {
30456 t_4 = ((uint32_t)(*scratch));
30457 break;
30458 }
30459 num_bits_4 += 8;
30460 *scratch |= ((uint64_t)(num_bits_4)) << 56;
30461 }
30462 }
Nigel Taobf9dab32021-11-18 19:19:55 +110030463 self->private_impl.f_num_animation_loops_value = t_4;
Nigel Taoe360a532021-04-05 22:47:03 +100030464 }
Nigel Taobf9dab32021-11-18 19:19:55 +110030465 self->private_impl.f_seen_num_animation_loops_value = true;
30466 if ((0 < self->private_impl.f_num_animation_loops_value) && (self->private_impl.f_num_animation_loops_value <= 65535)) {
30467 self->private_impl.f_num_animation_loops_value += 1;
Nigel Taoe360a532021-04-05 22:47:03 +100030468 }
30469 } else if (self->private_impl.f_ignore_metadata) {
30470 } else if (v_is_iccp && self->private_impl.f_report_metadata_iccp) {
30471 self->private_impl.f_metadata_fourcc = 1229144912;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100030472 self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)));
Nigel Taoe360a532021-04-05 22:47:03 +100030473 self->private_impl.f_call_sequence = 1;
30474 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
30475 goto ok;
30476 } else if (v_is_xmp && self->private_impl.f_report_metadata_xmp) {
30477 self->private_impl.f_metadata_fourcc = 1481461792;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100030478 self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)));
Nigel Taoe360a532021-04-05 22:47:03 +100030479 self->private_impl.f_call_sequence = 1;
30480 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
30481 goto ok;
30482 }
30483 goto label__goto_done__break;
30484 }
30485 label__goto_done__break:;
30486 if (a_src) {
30487 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30488 }
30489 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
30490 status = wuffs_gif__decoder__skip_blocks(self, a_src);
30491 if (a_src) {
30492 iop_a_src = a_src->data.ptr + a_src->meta.ri;
30493 }
30494 if (status.repr) {
30495 goto suspend;
30496 }
30497
Nigel Taoe360a532021-04-05 22:47:03 +100030498 ok:
30499 self->private_impl.p_decode_ae[0] = 0;
30500 goto exit;
30501 }
30502
30503 goto suspend;
30504 suspend:
30505 self->private_impl.p_decode_ae[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30506 self->private_data.s_decode_ae[0].v_block_size = v_block_size;
30507 self->private_data.s_decode_ae[0].v_is_animexts = v_is_animexts;
30508 self->private_data.s_decode_ae[0].v_is_netscape = v_is_netscape;
30509 self->private_data.s_decode_ae[0].v_is_iccp = v_is_iccp;
30510 self->private_data.s_decode_ae[0].v_is_xmp = v_is_xmp;
30511
30512 goto exit;
30513 exit:
30514 if (a_src) {
30515 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30516 }
30517
30518 return status;
30519}
30520
30521// -------- func gif.decoder.decode_gc
30522
30523static wuffs_base__status
30524wuffs_gif__decoder__decode_gc(
30525 wuffs_gif__decoder* self,
30526 wuffs_base__io_buffer* a_src) {
30527 wuffs_base__status status = wuffs_base__make_status(NULL);
30528
30529 uint8_t v_c = 0;
30530 uint8_t v_flags = 0;
30531 uint16_t v_gc_duration_centiseconds = 0;
30532
30533 const uint8_t* iop_a_src = NULL;
30534 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30535 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30536 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30537 if (a_src) {
30538 io0_a_src = a_src->data.ptr;
30539 io1_a_src = io0_a_src + a_src->meta.ri;
30540 iop_a_src = io1_a_src;
30541 io2_a_src = io0_a_src + a_src->meta.wi;
30542 }
30543
30544 uint32_t coro_susp_point = self->private_impl.p_decode_gc[0];
30545 switch (coro_susp_point) {
30546 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
30547
30548 {
30549 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
30550 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30551 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30552 goto suspend;
30553 }
30554 uint8_t t_0 = *iop_a_src++;
30555 v_c = t_0;
30556 }
30557 if (v_c != 4) {
30558 status = wuffs_base__make_status(wuffs_gif__error__bad_graphic_control);
30559 goto exit;
30560 }
30561 {
30562 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
30563 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30564 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30565 goto suspend;
30566 }
30567 uint8_t t_1 = *iop_a_src++;
30568 v_flags = t_1;
30569 }
30570 self->private_impl.f_gc_has_transparent_index = ((v_flags & 1) != 0);
30571 v_flags = ((v_flags >> 2) & 7);
30572 if (v_flags == 2) {
30573 self->private_impl.f_gc_disposal = 1;
30574 } else if ((v_flags == 3) || (v_flags == 4)) {
30575 self->private_impl.f_gc_disposal = 2;
30576 } else {
30577 self->private_impl.f_gc_disposal = 0;
30578 }
30579 {
30580 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
30581 uint16_t t_2;
30582 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
30583 t_2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
30584 iop_a_src += 2;
30585 } else {
30586 self->private_data.s_decode_gc[0].scratch = 0;
30587 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
30588 while (true) {
30589 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30590 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30591 goto suspend;
30592 }
30593 uint64_t* scratch = &self->private_data.s_decode_gc[0].scratch;
30594 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
30595 *scratch <<= 8;
30596 *scratch >>= 8;
30597 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
30598 if (num_bits_2 == 8) {
30599 t_2 = ((uint16_t)(*scratch));
30600 break;
30601 }
30602 num_bits_2 += 8;
30603 *scratch |= ((uint64_t)(num_bits_2)) << 56;
30604 }
30605 }
30606 v_gc_duration_centiseconds = t_2;
30607 }
30608 self->private_impl.f_gc_duration = (((uint64_t)(v_gc_duration_centiseconds)) * 7056000);
30609 {
30610 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
30611 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30612 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30613 goto suspend;
30614 }
30615 uint8_t t_3 = *iop_a_src++;
30616 self->private_impl.f_gc_transparent_index = t_3;
30617 }
30618 {
30619 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
30620 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30621 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30622 goto suspend;
30623 }
30624 uint8_t t_4 = *iop_a_src++;
30625 v_c = t_4;
30626 }
30627 if (v_c != 0) {
30628 status = wuffs_base__make_status(wuffs_gif__error__bad_graphic_control);
30629 goto exit;
30630 }
30631
30632 goto ok;
30633 ok:
30634 self->private_impl.p_decode_gc[0] = 0;
30635 goto exit;
30636 }
30637
30638 goto suspend;
30639 suspend:
30640 self->private_impl.p_decode_gc[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30641
30642 goto exit;
30643 exit:
30644 if (a_src) {
30645 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30646 }
30647
30648 return status;
30649}
30650
30651// -------- func gif.decoder.decode_id_part0
30652
30653static wuffs_base__status
30654wuffs_gif__decoder__decode_id_part0(
30655 wuffs_gif__decoder* self,
30656 wuffs_base__io_buffer* a_src) {
30657 wuffs_base__status status = wuffs_base__make_status(NULL);
30658
30659 const uint8_t* iop_a_src = NULL;
30660 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30661 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30662 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30663 if (a_src) {
30664 io0_a_src = a_src->data.ptr;
30665 io1_a_src = io0_a_src + a_src->meta.ri;
30666 iop_a_src = io1_a_src;
30667 io2_a_src = io0_a_src + a_src->meta.wi;
30668 }
30669
30670 uint32_t coro_susp_point = self->private_impl.p_decode_id_part0[0];
30671 switch (coro_susp_point) {
30672 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
30673
30674 {
30675 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
30676 uint32_t t_0;
30677 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
30678 t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
30679 iop_a_src += 2;
30680 } else {
30681 self->private_data.s_decode_id_part0[0].scratch = 0;
30682 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
30683 while (true) {
30684 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30685 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30686 goto suspend;
30687 }
30688 uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch;
30689 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
30690 *scratch <<= 8;
30691 *scratch >>= 8;
30692 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
30693 if (num_bits_0 == 8) {
30694 t_0 = ((uint32_t)(*scratch));
30695 break;
30696 }
30697 num_bits_0 += 8;
30698 *scratch |= ((uint64_t)(num_bits_0)) << 56;
30699 }
30700 }
30701 self->private_impl.f_frame_rect_x0 = t_0;
30702 }
30703 {
30704 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
30705 uint32_t t_1;
30706 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
30707 t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
30708 iop_a_src += 2;
30709 } else {
30710 self->private_data.s_decode_id_part0[0].scratch = 0;
30711 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
30712 while (true) {
30713 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30714 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30715 goto suspend;
30716 }
30717 uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch;
30718 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
30719 *scratch <<= 8;
30720 *scratch >>= 8;
30721 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
30722 if (num_bits_1 == 8) {
30723 t_1 = ((uint32_t)(*scratch));
30724 break;
30725 }
30726 num_bits_1 += 8;
30727 *scratch |= ((uint64_t)(num_bits_1)) << 56;
30728 }
30729 }
30730 self->private_impl.f_frame_rect_y0 = t_1;
30731 }
30732 {
30733 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
30734 uint32_t t_2;
30735 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
30736 t_2 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
30737 iop_a_src += 2;
30738 } else {
30739 self->private_data.s_decode_id_part0[0].scratch = 0;
30740 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
30741 while (true) {
30742 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30743 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30744 goto suspend;
30745 }
30746 uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch;
30747 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
30748 *scratch <<= 8;
30749 *scratch >>= 8;
30750 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
30751 if (num_bits_2 == 8) {
30752 t_2 = ((uint32_t)(*scratch));
30753 break;
30754 }
30755 num_bits_2 += 8;
30756 *scratch |= ((uint64_t)(num_bits_2)) << 56;
30757 }
30758 }
30759 self->private_impl.f_frame_rect_x1 = t_2;
30760 }
30761 self->private_impl.f_frame_rect_x1 += self->private_impl.f_frame_rect_x0;
30762 {
30763 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
30764 uint32_t t_3;
30765 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
30766 t_3 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
30767 iop_a_src += 2;
30768 } else {
30769 self->private_data.s_decode_id_part0[0].scratch = 0;
30770 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
30771 while (true) {
30772 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30773 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30774 goto suspend;
30775 }
30776 uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch;
30777 uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
30778 *scratch <<= 8;
30779 *scratch >>= 8;
30780 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
30781 if (num_bits_3 == 8) {
30782 t_3 = ((uint32_t)(*scratch));
30783 break;
30784 }
30785 num_bits_3 += 8;
30786 *scratch |= ((uint64_t)(num_bits_3)) << 56;
30787 }
30788 }
30789 self->private_impl.f_frame_rect_y1 = t_3;
30790 }
30791 self->private_impl.f_frame_rect_y1 += self->private_impl.f_frame_rect_y0;
30792 self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0;
30793 self->private_impl.f_dst_y = self->private_impl.f_frame_rect_y0;
30794 if ((self->private_impl.f_call_sequence == 0) && ! self->private_impl.f_quirks[4]) {
30795 self->private_impl.f_width = wuffs_base__u32__max(self->private_impl.f_width, self->private_impl.f_frame_rect_x1);
30796 self->private_impl.f_height = wuffs_base__u32__max(self->private_impl.f_height, self->private_impl.f_frame_rect_y1);
30797 }
30798
30799 goto ok;
30800 ok:
30801 self->private_impl.p_decode_id_part0[0] = 0;
30802 goto exit;
30803 }
30804
30805 goto suspend;
30806 suspend:
30807 self->private_impl.p_decode_id_part0[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30808
30809 goto exit;
30810 exit:
30811 if (a_src) {
30812 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30813 }
30814
30815 return status;
30816}
30817
30818// -------- func gif.decoder.decode_id_part1
30819
30820static wuffs_base__status
30821wuffs_gif__decoder__decode_id_part1(
30822 wuffs_gif__decoder* self,
30823 wuffs_base__pixel_buffer* a_dst,
30824 wuffs_base__io_buffer* a_src,
30825 wuffs_base__pixel_blend a_blend) {
30826 wuffs_base__status status = wuffs_base__make_status(NULL);
30827
30828 uint8_t v_flags = 0;
30829 uint8_t v_which_palette = 0;
30830 uint32_t v_num_palette_entries = 0;
30831 uint32_t v_i = 0;
30832 uint32_t v_argb = 0;
30833 wuffs_base__status v_status = wuffs_base__make_status(NULL);
30834 uint8_t v_lw = 0;
30835
30836 const uint8_t* iop_a_src = NULL;
30837 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30838 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30839 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30840 if (a_src) {
30841 io0_a_src = a_src->data.ptr;
30842 io1_a_src = io0_a_src + a_src->meta.ri;
30843 iop_a_src = io1_a_src;
30844 io2_a_src = io0_a_src + a_src->meta.wi;
30845 }
30846
30847 uint32_t coro_susp_point = self->private_impl.p_decode_id_part1[0];
30848 if (coro_susp_point) {
30849 v_which_palette = self->private_data.s_decode_id_part1[0].v_which_palette;
30850 v_num_palette_entries = self->private_data.s_decode_id_part1[0].v_num_palette_entries;
30851 v_i = self->private_data.s_decode_id_part1[0].v_i;
30852 }
30853 switch (coro_susp_point) {
30854 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
30855
30856 {
30857 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
30858 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30859 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30860 goto suspend;
30861 }
30862 uint8_t t_0 = *iop_a_src++;
30863 v_flags = t_0;
30864 }
30865 if ((v_flags & 64) != 0) {
30866 self->private_impl.f_interlace = 4;
30867 } else {
30868 self->private_impl.f_interlace = 0;
30869 }
30870 v_which_palette = 1;
30871 if ((v_flags & 128) != 0) {
30872 v_num_palette_entries = (((uint32_t)(1)) << (1 + (v_flags & 7)));
30873 v_i = 0;
30874 while (v_i < v_num_palette_entries) {
30875 {
30876 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
30877 uint32_t t_1;
30878 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
30879 t_1 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src)));
30880 iop_a_src += 3;
30881 } else {
30882 self->private_data.s_decode_id_part1[0].scratch = 0;
30883 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
30884 while (true) {
30885 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30886 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30887 goto suspend;
30888 }
30889 uint64_t* scratch = &self->private_data.s_decode_id_part1[0].scratch;
30890 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
30891 *scratch >>= 8;
30892 *scratch <<= 8;
30893 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
30894 if (num_bits_1 == 16) {
30895 t_1 = ((uint32_t)(*scratch >> 40));
30896 break;
30897 }
30898 num_bits_1 += 8;
30899 *scratch |= ((uint64_t)(num_bits_1));
30900 }
30901 }
30902 v_argb = t_1;
30903 }
30904 v_argb |= 4278190080;
30905 self->private_data.f_palettes[1][((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
30906 self->private_data.f_palettes[1][((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
30907 self->private_data.f_palettes[1][((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
30908 self->private_data.f_palettes[1][((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
30909 v_i += 1;
30910 }
30911 while (v_i < 256) {
30912 self->private_data.f_palettes[1][((4 * v_i) + 0)] = 0;
30913 self->private_data.f_palettes[1][((4 * v_i) + 1)] = 0;
30914 self->private_data.f_palettes[1][((4 * v_i) + 2)] = 0;
30915 self->private_data.f_palettes[1][((4 * v_i) + 3)] = 255;
30916 v_i += 1;
30917 }
30918 } else if (self->private_impl.f_quirks[6] && ! self->private_impl.f_has_global_palette) {
30919 status = wuffs_base__make_status(wuffs_gif__error__bad_palette);
30920 goto exit;
30921 } else if (self->private_impl.f_gc_has_transparent_index) {
30922 wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_palettes[1], 1024), wuffs_base__make_slice_u8(self->private_data.f_palettes[0], 1024));
30923 } else {
30924 v_which_palette = 0;
30925 }
30926 if (self->private_impl.f_gc_has_transparent_index) {
30927 self->private_data.f_palettes[1][((4 * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 0)] = 0;
30928 self->private_data.f_palettes[1][((4 * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 1)] = 0;
30929 self->private_data.f_palettes[1][((4 * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 2)] = 0;
30930 self->private_data.f_palettes[1][((4 * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 3)] = 0;
30931 }
30932 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
30933 wuffs_base__pixel_buffer__pixel_format(a_dst),
30934 wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)),
30935 wuffs_base__utility__make_pixel_format(2198077448),
30936 wuffs_base__make_slice_u8(self->private_data.f_palettes[v_which_palette], 1024),
30937 a_blend);
30938 if ( ! wuffs_base__status__is_ok(&v_status)) {
30939 status = v_status;
30940 if (wuffs_base__status__is_error(&status)) {
30941 goto exit;
30942 } else if (wuffs_base__status__is_suspension(&status)) {
30943 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
30944 goto exit;
30945 }
30946 goto ok;
30947 }
30948 if (self->private_impl.f_previous_lzw_decode_ended_abruptly) {
Nigel Taobf9dab32021-11-18 19:19:55 +110030949 wuffs_base__ignore_status(wuffs_lzw__decoder__initialize(&self->private_data.f_lzw,
30950 sizeof (wuffs_lzw__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
Nigel Taoe360a532021-04-05 22:47:03 +100030951 }
30952 {
30953 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
30954 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30955 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30956 goto suspend;
30957 }
30958 uint8_t t_2 = *iop_a_src++;
30959 v_lw = t_2;
30960 }
30961 if (v_lw > 8) {
30962 status = wuffs_base__make_status(wuffs_gif__error__bad_literal_width);
30963 goto exit;
30964 }
30965 wuffs_lzw__decoder__set_literal_width(&self->private_data.f_lzw, ((uint32_t)(v_lw)));
30966 self->private_impl.f_previous_lzw_decode_ended_abruptly = true;
30967
Nigel Taoe360a532021-04-05 22:47:03 +100030968 ok:
30969 self->private_impl.p_decode_id_part1[0] = 0;
30970 goto exit;
30971 }
30972
30973 goto suspend;
30974 suspend:
30975 self->private_impl.p_decode_id_part1[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30976 self->private_data.s_decode_id_part1[0].v_which_palette = v_which_palette;
30977 self->private_data.s_decode_id_part1[0].v_num_palette_entries = v_num_palette_entries;
30978 self->private_data.s_decode_id_part1[0].v_i = v_i;
30979
30980 goto exit;
30981 exit:
30982 if (a_src) {
30983 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30984 }
30985
30986 return status;
30987}
30988
30989// -------- func gif.decoder.decode_id_part2
30990
30991static wuffs_base__status
30992wuffs_gif__decoder__decode_id_part2(
30993 wuffs_gif__decoder* self,
30994 wuffs_base__pixel_buffer* a_dst,
30995 wuffs_base__io_buffer* a_src,
30996 wuffs_base__slice_u8 a_workbuf) {
30997 wuffs_base__io_buffer empty_io_buffer = wuffs_base__empty_io_buffer();
30998
30999 wuffs_base__status status = wuffs_base__make_status(NULL);
31000
31001 uint64_t v_block_size = 0;
31002 bool v_need_block_size = false;
31003 uint32_t v_n_copied = 0;
31004 uint64_t v_n_compressed = 0;
31005 wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer();
31006 wuffs_base__io_buffer* v_r = &u_r;
31007 const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31008 const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31009 const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31010 const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31011 uint64_t v_mark = 0;
31012 wuffs_base__status v_lzw_status = wuffs_base__make_status(NULL);
31013 wuffs_base__status v_copy_status = wuffs_base__make_status(NULL);
31014 wuffs_base__slice_u8 v_uncompressed = {0};
31015
31016 const uint8_t* iop_a_src = NULL;
31017 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31018 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31019 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31020 if (a_src) {
31021 io0_a_src = a_src->data.ptr;
31022 io1_a_src = io0_a_src + a_src->meta.ri;
31023 iop_a_src = io1_a_src;
31024 io2_a_src = io0_a_src + a_src->meta.wi;
31025 }
31026
31027 uint32_t coro_susp_point = self->private_impl.p_decode_id_part2[0];
31028 if (coro_susp_point) {
31029 v_block_size = self->private_data.s_decode_id_part2[0].v_block_size;
31030 v_need_block_size = self->private_data.s_decode_id_part2[0].v_need_block_size;
31031 v_lzw_status = self->private_data.s_decode_id_part2[0].v_lzw_status;
31032 }
31033 switch (coro_susp_point) {
31034 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
31035
31036 v_need_block_size = true;
31037 label__outer__continue:;
31038 while (true) {
31039 if (v_need_block_size) {
31040 v_need_block_size = false;
31041 {
31042 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
31043 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31044 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31045 goto suspend;
31046 }
31047 uint64_t t_0 = *iop_a_src++;
31048 v_block_size = t_0;
31049 }
31050 }
31051 if (v_block_size == 0) {
31052 goto label__outer__break;
31053 }
31054 while (((uint64_t)(io2_a_src - iop_a_src)) == 0) {
31055 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31056 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
31057 }
31058 if (self->private_impl.f_compressed_ri == self->private_impl.f_compressed_wi) {
31059 self->private_impl.f_compressed_ri = 0;
31060 self->private_impl.f_compressed_wi = 0;
31061 }
31062 while (self->private_impl.f_compressed_wi <= 3841) {
31063 v_n_compressed = wuffs_base__u64__min(v_block_size, ((uint64_t)(io2_a_src - iop_a_src)));
31064 if (v_n_compressed <= 0) {
31065 goto label__0__break;
31066 }
31067 v_n_copied = wuffs_base__io_reader__limited_copy_u32_to_slice(
31068 &iop_a_src, io2_a_src,((uint32_t)((v_n_compressed & 4294967295))), wuffs_base__slice_u8__subslice_i(wuffs_base__make_slice_u8(self->private_data.f_compressed, 4096), self->private_impl.f_compressed_wi));
31069 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_compressed_wi, ((uint64_t)(v_n_copied)));
31070 wuffs_base__u64__sat_sub_indirect(&v_block_size, ((uint64_t)(v_n_copied)));
31071 if (v_block_size > 0) {
31072 goto label__0__break;
31073 }
31074 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
31075 v_need_block_size = true;
31076 goto label__0__break;
31077 }
31078 v_block_size = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src)));
31079 iop_a_src += 1;
31080 }
31081 label__0__break:;
31082 label__inner__continue:;
31083 while (true) {
31084 if ((self->private_impl.f_compressed_ri > self->private_impl.f_compressed_wi) || (self->private_impl.f_compressed_wi > 4096)) {
31085 status = wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_ri_wi);
31086 goto exit;
31087 }
31088 {
31089 wuffs_base__io_buffer* o_0_v_r = v_r;
31090 const uint8_t *o_0_iop_v_r = iop_v_r;
31091 const uint8_t *o_0_io0_v_r = io0_v_r;
31092 const uint8_t *o_0_io1_v_r = io1_v_r;
31093 const uint8_t *o_0_io2_v_r = io2_v_r;
31094 v_r = wuffs_base__io_reader__set(
31095 &u_r,
31096 &iop_v_r,
31097 &io0_v_r,
31098 &io1_v_r,
31099 &io2_v_r,
31100 wuffs_base__slice_u8__subslice_ij(wuffs_base__make_slice_u8(self->private_data.f_compressed,
31101 4096),
31102 self->private_impl.f_compressed_ri,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100031103 self->private_impl.f_compressed_wi),
31104 0);
Nigel Taoe360a532021-04-05 22:47:03 +100031105 v_mark = ((uint64_t)(iop_v_r - io0_v_r));
31106 {
31107 u_r.meta.ri = ((size_t)(iop_v_r - u_r.data.ptr));
31108 wuffs_base__status t_1 = wuffs_lzw__decoder__transform_io(&self->private_data.f_lzw, &empty_io_buffer, v_r, wuffs_base__utility__empty_slice_u8());
31109 v_lzw_status = t_1;
31110 iop_v_r = u_r.data.ptr + u_r.meta.ri;
31111 }
31112 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_compressed_ri, wuffs_base__io__count_since(v_mark, ((uint64_t)(iop_v_r - io0_v_r))));
31113 v_r = o_0_v_r;
31114 iop_v_r = o_0_iop_v_r;
31115 io0_v_r = o_0_io0_v_r;
31116 io1_v_r = o_0_io1_v_r;
31117 io2_v_r = o_0_io2_v_r;
31118 }
31119 v_uncompressed = wuffs_lzw__decoder__flush(&self->private_data.f_lzw);
31120 if (((uint64_t)(v_uncompressed.len)) > 0) {
31121 v_copy_status = wuffs_gif__decoder__copy_to_image_buffer(self, a_dst, v_uncompressed);
31122 if (wuffs_base__status__is_error(&v_copy_status)) {
31123 status = v_copy_status;
31124 goto exit;
31125 }
31126 }
31127 if (wuffs_base__status__is_ok(&v_lzw_status)) {
31128 self->private_impl.f_previous_lzw_decode_ended_abruptly = false;
31129 if (v_need_block_size || (v_block_size > 0)) {
31130 self->private_data.s_decode_id_part2[0].scratch = ((uint32_t)(v_block_size));
31131 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
31132 if (self->private_data.s_decode_id_part2[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
31133 self->private_data.s_decode_id_part2[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
31134 iop_a_src = io2_a_src;
31135 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31136 goto suspend;
31137 }
31138 iop_a_src += self->private_data.s_decode_id_part2[0].scratch;
31139 if (a_src) {
31140 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
31141 }
31142 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
31143 status = wuffs_gif__decoder__skip_blocks(self, a_src);
31144 if (a_src) {
31145 iop_a_src = a_src->data.ptr + a_src->meta.ri;
31146 }
31147 if (status.repr) {
31148 goto suspend;
31149 }
31150 }
31151 goto label__outer__break;
31152 } else if (v_lzw_status.repr == wuffs_base__suspension__short_read) {
31153 goto label__outer__continue;
31154 } else if (v_lzw_status.repr == wuffs_base__suspension__short_write) {
31155 goto label__inner__continue;
31156 }
31157 status = v_lzw_status;
31158 if (wuffs_base__status__is_error(&status)) {
31159 goto exit;
31160 } else if (wuffs_base__status__is_suspension(&status)) {
31161 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
31162 goto exit;
31163 }
31164 goto ok;
31165 }
31166 }
31167 label__outer__break:;
31168 self->private_impl.f_compressed_ri = 0;
31169 self->private_impl.f_compressed_wi = 0;
31170 if ((self->private_impl.f_dst_y < self->private_impl.f_frame_rect_y1) && (self->private_impl.f_frame_rect_x0 != self->private_impl.f_frame_rect_x1) && (self->private_impl.f_frame_rect_y0 != self->private_impl.f_frame_rect_y1)) {
31171 status = wuffs_base__make_status(wuffs_base__error__not_enough_data);
31172 goto exit;
31173 }
31174
Nigel Taoe360a532021-04-05 22:47:03 +100031175 ok:
31176 self->private_impl.p_decode_id_part2[0] = 0;
31177 goto exit;
31178 }
31179
31180 goto suspend;
31181 suspend:
31182 self->private_impl.p_decode_id_part2[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
31183 self->private_data.s_decode_id_part2[0].v_block_size = v_block_size;
31184 self->private_data.s_decode_id_part2[0].v_need_block_size = v_need_block_size;
31185 self->private_data.s_decode_id_part2[0].v_lzw_status = v_lzw_status;
31186
31187 goto exit;
31188 exit:
31189 if (a_src) {
31190 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
31191 }
31192
31193 return status;
31194}
31195
31196// -------- func gif.decoder.copy_to_image_buffer
31197
31198static wuffs_base__status
31199wuffs_gif__decoder__copy_to_image_buffer(
31200 wuffs_gif__decoder* self,
31201 wuffs_base__pixel_buffer* a_pb,
31202 wuffs_base__slice_u8 a_src) {
31203 wuffs_base__slice_u8 v_dst = {0};
31204 wuffs_base__slice_u8 v_src = {0};
31205 uint64_t v_width_in_bytes = 0;
31206 uint64_t v_n = 0;
31207 uint64_t v_src_ri = 0;
31208 wuffs_base__pixel_format v_pixfmt = {0};
31209 uint32_t v_bytes_per_pixel = 0;
31210 uint32_t v_bits_per_pixel = 0;
31211 wuffs_base__table_u8 v_tab = {0};
31212 uint64_t v_i = 0;
31213 uint64_t v_j = 0;
31214 uint32_t v_replicate_y0 = 0;
31215 uint32_t v_replicate_y1 = 0;
31216 wuffs_base__slice_u8 v_replicate_dst = {0};
31217 wuffs_base__slice_u8 v_replicate_src = {0};
31218
31219 v_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_pb);
31220 v_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_pixfmt);
31221 if ((v_bits_per_pixel & 7) != 0) {
31222 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
31223 }
31224 v_bytes_per_pixel = (v_bits_per_pixel >> 3);
31225 v_width_in_bytes = (((uint64_t)(self->private_impl.f_width)) * ((uint64_t)(v_bytes_per_pixel)));
31226 v_tab = wuffs_base__pixel_buffer__plane(a_pb, 0);
31227 label__0__continue:;
31228 while (v_src_ri < ((uint64_t)(a_src.len))) {
31229 v_src = wuffs_base__slice_u8__subslice_i(a_src, v_src_ri);
31230 if (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1) {
31231 if (self->private_impl.f_quirks[3]) {
31232 return wuffs_base__make_status(NULL);
31233 }
31234 return wuffs_base__make_status(wuffs_base__error__too_much_data);
31235 }
Nigel Taobf9dab32021-11-18 19:19:55 +110031236 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100031237 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
31238 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, 0);
31239 } else if (v_width_in_bytes < ((uint64_t)(v_dst.len))) {
31240 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_width_in_bytes);
31241 }
31242 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_bytes_per_pixel)));
31243 if (v_i < ((uint64_t)(v_dst.len))) {
31244 v_j = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * ((uint64_t)(v_bytes_per_pixel)));
31245 if ((v_i <= v_j) && (v_j <= ((uint64_t)(v_dst.len)))) {
31246 v_dst = wuffs_base__slice_u8__subslice_ij(v_dst, v_i, v_j);
31247 } else {
31248 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i);
31249 }
31250 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024), v_src);
31251 wuffs_base__u64__sat_add_indirect(&v_src_ri, v_n);
31252 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
31253 self->private_impl.f_dirty_max_excl_y = wuffs_base__u32__max(self->private_impl.f_dirty_max_excl_y, wuffs_base__u32__sat_add(self->private_impl.f_dst_y, 1));
31254 }
31255 if (self->private_impl.f_frame_rect_x1 <= self->private_impl.f_dst_x) {
31256 self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0;
31257 if (self->private_impl.f_interlace == 0) {
31258 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, 1);
31259 goto label__0__continue;
31260 }
31261 if ((self->private_impl.f_num_decoded_frames_value == 0) && ! self->private_impl.f_gc_has_transparent_index && (self->private_impl.f_interlace > 1)) {
Nigel Taobf9dab32021-11-18 19:19:55 +110031262 v_replicate_src = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100031263 v_replicate_y0 = wuffs_base__u32__sat_add(self->private_impl.f_dst_y, 1);
31264 v_replicate_y1 = wuffs_base__u32__sat_add(self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_COUNT[self->private_impl.f_interlace])));
31265 v_replicate_y1 = wuffs_base__u32__min(v_replicate_y1, self->private_impl.f_frame_rect_y1);
31266 while (v_replicate_y0 < v_replicate_y1) {
Nigel Taobf9dab32021-11-18 19:19:55 +110031267 v_replicate_dst = wuffs_base__table_u8__row_u32(v_tab, v_replicate_y0);
Nigel Taoe360a532021-04-05 22:47:03 +100031268 wuffs_base__slice_u8__copy_from_slice(v_replicate_dst, v_replicate_src);
31269 v_replicate_y0 += 1;
31270 }
31271 self->private_impl.f_dirty_max_excl_y = wuffs_base__u32__max(self->private_impl.f_dirty_max_excl_y, v_replicate_y1);
31272 }
31273 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_DELTA[self->private_impl.f_interlace])));
31274 while ((self->private_impl.f_interlace > 0) && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1)) {
31275#if defined(__GNUC__)
31276#pragma GCC diagnostic push
31277#pragma GCC diagnostic ignored "-Wconversion"
31278#endif
31279 self->private_impl.f_interlace -= 1;
31280#if defined(__GNUC__)
31281#pragma GCC diagnostic pop
31282#endif
31283 self->private_impl.f_dst_y = wuffs_base__u32__sat_add(self->private_impl.f_frame_rect_y0, WUFFS_GIF__INTERLACE_START[self->private_impl.f_interlace]);
31284 }
31285 goto label__0__continue;
31286 }
31287 if (((uint64_t)(a_src.len)) == v_src_ri) {
31288 goto label__0__break;
31289 } else if (((uint64_t)(a_src.len)) < v_src_ri) {
31290 return wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_ri_wi);
31291 }
31292 v_n = ((uint64_t)((self->private_impl.f_frame_rect_x1 - self->private_impl.f_dst_x)));
31293 v_n = wuffs_base__u64__min(v_n, (((uint64_t)(a_src.len)) - v_src_ri));
31294 wuffs_base__u64__sat_add_indirect(&v_src_ri, v_n);
31295 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
31296 if (self->private_impl.f_frame_rect_x1 <= self->private_impl.f_dst_x) {
31297 self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0;
31298 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_DELTA[self->private_impl.f_interlace])));
31299 while ((self->private_impl.f_interlace > 0) && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1)) {
31300#if defined(__GNUC__)
31301#pragma GCC diagnostic push
31302#pragma GCC diagnostic ignored "-Wconversion"
31303#endif
31304 self->private_impl.f_interlace -= 1;
31305#if defined(__GNUC__)
31306#pragma GCC diagnostic pop
31307#endif
31308 self->private_impl.f_dst_y = wuffs_base__u32__sat_add(self->private_impl.f_frame_rect_y0, WUFFS_GIF__INTERLACE_START[self->private_impl.f_interlace]);
31309 }
31310 goto label__0__continue;
31311 }
31312 if (v_src_ri != ((uint64_t)(a_src.len))) {
31313 return wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_ri_wi);
31314 }
31315 goto label__0__break;
31316 }
31317 label__0__break:;
31318 return wuffs_base__make_status(NULL);
31319}
31320
31321#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF)
31322
31323#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP)
31324
31325// ---------------- Status Codes Implementations
31326
31327const char wuffs_gzip__error__bad_checksum[] = "#gzip: bad checksum";
31328const char wuffs_gzip__error__bad_compression_method[] = "#gzip: bad compression method";
31329const char wuffs_gzip__error__bad_encoding_flags[] = "#gzip: bad encoding flags";
31330const char wuffs_gzip__error__bad_header[] = "#gzip: bad header";
31331
31332// ---------------- Private Consts
31333
31334// ---------------- Private Initializer Prototypes
31335
31336// ---------------- Private Function Prototypes
31337
31338// ---------------- VTables
31339
31340const wuffs_base__io_transformer__func_ptrs
31341wuffs_gzip__decoder__func_ptrs_for__wuffs_base__io_transformer = {
31342 (wuffs_base__empty_struct(*)(void*,
31343 uint32_t,
31344 bool))(&wuffs_gzip__decoder__set_quirk_enabled),
31345 (wuffs_base__status(*)(void*,
31346 wuffs_base__io_buffer*,
31347 wuffs_base__io_buffer*,
31348 wuffs_base__slice_u8))(&wuffs_gzip__decoder__transform_io),
31349 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_gzip__decoder__workbuf_len),
31350};
31351
31352// ---------------- Initializer Implementations
31353
31354wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
31355wuffs_gzip__decoder__initialize(
31356 wuffs_gzip__decoder* self,
31357 size_t sizeof_star_self,
31358 uint64_t wuffs_version,
31359 uint32_t options){
31360 if (!self) {
31361 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
31362 }
31363 if (sizeof(*self) != sizeof_star_self) {
31364 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
31365 }
31366 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
31367 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
31368 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
31369 }
31370
31371 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
31372 // The whole point of this if-check is to detect an uninitialized *self.
31373 // We disable the warning on GCC. Clang-5.0 does not have this warning.
31374#if !defined(__clang__) && defined(__GNUC__)
31375#pragma GCC diagnostic push
31376#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
31377#endif
31378 if (self->private_impl.magic != 0) {
31379 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
31380 }
31381#if !defined(__clang__) && defined(__GNUC__)
31382#pragma GCC diagnostic pop
31383#endif
31384 } else {
31385 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
31386 memset(self, 0, sizeof(*self));
31387 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
31388 } else {
31389 memset(&(self->private_impl), 0, sizeof(self->private_impl));
31390 }
31391 }
31392
31393 {
31394 wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize(
31395 &self->private_data.f_checksum, sizeof(self->private_data.f_checksum), WUFFS_VERSION, options);
31396 if (z.repr) {
31397 return z;
31398 }
31399 }
31400 {
31401 wuffs_base__status z = wuffs_deflate__decoder__initialize(
31402 &self->private_data.f_flate, sizeof(self->private_data.f_flate), WUFFS_VERSION, options);
31403 if (z.repr) {
31404 return z;
31405 }
31406 }
31407 self->private_impl.magic = WUFFS_BASE__MAGIC;
31408 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
31409 wuffs_base__io_transformer__vtable_name;
31410 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
31411 (const void*)(&wuffs_gzip__decoder__func_ptrs_for__wuffs_base__io_transformer);
31412 return wuffs_base__make_status(NULL);
31413}
31414
31415wuffs_gzip__decoder*
31416wuffs_gzip__decoder__alloc() {
31417 wuffs_gzip__decoder* x =
31418 (wuffs_gzip__decoder*)(calloc(sizeof(wuffs_gzip__decoder), 1));
31419 if (!x) {
31420 return NULL;
31421 }
31422 if (wuffs_gzip__decoder__initialize(
31423 x, sizeof(wuffs_gzip__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
31424 free(x);
31425 return NULL;
31426 }
31427 return x;
31428}
31429
31430size_t
31431sizeof__wuffs_gzip__decoder() {
31432 return sizeof(wuffs_gzip__decoder);
31433}
31434
31435// ---------------- Function Implementations
31436
31437// -------- func gzip.decoder.set_quirk_enabled
31438
31439WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
31440wuffs_gzip__decoder__set_quirk_enabled(
31441 wuffs_gzip__decoder* self,
31442 uint32_t a_quirk,
31443 bool a_enabled) {
31444 if (!self) {
31445 return wuffs_base__make_empty_struct();
31446 }
31447 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31448 return wuffs_base__make_empty_struct();
31449 }
31450
31451 if (a_quirk == 1) {
31452 self->private_impl.f_ignore_checksum = a_enabled;
31453 }
31454 return wuffs_base__make_empty_struct();
31455}
31456
31457// -------- func gzip.decoder.workbuf_len
31458
31459WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
31460wuffs_gzip__decoder__workbuf_len(
31461 const wuffs_gzip__decoder* self) {
31462 if (!self) {
31463 return wuffs_base__utility__empty_range_ii_u64();
31464 }
31465 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
31466 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
31467 return wuffs_base__utility__empty_range_ii_u64();
31468 }
31469
31470 return wuffs_base__utility__make_range_ii_u64(1, 1);
31471}
31472
31473// -------- func gzip.decoder.transform_io
31474
31475WUFFS_BASE__MAYBE_STATIC wuffs_base__status
31476wuffs_gzip__decoder__transform_io(
31477 wuffs_gzip__decoder* self,
31478 wuffs_base__io_buffer* a_dst,
31479 wuffs_base__io_buffer* a_src,
31480 wuffs_base__slice_u8 a_workbuf) {
31481 if (!self) {
31482 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
31483 }
31484 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31485 return wuffs_base__make_status(
31486 (self->private_impl.magic == WUFFS_BASE__DISABLED)
31487 ? wuffs_base__error__disabled_by_previous_error
31488 : wuffs_base__error__initialize_not_called);
31489 }
31490 if (!a_dst || !a_src) {
31491 self->private_impl.magic = WUFFS_BASE__DISABLED;
31492 return wuffs_base__make_status(wuffs_base__error__bad_argument);
31493 }
31494 if ((self->private_impl.active_coroutine != 0) &&
31495 (self->private_impl.active_coroutine != 1)) {
31496 self->private_impl.magic = WUFFS_BASE__DISABLED;
31497 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
31498 }
31499 self->private_impl.active_coroutine = 0;
31500 wuffs_base__status status = wuffs_base__make_status(NULL);
31501
31502 uint8_t v_c = 0;
31503 uint8_t v_flags = 0;
31504 uint16_t v_xlen = 0;
31505 uint64_t v_mark = 0;
31506 uint32_t v_checksum_got = 0;
31507 uint32_t v_decoded_length_got = 0;
31508 wuffs_base__status v_status = wuffs_base__make_status(NULL);
31509 uint32_t v_checksum_want = 0;
31510 uint32_t v_decoded_length_want = 0;
31511
31512 uint8_t* iop_a_dst = NULL;
31513 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31514 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31515 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31516 if (a_dst) {
31517 io0_a_dst = a_dst->data.ptr;
31518 io1_a_dst = io0_a_dst + a_dst->meta.wi;
31519 iop_a_dst = io1_a_dst;
31520 io2_a_dst = io0_a_dst + a_dst->data.len;
31521 if (a_dst->meta.closed) {
31522 io2_a_dst = iop_a_dst;
31523 }
31524 }
31525 const uint8_t* iop_a_src = NULL;
31526 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31527 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31528 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31529 if (a_src) {
31530 io0_a_src = a_src->data.ptr;
31531 io1_a_src = io0_a_src + a_src->meta.ri;
31532 iop_a_src = io1_a_src;
31533 io2_a_src = io0_a_src + a_src->meta.wi;
31534 }
31535
31536 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
31537 if (coro_susp_point) {
31538 v_flags = self->private_data.s_transform_io[0].v_flags;
31539 v_checksum_got = self->private_data.s_transform_io[0].v_checksum_got;
31540 v_decoded_length_got = self->private_data.s_transform_io[0].v_decoded_length_got;
31541 v_checksum_want = self->private_data.s_transform_io[0].v_checksum_want;
31542 }
31543 switch (coro_susp_point) {
31544 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
31545
31546 {
31547 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
31548 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31549 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31550 goto suspend;
31551 }
31552 uint8_t t_0 = *iop_a_src++;
31553 v_c = t_0;
31554 }
31555 if (v_c != 31) {
31556 status = wuffs_base__make_status(wuffs_gzip__error__bad_header);
31557 goto exit;
31558 }
31559 {
31560 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
31561 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31562 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31563 goto suspend;
31564 }
31565 uint8_t t_1 = *iop_a_src++;
31566 v_c = t_1;
31567 }
31568 if (v_c != 139) {
31569 status = wuffs_base__make_status(wuffs_gzip__error__bad_header);
31570 goto exit;
31571 }
31572 {
31573 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
31574 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31575 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31576 goto suspend;
31577 }
31578 uint8_t t_2 = *iop_a_src++;
31579 v_c = t_2;
31580 }
31581 if (v_c != 8) {
31582 status = wuffs_base__make_status(wuffs_gzip__error__bad_compression_method);
31583 goto exit;
31584 }
31585 {
31586 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
31587 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31588 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31589 goto suspend;
31590 }
31591 uint8_t t_3 = *iop_a_src++;
31592 v_flags = t_3;
31593 }
31594 self->private_data.s_transform_io[0].scratch = 6;
31595 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
31596 if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
31597 self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
31598 iop_a_src = io2_a_src;
31599 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31600 goto suspend;
31601 }
31602 iop_a_src += self->private_data.s_transform_io[0].scratch;
31603 if ((v_flags & 4) != 0) {
31604 {
31605 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
31606 uint16_t t_4;
31607 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
31608 t_4 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
31609 iop_a_src += 2;
31610 } else {
31611 self->private_data.s_transform_io[0].scratch = 0;
31612 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
31613 while (true) {
31614 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31615 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31616 goto suspend;
31617 }
31618 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
31619 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
31620 *scratch <<= 8;
31621 *scratch >>= 8;
31622 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
31623 if (num_bits_4 == 8) {
31624 t_4 = ((uint16_t)(*scratch));
31625 break;
31626 }
31627 num_bits_4 += 8;
31628 *scratch |= ((uint64_t)(num_bits_4)) << 56;
31629 }
31630 }
31631 v_xlen = t_4;
31632 }
31633 self->private_data.s_transform_io[0].scratch = ((uint32_t)(v_xlen));
31634 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
31635 if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
31636 self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
31637 iop_a_src = io2_a_src;
31638 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31639 goto suspend;
31640 }
31641 iop_a_src += self->private_data.s_transform_io[0].scratch;
31642 }
31643 if ((v_flags & 8) != 0) {
31644 while (true) {
31645 {
31646 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
31647 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31648 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31649 goto suspend;
31650 }
31651 uint8_t t_5 = *iop_a_src++;
31652 v_c = t_5;
31653 }
31654 if (v_c == 0) {
31655 goto label__0__break;
31656 }
31657 }
31658 label__0__break:;
31659 }
31660 if ((v_flags & 16) != 0) {
31661 while (true) {
31662 {
31663 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
31664 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31665 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31666 goto suspend;
31667 }
31668 uint8_t t_6 = *iop_a_src++;
31669 v_c = t_6;
31670 }
31671 if (v_c == 0) {
31672 goto label__1__break;
31673 }
31674 }
31675 label__1__break:;
31676 }
31677 if ((v_flags & 2) != 0) {
31678 self->private_data.s_transform_io[0].scratch = 2;
31679 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
31680 if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
31681 self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
31682 iop_a_src = io2_a_src;
31683 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31684 goto suspend;
31685 }
31686 iop_a_src += self->private_data.s_transform_io[0].scratch;
31687 }
31688 if ((v_flags & 224) != 0) {
31689 status = wuffs_base__make_status(wuffs_gzip__error__bad_encoding_flags);
31690 goto exit;
31691 }
31692 while (true) {
31693 v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
31694 {
31695 if (a_dst) {
31696 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
31697 }
31698 if (a_src) {
31699 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
31700 }
31701 wuffs_base__status t_7 = wuffs_deflate__decoder__transform_io(&self->private_data.f_flate, a_dst, a_src, a_workbuf);
31702 v_status = t_7;
31703 if (a_dst) {
31704 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
31705 }
31706 if (a_src) {
31707 iop_a_src = a_src->data.ptr + a_src->meta.ri;
31708 }
31709 }
31710 if ( ! self->private_impl.f_ignore_checksum) {
31711 v_checksum_got = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_checksum, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst));
31712 v_decoded_length_got += ((uint32_t)((wuffs_base__io__count_since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst))) & 4294967295)));
31713 }
31714 if (wuffs_base__status__is_ok(&v_status)) {
31715 goto label__2__break;
31716 }
31717 status = v_status;
31718 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12);
31719 }
31720 label__2__break:;
31721 {
31722 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
31723 uint32_t t_8;
31724 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
31725 t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
31726 iop_a_src += 4;
31727 } else {
31728 self->private_data.s_transform_io[0].scratch = 0;
31729 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
31730 while (true) {
31731 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31732 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31733 goto suspend;
31734 }
31735 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
31736 uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56));
31737 *scratch <<= 8;
31738 *scratch >>= 8;
31739 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8;
31740 if (num_bits_8 == 24) {
31741 t_8 = ((uint32_t)(*scratch));
31742 break;
31743 }
31744 num_bits_8 += 8;
31745 *scratch |= ((uint64_t)(num_bits_8)) << 56;
31746 }
31747 }
31748 v_checksum_want = t_8;
31749 }
31750 {
31751 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
31752 uint32_t t_9;
31753 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
31754 t_9 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
31755 iop_a_src += 4;
31756 } else {
31757 self->private_data.s_transform_io[0].scratch = 0;
31758 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
31759 while (true) {
31760 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
31761 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31762 goto suspend;
31763 }
31764 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
31765 uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56));
31766 *scratch <<= 8;
31767 *scratch >>= 8;
31768 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9;
31769 if (num_bits_9 == 24) {
31770 t_9 = ((uint32_t)(*scratch));
31771 break;
31772 }
31773 num_bits_9 += 8;
31774 *scratch |= ((uint64_t)(num_bits_9)) << 56;
31775 }
31776 }
31777 v_decoded_length_want = t_9;
31778 }
31779 if ( ! self->private_impl.f_ignore_checksum && ((v_checksum_got != v_checksum_want) || (v_decoded_length_got != v_decoded_length_want))) {
31780 status = wuffs_base__make_status(wuffs_gzip__error__bad_checksum);
31781 goto exit;
31782 }
31783
Nigel Taoe360a532021-04-05 22:47:03 +100031784 ok:
31785 self->private_impl.p_transform_io[0] = 0;
31786 goto exit;
31787 }
31788
31789 goto suspend;
31790 suspend:
31791 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
31792 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
31793 self->private_data.s_transform_io[0].v_flags = v_flags;
31794 self->private_data.s_transform_io[0].v_checksum_got = v_checksum_got;
31795 self->private_data.s_transform_io[0].v_decoded_length_got = v_decoded_length_got;
31796 self->private_data.s_transform_io[0].v_checksum_want = v_checksum_want;
31797
31798 goto exit;
31799 exit:
31800 if (a_dst) {
31801 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
31802 }
31803 if (a_src) {
31804 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
31805 }
31806
31807 if (wuffs_base__status__is_error(&status)) {
31808 self->private_impl.magic = WUFFS_BASE__DISABLED;
31809 }
31810 return status;
31811}
31812
31813#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP)
31814
31815#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON)
31816
31817// ---------------- Status Codes Implementations
31818
31819const char wuffs_json__error__bad_c0_control_code[] = "#json: bad C0 control code";
31820const char wuffs_json__error__bad_utf_8[] = "#json: bad UTF-8";
31821const char wuffs_json__error__bad_backslash_escape[] = "#json: bad backslash-escape";
31822const char wuffs_json__error__bad_input[] = "#json: bad input";
31823const char wuffs_json__error__bad_new_line_in_a_string[] = "#json: bad new-line in a string";
31824const char wuffs_json__error__bad_quirk_combination[] = "#json: bad quirk combination";
31825const char wuffs_json__error__unsupported_number_length[] = "#json: unsupported number length";
31826const char wuffs_json__error__unsupported_recursion_depth[] = "#json: unsupported recursion depth";
31827const char wuffs_json__error__internal_error_inconsistent_i_o[] = "#json: internal error: inconsistent I/O";
31828
31829// ---------------- Private Consts
31830
31831#define WUFFS_JSON__DECODER_NUMBER_LENGTH_MAX_INCL 99
31832
31833static const uint8_t
31834WUFFS_JSON__LUT_BACKSLASHES[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
31835 0, 0, 0, 0, 0, 0, 0, 0,
31836 0, 0, 3, 0, 0, 0, 0, 0,
31837 0, 0, 0, 0, 0, 0, 0, 0,
31838 0, 0, 0, 0, 0, 0, 0, 0,
31839 0, 0, 162, 0, 0, 0, 0, 5,
31840 0, 0, 0, 0, 0, 0, 0, 175,
31841 7, 0, 0, 0, 0, 0, 0, 0,
31842 0, 0, 0, 0, 0, 0, 0, 4,
31843 0, 0, 0, 0, 0, 0, 0, 0,
31844 0, 0, 0, 0, 0, 0, 0, 0,
31845 0, 0, 0, 0, 0, 0, 0, 0,
31846 0, 0, 0, 0, 220, 0, 0, 0,
31847 0, 1, 136, 0, 0, 2, 140, 0,
31848 0, 0, 0, 0, 0, 0, 138, 0,
31849 0, 0, 141, 0, 137, 0, 6, 0,
31850 0, 0, 0, 0, 0, 0, 0, 0,
31851 0, 0, 0, 0, 0, 0, 0, 0,
31852 0, 0, 0, 0, 0, 0, 0, 0,
31853 0, 0, 0, 0, 0, 0, 0, 0,
31854 0, 0, 0, 0, 0, 0, 0, 0,
31855 0, 0, 0, 0, 0, 0, 0, 0,
31856 0, 0, 0, 0, 0, 0, 0, 0,
31857 0, 0, 0, 0, 0, 0, 0, 0,
31858 0, 0, 0, 0, 0, 0, 0, 0,
31859 0, 0, 0, 0, 0, 0, 0, 0,
31860 0, 0, 0, 0, 0, 0, 0, 0,
31861 0, 0, 0, 0, 0, 0, 0, 0,
31862 0, 0, 0, 0, 0, 0, 0, 0,
31863 0, 0, 0, 0, 0, 0, 0, 0,
31864 0, 0, 0, 0, 0, 0, 0, 0,
31865 0, 0, 0, 0, 0, 0, 0, 0,
31866 0, 0, 0, 0, 0, 0, 0, 0,
31867};
31868
31869static const uint8_t
31870WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
31871 0, 1, 3, 4, 5, 6, 7, 10,
31872};
31873
31874static const uint8_t
31875WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_CHARS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
31876 0, 7, 27, 10, 63, 39, 11, 0,
31877};
31878
31879static const uint8_t
31880WUFFS_JSON__LUT_CHARS[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
31881 128, 129, 130, 131, 132, 133, 134, 135,
31882 136, 137, 138, 139, 140, 141, 142, 143,
31883 144, 145, 146, 147, 148, 149, 150, 151,
31884 152, 153, 154, 155, 156, 157, 158, 159,
31885 0, 0, 1, 0, 0, 0, 0, 0,
31886 0, 0, 0, 0, 0, 0, 0, 0,
31887 0, 0, 0, 0, 0, 0, 0, 0,
31888 0, 0, 0, 0, 0, 0, 0, 0,
31889 0, 0, 0, 0, 0, 0, 0, 0,
31890 0, 0, 0, 0, 0, 0, 0, 0,
31891 0, 0, 0, 0, 0, 0, 0, 0,
31892 0, 0, 0, 0, 2, 0, 0, 0,
31893 0, 0, 0, 0, 0, 0, 0, 0,
31894 0, 0, 0, 0, 0, 0, 0, 0,
31895 0, 0, 0, 0, 0, 0, 0, 0,
31896 0, 0, 0, 0, 0, 0, 0, 0,
31897 16, 16, 16, 16, 16, 16, 16, 16,
31898 16, 16, 16, 16, 16, 16, 16, 16,
31899 16, 16, 16, 16, 16, 16, 16, 16,
31900 16, 16, 16, 16, 16, 16, 16, 16,
31901 16, 16, 16, 16, 16, 16, 16, 16,
31902 16, 16, 16, 16, 16, 16, 16, 16,
31903 16, 16, 16, 16, 16, 16, 16, 16,
31904 16, 16, 16, 16, 16, 16, 16, 16,
31905 32, 32, 3, 3, 3, 3, 3, 3,
31906 3, 3, 3, 3, 3, 3, 3, 3,
31907 3, 3, 3, 3, 3, 3, 3, 3,
31908 3, 3, 3, 3, 3, 3, 3, 3,
31909 4, 4, 4, 4, 4, 4, 4, 4,
31910 4, 4, 4, 4, 4, 4, 4, 4,
31911 5, 5, 5, 5, 5, 32, 32, 32,
31912 32, 32, 32, 32, 32, 32, 32, 32,
31913};
31914
31915#define WUFFS_JSON__CLASS_WHITESPACE 0
31916
31917#define WUFFS_JSON__CLASS_STRING 1
31918
31919#define WUFFS_JSON__CLASS_COMMA 2
31920
31921#define WUFFS_JSON__CLASS_COLON 3
31922
31923#define WUFFS_JSON__CLASS_NUMBER 4
31924
31925#define WUFFS_JSON__CLASS_OPEN_CURLY_BRACE 5
31926
31927#define WUFFS_JSON__CLASS_CLOSE_CURLY_BRACE 6
31928
31929#define WUFFS_JSON__CLASS_OPEN_SQUARE_BRACKET 7
31930
31931#define WUFFS_JSON__CLASS_CLOSE_SQUARE_BRACKET 8
31932
31933#define WUFFS_JSON__CLASS_FALSE 9
31934
31935#define WUFFS_JSON__CLASS_TRUE 10
31936
31937#define WUFFS_JSON__CLASS_NULL_NAN_INF 11
31938
31939#define WUFFS_JSON__CLASS_COMMENT 12
31940
31941#define WUFFS_JSON__EXPECT_VALUE 7858
31942
31943#define WUFFS_JSON__EXPECT_NON_STRING_VALUE 7856
31944
31945#define WUFFS_JSON__EXPECT_STRING 4098
31946
31947#define WUFFS_JSON__EXPECT_COMMA 4100
31948
31949#define WUFFS_JSON__EXPECT_COLON 4104
31950
31951#define WUFFS_JSON__EXPECT_NUMBER 4112
31952
31953#define WUFFS_JSON__EXPECT_CLOSE_CURLY_BRACE 4160
31954
31955#define WUFFS_JSON__EXPECT_CLOSE_SQUARE_BRACKET 4352
31956
31957static const uint8_t
31958WUFFS_JSON__LUT_CLASSES[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
31959 15, 15, 15, 15, 15, 15, 15, 15,
31960 15, 0, 0, 15, 15, 0, 15, 15,
31961 15, 15, 15, 15, 15, 15, 15, 15,
31962 15, 15, 15, 15, 15, 15, 15, 15,
31963 0, 15, 1, 15, 15, 15, 15, 15,
31964 15, 15, 15, 11, 2, 4, 15, 12,
31965 4, 4, 4, 4, 4, 4, 4, 4,
31966 4, 4, 3, 15, 15, 15, 15, 15,
31967 15, 15, 15, 15, 15, 15, 15, 15,
31968 15, 11, 15, 15, 15, 15, 11, 15,
31969 15, 15, 15, 15, 15, 15, 15, 15,
31970 15, 15, 15, 7, 15, 8, 15, 15,
31971 15, 15, 15, 15, 15, 15, 9, 15,
31972 15, 11, 15, 15, 15, 15, 11, 15,
31973 15, 15, 15, 15, 10, 15, 15, 15,
31974 15, 15, 15, 5, 15, 6, 15, 15,
31975 15, 15, 15, 15, 15, 15, 15, 15,
31976 15, 15, 15, 15, 15, 15, 15, 15,
31977 15, 15, 15, 15, 15, 15, 15, 15,
31978 15, 15, 15, 15, 15, 15, 15, 15,
31979 15, 15, 15, 15, 15, 15, 15, 15,
31980 15, 15, 15, 15, 15, 15, 15, 15,
31981 15, 15, 15, 15, 15, 15, 15, 15,
31982 15, 15, 15, 15, 15, 15, 15, 15,
31983 15, 15, 15, 15, 15, 15, 15, 15,
31984 15, 15, 15, 15, 15, 15, 15, 15,
31985 15, 15, 15, 15, 15, 15, 15, 15,
31986 15, 15, 15, 15, 15, 15, 15, 15,
31987 15, 15, 15, 15, 15, 15, 15, 15,
31988 15, 15, 15, 15, 15, 15, 15, 15,
31989 15, 15, 15, 15, 15, 15, 15, 15,
31990 15, 15, 15, 15, 15, 15, 15, 15,
31991};
31992
31993static const uint8_t
31994WUFFS_JSON__LUT_DECIMAL_DIGITS[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
31995 0, 0, 0, 0, 0, 0, 0, 0,
31996 0, 0, 0, 0, 0, 0, 0, 0,
31997 0, 0, 0, 0, 0, 0, 0, 0,
31998 0, 0, 0, 0, 0, 0, 0, 0,
31999 0, 0, 0, 0, 0, 0, 0, 0,
32000 0, 0, 0, 0, 0, 0, 0, 0,
32001 128, 129, 130, 131, 132, 133, 134, 135,
32002 136, 137, 0, 0, 0, 0, 0, 0,
32003 0, 0, 0, 0, 0, 0, 0, 0,
32004 0, 0, 0, 0, 0, 0, 0, 0,
32005 0, 0, 0, 0, 0, 0, 0, 0,
32006 0, 0, 0, 0, 0, 0, 0, 0,
32007 0, 0, 0, 0, 0, 0, 0, 0,
32008 0, 0, 0, 0, 0, 0, 0, 0,
32009 0, 0, 0, 0, 0, 0, 0, 0,
32010 0, 0, 0, 0, 0, 0, 0, 0,
32011 0, 0, 0, 0, 0, 0, 0, 0,
32012 0, 0, 0, 0, 0, 0, 0, 0,
32013 0, 0, 0, 0, 0, 0, 0, 0,
32014 0, 0, 0, 0, 0, 0, 0, 0,
32015 0, 0, 0, 0, 0, 0, 0, 0,
32016 0, 0, 0, 0, 0, 0, 0, 0,
32017 0, 0, 0, 0, 0, 0, 0, 0,
32018 0, 0, 0, 0, 0, 0, 0, 0,
32019 0, 0, 0, 0, 0, 0, 0, 0,
32020 0, 0, 0, 0, 0, 0, 0, 0,
32021 0, 0, 0, 0, 0, 0, 0, 0,
32022 0, 0, 0, 0, 0, 0, 0, 0,
32023 0, 0, 0, 0, 0, 0, 0, 0,
32024 0, 0, 0, 0, 0, 0, 0, 0,
32025 0, 0, 0, 0, 0, 0, 0, 0,
32026 0, 0, 0, 0, 0, 0, 0, 0,
32027};
32028
32029static const uint8_t
32030WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
32031 0, 0, 0, 0, 0, 0, 0, 0,
32032 0, 0, 0, 0, 0, 0, 0, 0,
32033 0, 0, 0, 0, 0, 0, 0, 0,
32034 0, 0, 0, 0, 0, 0, 0, 0,
32035 0, 0, 0, 0, 0, 0, 0, 0,
32036 0, 0, 0, 0, 0, 0, 0, 0,
32037 128, 129, 130, 131, 132, 133, 134, 135,
32038 136, 137, 0, 0, 0, 0, 0, 0,
32039 0, 138, 139, 140, 141, 142, 143, 0,
32040 0, 0, 0, 0, 0, 0, 0, 0,
32041 0, 0, 0, 0, 0, 0, 0, 0,
32042 0, 0, 0, 0, 0, 0, 0, 0,
32043 0, 138, 139, 140, 141, 142, 143, 0,
32044 0, 0, 0, 0, 0, 0, 0, 0,
32045 0, 0, 0, 0, 0, 0, 0, 0,
32046 0, 0, 0, 0, 0, 0, 0, 0,
32047 0, 0, 0, 0, 0, 0, 0, 0,
32048 0, 0, 0, 0, 0, 0, 0, 0,
32049 0, 0, 0, 0, 0, 0, 0, 0,
32050 0, 0, 0, 0, 0, 0, 0, 0,
32051 0, 0, 0, 0, 0, 0, 0, 0,
32052 0, 0, 0, 0, 0, 0, 0, 0,
32053 0, 0, 0, 0, 0, 0, 0, 0,
32054 0, 0, 0, 0, 0, 0, 0, 0,
32055 0, 0, 0, 0, 0, 0, 0, 0,
32056 0, 0, 0, 0, 0, 0, 0, 0,
32057 0, 0, 0, 0, 0, 0, 0, 0,
32058 0, 0, 0, 0, 0, 0, 0, 0,
32059 0, 0, 0, 0, 0, 0, 0, 0,
32060 0, 0, 0, 0, 0, 0, 0, 0,
32061 0, 0, 0, 0, 0, 0, 0, 0,
32062 0, 0, 0, 0, 0, 0, 0, 0,
32063};
32064
32065#define WUFFS_JSON__QUIRKS_BASE 1225364480
32066
32067#define WUFFS_JSON__QUIRKS_COUNT 21
32068
32069// ---------------- Private Initializer Prototypes
32070
32071// ---------------- Private Function Prototypes
32072
32073static uint32_t
32074wuffs_json__decoder__decode_number(
32075 wuffs_json__decoder* self,
32076 wuffs_base__io_buffer* a_src);
32077
32078static uint32_t
32079wuffs_json__decoder__decode_digits(
32080 wuffs_json__decoder* self,
32081 wuffs_base__io_buffer* a_src,
32082 uint32_t a_n);
32083
32084static wuffs_base__status
32085wuffs_json__decoder__decode_leading(
32086 wuffs_json__decoder* self,
32087 wuffs_base__token_buffer* a_dst,
32088 wuffs_base__io_buffer* a_src);
32089
32090static wuffs_base__status
32091wuffs_json__decoder__decode_comment(
32092 wuffs_json__decoder* self,
32093 wuffs_base__token_buffer* a_dst,
32094 wuffs_base__io_buffer* a_src);
32095
32096static wuffs_base__status
32097wuffs_json__decoder__decode_inf_nan(
32098 wuffs_json__decoder* self,
32099 wuffs_base__token_buffer* a_dst,
32100 wuffs_base__io_buffer* a_src);
32101
32102static wuffs_base__status
32103wuffs_json__decoder__decode_trailer(
32104 wuffs_json__decoder* self,
32105 wuffs_base__token_buffer* a_dst,
32106 wuffs_base__io_buffer* a_src);
32107
32108// ---------------- VTables
32109
32110const wuffs_base__token_decoder__func_ptrs
32111wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder = {
32112 (wuffs_base__status(*)(void*,
32113 wuffs_base__token_buffer*,
32114 wuffs_base__io_buffer*,
32115 wuffs_base__slice_u8))(&wuffs_json__decoder__decode_tokens),
32116 (wuffs_base__empty_struct(*)(void*,
32117 uint32_t,
32118 bool))(&wuffs_json__decoder__set_quirk_enabled),
32119 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_json__decoder__workbuf_len),
32120};
32121
32122// ---------------- Initializer Implementations
32123
32124wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
32125wuffs_json__decoder__initialize(
32126 wuffs_json__decoder* self,
32127 size_t sizeof_star_self,
32128 uint64_t wuffs_version,
32129 uint32_t options){
32130 if (!self) {
32131 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
32132 }
32133 if (sizeof(*self) != sizeof_star_self) {
32134 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
32135 }
32136 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
32137 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
32138 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
32139 }
32140
32141 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
32142 // The whole point of this if-check is to detect an uninitialized *self.
32143 // We disable the warning on GCC. Clang-5.0 does not have this warning.
32144#if !defined(__clang__) && defined(__GNUC__)
32145#pragma GCC diagnostic push
32146#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
32147#endif
32148 if (self->private_impl.magic != 0) {
32149 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
32150 }
32151#if !defined(__clang__) && defined(__GNUC__)
32152#pragma GCC diagnostic pop
32153#endif
32154 } else {
32155 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
32156 memset(self, 0, sizeof(*self));
32157 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
32158 } else {
32159 memset(&(self->private_impl), 0, sizeof(self->private_impl));
32160 }
32161 }
32162
32163 self->private_impl.magic = WUFFS_BASE__MAGIC;
32164 self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name =
32165 wuffs_base__token_decoder__vtable_name;
32166 self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers =
32167 (const void*)(&wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder);
32168 return wuffs_base__make_status(NULL);
32169}
32170
32171wuffs_json__decoder*
32172wuffs_json__decoder__alloc() {
32173 wuffs_json__decoder* x =
32174 (wuffs_json__decoder*)(calloc(sizeof(wuffs_json__decoder), 1));
32175 if (!x) {
32176 return NULL;
32177 }
32178 if (wuffs_json__decoder__initialize(
32179 x, sizeof(wuffs_json__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
32180 free(x);
32181 return NULL;
32182 }
32183 return x;
32184}
32185
32186size_t
32187sizeof__wuffs_json__decoder() {
32188 return sizeof(wuffs_json__decoder);
32189}
32190
32191// ---------------- Function Implementations
32192
32193// -------- func json.decoder.set_quirk_enabled
32194
32195WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
32196wuffs_json__decoder__set_quirk_enabled(
32197 wuffs_json__decoder* self,
32198 uint32_t a_quirk,
32199 bool a_enabled) {
32200 if (!self) {
32201 return wuffs_base__make_empty_struct();
32202 }
32203 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
32204 return wuffs_base__make_empty_struct();
32205 }
32206
32207 if (a_quirk >= 1225364480) {
32208 a_quirk -= 1225364480;
32209 if (a_quirk < 21) {
32210 self->private_impl.f_quirks[a_quirk] = a_enabled;
32211 }
32212 }
32213 return wuffs_base__make_empty_struct();
32214}
32215
32216// -------- func json.decoder.workbuf_len
32217
32218WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
32219wuffs_json__decoder__workbuf_len(
32220 const wuffs_json__decoder* self) {
32221 if (!self) {
32222 return wuffs_base__utility__empty_range_ii_u64();
32223 }
32224 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
32225 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
32226 return wuffs_base__utility__empty_range_ii_u64();
32227 }
32228
32229 return wuffs_base__utility__empty_range_ii_u64();
32230}
32231
32232// -------- func json.decoder.decode_tokens
32233
32234WUFFS_BASE__MAYBE_STATIC wuffs_base__status
32235wuffs_json__decoder__decode_tokens(
32236 wuffs_json__decoder* self,
32237 wuffs_base__token_buffer* a_dst,
32238 wuffs_base__io_buffer* a_src,
32239 wuffs_base__slice_u8 a_workbuf) {
32240 if (!self) {
32241 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
32242 }
32243 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
32244 return wuffs_base__make_status(
32245 (self->private_impl.magic == WUFFS_BASE__DISABLED)
32246 ? wuffs_base__error__disabled_by_previous_error
32247 : wuffs_base__error__initialize_not_called);
32248 }
32249 if (!a_dst || !a_src) {
32250 self->private_impl.magic = WUFFS_BASE__DISABLED;
32251 return wuffs_base__make_status(wuffs_base__error__bad_argument);
32252 }
32253 if ((self->private_impl.active_coroutine != 0) &&
32254 (self->private_impl.active_coroutine != 1)) {
32255 self->private_impl.magic = WUFFS_BASE__DISABLED;
32256 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
32257 }
32258 self->private_impl.active_coroutine = 0;
32259 wuffs_base__status status = wuffs_base__make_status(NULL);
32260
32261 uint32_t v_vminor = 0;
32262 uint32_t v_number_length = 0;
32263 uint32_t v_number_status = 0;
32264 uint32_t v_string_length = 0;
32265 uint32_t v_whitespace_length = 0;
32266 uint32_t v_depth = 0;
32267 uint32_t v_stack_byte = 0;
32268 uint32_t v_stack_bit = 0;
32269 uint32_t v_match = 0;
32270 uint32_t v_c4 = 0;
32271 uint8_t v_c = 0;
32272 uint8_t v_backslash = 0;
32273 uint8_t v_char = 0;
32274 uint8_t v_class = 0;
32275 uint32_t v_multi_byte_utf8 = 0;
32276 uint8_t v_backslash_x_ok = 0;
32277 uint8_t v_backslash_x_value = 0;
32278 uint32_t v_backslash_x_string = 0;
32279 uint8_t v_uni4_ok = 0;
32280 uint64_t v_uni4_string = 0;
32281 uint32_t v_uni4_value = 0;
32282 uint32_t v_uni4_high_surrogate = 0;
32283 uint8_t v_uni8_ok = 0;
32284 uint64_t v_uni8_string = 0;
32285 uint32_t v_uni8_value = 0;
32286 uint32_t v_expect = 0;
32287 uint32_t v_expect_after_value = 0;
32288
32289 wuffs_base__token* iop_a_dst = NULL;
32290 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32291 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32292 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32293 if (a_dst) {
32294 io0_a_dst = a_dst->data.ptr;
32295 io1_a_dst = io0_a_dst + a_dst->meta.wi;
32296 iop_a_dst = io1_a_dst;
32297 io2_a_dst = io0_a_dst + a_dst->data.len;
32298 if (a_dst->meta.closed) {
32299 io2_a_dst = iop_a_dst;
32300 }
32301 }
32302 const uint8_t* iop_a_src = NULL;
32303 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32304 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32305 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32306 if (a_src) {
32307 io0_a_src = a_src->data.ptr;
32308 io1_a_src = io0_a_src + a_src->meta.ri;
32309 iop_a_src = io1_a_src;
32310 io2_a_src = io0_a_src + a_src->meta.wi;
32311 }
32312
32313 uint32_t coro_susp_point = self->private_impl.p_decode_tokens[0];
32314 if (coro_susp_point) {
32315 v_depth = self->private_data.s_decode_tokens[0].v_depth;
32316 v_expect = self->private_data.s_decode_tokens[0].v_expect;
32317 v_expect_after_value = self->private_data.s_decode_tokens[0].v_expect_after_value;
32318 }
32319 switch (coro_susp_point) {
32320 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32321
32322 if (self->private_impl.f_end_of_data) {
32323 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
32324 goto ok;
32325 }
32326 if (self->private_impl.f_quirks[18]) {
32327 if (self->private_impl.f_quirks[11] || self->private_impl.f_quirks[12] || self->private_impl.f_quirks[17]) {
32328 status = wuffs_base__make_status(wuffs_json__error__bad_quirk_combination);
32329 goto exit;
32330 }
32331 }
32332 if (self->private_impl.f_quirks[15] || self->private_impl.f_quirks[16]) {
32333 if (a_dst) {
32334 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
32335 }
32336 if (a_src) {
32337 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32338 }
32339 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32340 status = wuffs_json__decoder__decode_leading(self, a_dst, a_src);
32341 if (a_dst) {
32342 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
32343 }
32344 if (a_src) {
32345 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32346 }
32347 if (status.repr) {
32348 goto suspend;
32349 }
32350 }
32351 v_expect = 7858;
32352 label__outer__continue:;
32353 while (true) {
32354 while (true) {
32355 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32356 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
32357 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
32358 goto label__outer__continue;
32359 }
32360 v_whitespace_length = 0;
32361 v_c = 0;
32362 v_class = 0;
32363 while (true) {
32364 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
32365 if (v_whitespace_length > 0) {
32366 *iop_a_dst++ = wuffs_base__make_token(
32367 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32368 (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32369 v_whitespace_length = 0;
32370 }
32371 if (a_src && a_src->meta.closed) {
32372 status = wuffs_base__make_status(wuffs_json__error__bad_input);
32373 goto exit;
32374 }
32375 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32376 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
32377 v_whitespace_length = 0;
32378 goto label__outer__continue;
32379 }
32380 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
32381 v_class = WUFFS_JSON__LUT_CLASSES[v_c];
32382 if (v_class != 0) {
32383 goto label__ws__break;
32384 }
32385 iop_a_src += 1;
32386 if (v_whitespace_length >= 65534) {
32387 *iop_a_dst++ = wuffs_base__make_token(
32388 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32389 (((uint64_t)(65535)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32390 v_whitespace_length = 0;
32391 goto label__outer__continue;
32392 }
32393 v_whitespace_length += 1;
32394 }
32395 label__ws__break:;
32396 if (v_whitespace_length > 0) {
32397 *iop_a_dst++ = wuffs_base__make_token(
32398 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32399 (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32400 v_whitespace_length = 0;
32401 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32402 goto label__outer__continue;
32403 }
32404 }
32405 if (0 == (v_expect & (((uint32_t)(1)) << v_class))) {
32406 status = wuffs_base__make_status(wuffs_json__error__bad_input);
32407 goto exit;
32408 }
32409 if (v_class == 1) {
32410 *iop_a_dst++ = wuffs_base__make_token(
32411 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32412 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32413 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32414 iop_a_src += 1;
32415 label__string_loop_outer__continue:;
32416 while (true) {
32417 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32418 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
32419 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
32420 goto label__string_loop_outer__continue;
32421 }
32422 v_string_length = 0;
32423 label__string_loop_inner__continue:;
32424 while (true) {
32425 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
32426 if (v_string_length > 0) {
32427 *iop_a_dst++ = wuffs_base__make_token(
32428 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32429 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32430 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32431 v_string_length = 0;
32432 }
32433 if (a_src && a_src->meta.closed) {
32434 status = wuffs_base__make_status(wuffs_json__error__bad_input);
32435 goto exit;
32436 }
32437 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32438 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
32439 v_string_length = 0;
32440 goto label__string_loop_outer__continue;
32441 }
32442 while (((uint64_t)(io2_a_src - iop_a_src)) > 4) {
32443 v_c4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
32444 if (0 != (WUFFS_JSON__LUT_CHARS[(255 & (v_c4 >> 0))] |
32445 WUFFS_JSON__LUT_CHARS[(255 & (v_c4 >> 8))] |
32446 WUFFS_JSON__LUT_CHARS[(255 & (v_c4 >> 16))] |
32447 WUFFS_JSON__LUT_CHARS[(255 & (v_c4 >> 24))])) {
32448 goto label__0__break;
32449 }
32450 iop_a_src += 4;
32451 if (v_string_length > 65527) {
32452 *iop_a_dst++ = wuffs_base__make_token(
32453 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32454 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32455 (((uint64_t)((v_string_length + 4))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32456 v_string_length = 0;
32457 goto label__string_loop_outer__continue;
32458 }
32459 v_string_length += 4;
32460 }
32461 label__0__break:;
32462 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
32463 v_char = WUFFS_JSON__LUT_CHARS[v_c];
32464 if (v_char == 0) {
32465 iop_a_src += 1;
32466 if (v_string_length >= 65531) {
32467 *iop_a_dst++ = wuffs_base__make_token(
32468 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32469 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32470 (((uint64_t)(65532)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32471 v_string_length = 0;
32472 goto label__string_loop_outer__continue;
32473 }
32474 v_string_length += 1;
32475 goto label__string_loop_inner__continue;
32476 } else if (v_char == 1) {
32477 if (v_string_length != 0) {
32478 *iop_a_dst++ = wuffs_base__make_token(
32479 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32480 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32481 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32482 v_string_length = 0;
32483 }
32484 goto label__string_loop_outer__break;
32485 } else if (v_char == 2) {
32486 if (v_string_length > 0) {
32487 *iop_a_dst++ = wuffs_base__make_token(
32488 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32489 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32490 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32491 v_string_length = 0;
32492 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32493 goto label__string_loop_outer__continue;
32494 }
32495 }
32496 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
32497 if (a_src && a_src->meta.closed) {
32498 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
32499 goto exit;
32500 }
32501 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32502 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
32503 v_string_length = 0;
32504 v_char = 0;
32505 goto label__string_loop_outer__continue;
32506 }
32507 v_c = ((uint8_t)((wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8)));
32508 v_backslash = WUFFS_JSON__LUT_BACKSLASHES[v_c];
32509 if ((v_backslash & 128) != 0) {
32510 iop_a_src += 2;
32511 *iop_a_dst++ = wuffs_base__make_token(
32512 (((uint64_t)((6291456 | ((uint32_t)((v_backslash & 127)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32513 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32514 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32515 goto label__string_loop_outer__continue;
32516 } else if (v_backslash != 0) {
32517 if (self->private_impl.f_quirks[WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[(v_backslash & 7)]]) {
32518 iop_a_src += 2;
32519 *iop_a_dst++ = wuffs_base__make_token(
32520 (((uint64_t)((6291456 | ((uint32_t)(WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_CHARS[(v_backslash & 7)]))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32521 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32522 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32523 goto label__string_loop_outer__continue;
32524 }
32525 } else if (v_c == 117) {
32526 if (((uint64_t)(io2_a_src - iop_a_src)) < 6) {
32527 if (a_src && a_src->meta.closed) {
32528 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
32529 goto exit;
32530 }
32531 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32532 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
32533 v_string_length = 0;
32534 v_char = 0;
32535 goto label__string_loop_outer__continue;
32536 }
32537 v_uni4_string = (((uint64_t)(wuffs_base__peek_u48le__no_bounds_check(iop_a_src))) >> 16);
32538 v_uni4_value = 0;
32539 v_uni4_ok = 128;
32540 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 0))];
32541 v_uni4_ok &= v_c;
32542 v_uni4_value |= (((uint32_t)((v_c & 15))) << 12);
32543 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 8))];
32544 v_uni4_ok &= v_c;
32545 v_uni4_value |= (((uint32_t)((v_c & 15))) << 8);
32546 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 16))];
32547 v_uni4_ok &= v_c;
32548 v_uni4_value |= (((uint32_t)((v_c & 15))) << 4);
32549 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 24))];
32550 v_uni4_ok &= v_c;
32551 v_uni4_value |= (((uint32_t)((v_c & 15))) << 0);
32552 if (v_uni4_ok == 0) {
32553 } else if ((v_uni4_value < 55296) || (57343 < v_uni4_value)) {
32554 iop_a_src += 6;
32555 *iop_a_dst++ = wuffs_base__make_token(
32556 (((uint64_t)((6291456 | v_uni4_value))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32557 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32558 (((uint64_t)(6)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32559 goto label__string_loop_outer__continue;
32560 } else if (v_uni4_value >= 56320) {
32561 } else {
32562 if (((uint64_t)(io2_a_src - iop_a_src)) < 12) {
32563 if (a_src && a_src->meta.closed) {
32564 if (self->private_impl.f_quirks[20]) {
32565 iop_a_src += 6;
32566 *iop_a_dst++ = wuffs_base__make_token(
32567 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32568 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32569 (((uint64_t)(6)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32570 goto label__string_loop_outer__continue;
32571 }
32572 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
32573 goto exit;
32574 }
32575 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32576 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
32577 v_string_length = 0;
32578 v_uni4_value = 0;
32579 v_char = 0;
32580 goto label__string_loop_outer__continue;
32581 }
32582 v_uni4_string = (wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 4) >> 16);
32583 if (((255 & (v_uni4_string >> 0)) != 92) || ((255 & (v_uni4_string >> 8)) != 117)) {
32584 v_uni4_high_surrogate = 0;
32585 v_uni4_value = 0;
32586 v_uni4_ok = 0;
32587 } else {
32588 v_uni4_high_surrogate = (65536 + ((v_uni4_value - 55296) << 10));
32589 v_uni4_value = 0;
32590 v_uni4_ok = 128;
32591 v_uni4_string >>= 16;
32592 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 0))];
32593 v_uni4_ok &= v_c;
32594 v_uni4_value |= (((uint32_t)((v_c & 15))) << 12);
32595 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 8))];
32596 v_uni4_ok &= v_c;
32597 v_uni4_value |= (((uint32_t)((v_c & 15))) << 8);
32598 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 16))];
32599 v_uni4_ok &= v_c;
32600 v_uni4_value |= (((uint32_t)((v_c & 15))) << 4);
32601 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 24))];
32602 v_uni4_ok &= v_c;
32603 v_uni4_value |= (((uint32_t)((v_c & 15))) << 0);
32604 }
32605 if ((v_uni4_ok != 0) && (56320 <= v_uni4_value) && (v_uni4_value <= 57343)) {
32606 v_uni4_value -= 56320;
32607 iop_a_src += 12;
32608 *iop_a_dst++ = wuffs_base__make_token(
32609 (((uint64_t)((6291456 | v_uni4_high_surrogate | v_uni4_value))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32610 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32611 (((uint64_t)(12)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32612 goto label__string_loop_outer__continue;
32613 }
32614 }
32615 if (self->private_impl.f_quirks[20]) {
32616 if (((uint64_t)(io2_a_src - iop_a_src)) < 6) {
32617 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
32618 goto exit;
32619 }
32620 iop_a_src += 6;
32621 *iop_a_dst++ = wuffs_base__make_token(
32622 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32623 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32624 (((uint64_t)(6)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32625 goto label__string_loop_outer__continue;
32626 }
32627 } else if ((v_c == 85) && self->private_impl.f_quirks[2]) {
32628 if (((uint64_t)(io2_a_src - iop_a_src)) < 10) {
32629 if (a_src && a_src->meta.closed) {
32630 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
32631 goto exit;
32632 }
32633 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32634 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
32635 v_string_length = 0;
32636 v_char = 0;
32637 goto label__string_loop_outer__continue;
32638 }
32639 v_uni8_string = wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 2);
32640 v_uni8_value = 0;
32641 v_uni8_ok = 128;
32642 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 0))];
32643 v_uni8_ok &= v_c;
32644 v_uni8_value |= (((uint32_t)((v_c & 15))) << 28);
32645 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 8))];
32646 v_uni8_ok &= v_c;
32647 v_uni8_value |= (((uint32_t)((v_c & 15))) << 24);
32648 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 16))];
32649 v_uni8_ok &= v_c;
32650 v_uni8_value |= (((uint32_t)((v_c & 15))) << 20);
32651 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 24))];
32652 v_uni8_ok &= v_c;
32653 v_uni8_value |= (((uint32_t)((v_c & 15))) << 16);
32654 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 32))];
32655 v_uni8_ok &= v_c;
32656 v_uni8_value |= (((uint32_t)((v_c & 15))) << 12);
32657 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 40))];
32658 v_uni8_ok &= v_c;
32659 v_uni8_value |= (((uint32_t)((v_c & 15))) << 8);
32660 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 48))];
32661 v_uni8_ok &= v_c;
32662 v_uni8_value |= (((uint32_t)((v_c & 15))) << 4);
32663 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 56))];
32664 v_uni8_ok &= v_c;
32665 v_uni8_value |= (((uint32_t)((v_c & 15))) << 0);
32666 if (v_uni8_ok == 0) {
32667 } else if ((v_uni8_value < 55296) || ((57343 < v_uni8_value) && (v_uni8_value <= 1114111))) {
32668 iop_a_src += 10;
32669 *iop_a_dst++ = wuffs_base__make_token(
32670 (((uint64_t)((6291456 | (v_uni8_value & 2097151)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32671 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32672 (((uint64_t)(10)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32673 goto label__string_loop_outer__continue;
32674 } else if (self->private_impl.f_quirks[20]) {
32675 iop_a_src += 10;
32676 *iop_a_dst++ = wuffs_base__make_token(
32677 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32678 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32679 (((uint64_t)(10)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32680 goto label__string_loop_outer__continue;
32681 }
32682 } else if ((v_c == 120) && self->private_impl.f_quirks[9]) {
32683 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
32684 if (a_src && a_src->meta.closed) {
32685 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
32686 goto exit;
32687 }
32688 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32689 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
32690 v_string_length = 0;
32691 v_char = 0;
32692 goto label__string_loop_outer__continue;
32693 }
32694 v_backslash_x_string = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
32695 v_backslash_x_ok = 128;
32696 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_backslash_x_string >> 16))];
32697 v_backslash_x_ok &= v_c;
32698 v_backslash_x_value = ((uint8_t)(((v_c & 15) << 4)));
32699 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_backslash_x_string >> 24))];
32700 v_backslash_x_ok &= v_c;
32701 v_backslash_x_value = ((uint8_t)((v_backslash_x_value | (v_c & 15))));
32702 if ((v_backslash_x_ok == 0) || ((v_backslash_x_string & 65535) != 30812)) {
32703 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
32704 goto exit;
32705 }
32706 iop_a_src += 4;
32707 *iop_a_dst++ = wuffs_base__make_token(
32708 (((uint64_t)((6291456 | ((uint32_t)(v_backslash_x_value))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32709 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32710 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32711 goto label__string_loop_outer__continue;
32712 }
32713 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
32714 goto exit;
32715 } else if (v_char == 3) {
32716 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
32717 if (v_string_length > 0) {
32718 *iop_a_dst++ = wuffs_base__make_token(
32719 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32720 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32721 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32722 v_string_length = 0;
32723 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32724 goto label__string_loop_outer__continue;
32725 }
32726 }
32727 if (a_src && a_src->meta.closed) {
32728 if (self->private_impl.f_quirks[20]) {
32729 *iop_a_dst++ = wuffs_base__make_token(
32730 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32731 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32732 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32733 iop_a_src += 1;
32734 goto label__string_loop_outer__continue;
32735 }
32736 status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
32737 goto exit;
32738 }
32739 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32740 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
32741 v_string_length = 0;
32742 v_char = 0;
32743 goto label__string_loop_outer__continue;
32744 }
32745 v_multi_byte_utf8 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
32746 if ((v_multi_byte_utf8 & 49152) == 32768) {
32747 v_multi_byte_utf8 = ((1984 & ((uint32_t)(v_multi_byte_utf8 << 6))) | (63 & (v_multi_byte_utf8 >> 8)));
32748 iop_a_src += 2;
32749 if (v_string_length >= 65528) {
32750 *iop_a_dst++ = wuffs_base__make_token(
32751 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32752 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32753 (((uint64_t)((v_string_length + 2))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32754 v_string_length = 0;
32755 goto label__string_loop_outer__continue;
32756 }
32757 v_string_length += 2;
32758 goto label__string_loop_inner__continue;
32759 }
32760 } else if (v_char == 4) {
32761 if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
32762 if (v_string_length > 0) {
32763 *iop_a_dst++ = wuffs_base__make_token(
32764 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32765 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32766 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32767 v_string_length = 0;
32768 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32769 goto label__string_loop_outer__continue;
32770 }
32771 }
32772 if (a_src && a_src->meta.closed) {
32773 if (self->private_impl.f_quirks[20]) {
32774 *iop_a_dst++ = wuffs_base__make_token(
32775 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32776 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32777 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32778 iop_a_src += 1;
32779 goto label__string_loop_outer__continue;
32780 }
32781 status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
32782 goto exit;
32783 }
32784 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32785 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12);
32786 v_string_length = 0;
32787 v_char = 0;
32788 goto label__string_loop_outer__continue;
32789 }
32790 v_multi_byte_utf8 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
32791 if ((v_multi_byte_utf8 & 12632064) == 8421376) {
32792 v_multi_byte_utf8 = ((61440 & ((uint32_t)(v_multi_byte_utf8 << 12))) | (4032 & (v_multi_byte_utf8 >> 2)) | (63 & (v_multi_byte_utf8 >> 16)));
32793 if ((2047 < v_multi_byte_utf8) && ((v_multi_byte_utf8 < 55296) || (57343 < v_multi_byte_utf8))) {
32794 iop_a_src += 3;
32795 if (v_string_length >= 65528) {
32796 *iop_a_dst++ = wuffs_base__make_token(
32797 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32798 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32799 (((uint64_t)((v_string_length + 3))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32800 v_string_length = 0;
32801 goto label__string_loop_outer__continue;
32802 }
32803 v_string_length += 3;
32804 goto label__string_loop_inner__continue;
32805 }
32806 }
32807 } else if (v_char == 5) {
32808 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
32809 if (v_string_length > 0) {
32810 *iop_a_dst++ = wuffs_base__make_token(
32811 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32812 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32813 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32814 v_string_length = 0;
32815 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32816 goto label__string_loop_outer__continue;
32817 }
32818 }
32819 if (a_src && a_src->meta.closed) {
32820 if (self->private_impl.f_quirks[20]) {
32821 *iop_a_dst++ = wuffs_base__make_token(
32822 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32823 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32824 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32825 iop_a_src += 1;
32826 goto label__string_loop_outer__continue;
32827 }
32828 status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
32829 goto exit;
32830 }
32831 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32832 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(13);
32833 v_string_length = 0;
32834 v_char = 0;
32835 goto label__string_loop_outer__continue;
32836 }
32837 v_multi_byte_utf8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
32838 if ((v_multi_byte_utf8 & 3233857536) == 2155905024) {
32839 v_multi_byte_utf8 = ((1835008 & ((uint32_t)(v_multi_byte_utf8 << 18))) |
32840 (258048 & ((uint32_t)(v_multi_byte_utf8 << 4))) |
32841 (4032 & (v_multi_byte_utf8 >> 10)) |
32842 (63 & (v_multi_byte_utf8 >> 24)));
32843 if ((65535 < v_multi_byte_utf8) && (v_multi_byte_utf8 <= 1114111)) {
32844 iop_a_src += 4;
32845 if (v_string_length >= 65528) {
32846 *iop_a_dst++ = wuffs_base__make_token(
32847 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32848 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32849 (((uint64_t)((v_string_length + 4))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32850 v_string_length = 0;
32851 goto label__string_loop_outer__continue;
32852 }
32853 v_string_length += 4;
32854 goto label__string_loop_inner__continue;
32855 }
32856 }
32857 }
32858 if (v_string_length > 0) {
32859 *iop_a_dst++ = wuffs_base__make_token(
32860 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32861 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32862 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32863 v_string_length = 0;
32864 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32865 goto label__string_loop_outer__continue;
32866 }
32867 }
32868 if ((v_char & 128) != 0) {
32869 if (self->private_impl.f_quirks[0]) {
32870 *iop_a_dst++ = wuffs_base__make_token(
32871 (((uint64_t)((6291456 | ((uint32_t)((v_char & 127)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32872 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32873 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32874 iop_a_src += 1;
32875 goto label__string_loop_outer__continue;
32876 }
32877 if (v_char == 138) {
32878 status = wuffs_base__make_status(wuffs_json__error__bad_new_line_in_a_string);
32879 goto exit;
32880 }
32881 status = wuffs_base__make_status(wuffs_json__error__bad_c0_control_code);
32882 goto exit;
32883 }
32884 if (self->private_impl.f_quirks[20]) {
32885 *iop_a_dst++ = wuffs_base__make_token(
32886 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32887 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
32888 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32889 iop_a_src += 1;
32890 goto label__string_loop_outer__continue;
32891 }
32892 status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
32893 goto exit;
32894 }
32895 }
32896 label__string_loop_outer__break:;
32897 label__1__continue:;
32898 while (true) {
32899 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
32900 if (a_src && a_src->meta.closed) {
32901 status = wuffs_base__make_status(wuffs_json__error__bad_input);
32902 goto exit;
32903 }
32904 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32905 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14);
32906 goto label__1__continue;
32907 }
32908 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
32909 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
32910 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15);
32911 goto label__1__continue;
32912 }
32913 iop_a_src += 1;
32914 *iop_a_dst++ = wuffs_base__make_token(
32915 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32916 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32917 goto label__1__break;
32918 }
32919 label__1__break:;
32920 if (0 == (v_expect & (((uint32_t)(1)) << 4))) {
32921 v_expect = 4104;
32922 goto label__outer__continue;
32923 }
32924 goto label__goto_parsed_a_leaf_value__break;
32925 } else if (v_class == 2) {
32926 iop_a_src += 1;
32927 *iop_a_dst++ = wuffs_base__make_token(
32928 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32929 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32930 if (0 == (v_expect & (((uint32_t)(1)) << 8))) {
32931 if (self->private_impl.f_quirks[13]) {
32932 v_expect = 4162;
32933 } else {
32934 v_expect = 4098;
32935 }
32936 } else {
32937 if (self->private_impl.f_quirks[13]) {
32938 v_expect = 8114;
32939 } else {
32940 v_expect = 7858;
32941 }
32942 }
32943 goto label__outer__continue;
32944 } else if (v_class == 3) {
32945 iop_a_src += 1;
32946 *iop_a_dst++ = wuffs_base__make_token(
32947 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32948 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32949 v_expect = 7858;
32950 goto label__outer__continue;
32951 } else if (v_class == 4) {
32952 while (true) {
32953 if (a_src) {
32954 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32955 }
32956 v_number_length = wuffs_json__decoder__decode_number(self, a_src);
32957 if (a_src) {
32958 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32959 }
32960 v_number_status = (v_number_length >> 8);
32961 v_vminor = 10486787;
32962 if ((v_number_length & 128) != 0) {
32963 v_vminor = 10486785;
32964 }
32965 v_number_length = (v_number_length & 127);
32966 if (v_number_status == 0) {
32967 *iop_a_dst++ = wuffs_base__make_token(
32968 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
32969 (((uint64_t)(v_number_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
32970 goto label__2__break;
32971 }
32972 while (v_number_length > 0) {
32973 v_number_length -= 1;
32974 if (iop_a_src > io1_a_src) {
32975 iop_a_src--;
32976 } else {
32977 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
32978 goto exit;
32979 }
32980 }
32981 if (v_number_status == 1) {
32982 if (self->private_impl.f_quirks[14]) {
32983 if (a_dst) {
32984 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
32985 }
32986 if (a_src) {
32987 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32988 }
32989 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
32990 status = wuffs_json__decoder__decode_inf_nan(self, a_dst, a_src);
32991 if (a_dst) {
32992 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
32993 }
32994 if (a_src) {
32995 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32996 }
32997 if (status.repr) {
32998 goto suspend;
32999 }
33000 goto label__2__break;
33001 }
33002 status = wuffs_base__make_status(wuffs_json__error__bad_input);
33003 goto exit;
33004 } else if (v_number_status == 2) {
33005 status = wuffs_base__make_status(wuffs_json__error__unsupported_number_length);
33006 goto exit;
33007 } else {
33008 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33009 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17);
33010 while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
33011 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
33012 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(18);
33013 }
33014 }
33015 }
33016 label__2__break:;
33017 goto label__goto_parsed_a_leaf_value__break;
33018 } else if (v_class == 5) {
33019 v_vminor = 2113553;
33020 if (v_depth == 0) {
33021 } else if (0 != (v_expect_after_value & (((uint32_t)(1)) << 6))) {
33022 v_vminor = 2113601;
33023 } else {
33024 v_vminor = 2113569;
33025 }
33026 if (v_depth >= 1024) {
33027 status = wuffs_base__make_status(wuffs_json__error__unsupported_recursion_depth);
33028 goto exit;
33029 }
33030 v_stack_byte = (v_depth / 32);
33031 v_stack_bit = (v_depth & 31);
33032 self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(1)) << v_stack_bit);
33033 v_depth += 1;
33034 iop_a_src += 1;
33035 *iop_a_dst++ = wuffs_base__make_token(
33036 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33037 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33038 v_expect = 4162;
33039 v_expect_after_value = 4164;
33040 goto label__outer__continue;
33041 } else if (v_class == 6) {
33042 iop_a_src += 1;
33043 if (v_depth <= 1) {
33044 *iop_a_dst++ = wuffs_base__make_token(
33045 (((uint64_t)(2101314)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33046 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33047 goto label__outer__break;
33048 }
33049 v_depth -= 1;
33050 v_stack_byte = ((v_depth - 1) / 32);
33051 v_stack_bit = ((v_depth - 1) & 31);
33052 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
33053 *iop_a_dst++ = wuffs_base__make_token(
33054 (((uint64_t)(2105410)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33055 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33056 v_expect = 4356;
33057 v_expect_after_value = 4356;
33058 } else {
33059 *iop_a_dst++ = wuffs_base__make_token(
33060 (((uint64_t)(2113602)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33061 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33062 v_expect = 4164;
33063 v_expect_after_value = 4164;
33064 }
33065 goto label__outer__continue;
33066 } else if (v_class == 7) {
33067 v_vminor = 2105361;
33068 if (v_depth == 0) {
33069 } else if (0 != (v_expect_after_value & (((uint32_t)(1)) << 6))) {
33070 v_vminor = 2105409;
33071 } else {
33072 v_vminor = 2105377;
33073 }
33074 if (v_depth >= 1024) {
33075 status = wuffs_base__make_status(wuffs_json__error__unsupported_recursion_depth);
33076 goto exit;
33077 }
33078 v_stack_byte = (v_depth / 32);
33079 v_stack_bit = (v_depth & 31);
33080 self->private_data.f_stack[v_stack_byte] &= (4294967295 ^ (((uint32_t)(1)) << v_stack_bit));
33081 v_depth += 1;
33082 iop_a_src += 1;
33083 *iop_a_dst++ = wuffs_base__make_token(
33084 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33085 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33086 v_expect = 8114;
33087 v_expect_after_value = 4356;
33088 goto label__outer__continue;
33089 } else if (v_class == 8) {
33090 iop_a_src += 1;
33091 if (v_depth <= 1) {
33092 *iop_a_dst++ = wuffs_base__make_token(
33093 (((uint64_t)(2101282)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33094 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33095 goto label__outer__break;
33096 }
33097 v_depth -= 1;
33098 v_stack_byte = ((v_depth - 1) / 32);
33099 v_stack_bit = ((v_depth - 1) & 31);
33100 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
33101 *iop_a_dst++ = wuffs_base__make_token(
33102 (((uint64_t)(2105378)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33103 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33104 v_expect = 4356;
33105 v_expect_after_value = 4356;
33106 } else {
33107 *iop_a_dst++ = wuffs_base__make_token(
33108 (((uint64_t)(2113570)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33109 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33110 v_expect = 4164;
33111 v_expect_after_value = 4164;
33112 }
33113 goto label__outer__continue;
33114 } else if (v_class == 9) {
33115 v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src,111546413966853);
33116 if (v_match == 0) {
33117 *iop_a_dst++ = wuffs_base__make_token(
33118 (((uint64_t)(8388612)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33119 (((uint64_t)(5)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33120 if (((uint64_t)(io2_a_src - iop_a_src)) < 5) {
33121 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
33122 goto exit;
33123 }
33124 iop_a_src += 5;
33125 goto label__goto_parsed_a_leaf_value__break;
33126 } else if (v_match == 1) {
33127 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33128 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(19);
33129 goto label__outer__continue;
33130 }
33131 } else if (v_class == 10) {
33132 v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src,435762131972);
33133 if (v_match == 0) {
33134 *iop_a_dst++ = wuffs_base__make_token(
33135 (((uint64_t)(8388616)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33136 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33137 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
33138 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
33139 goto exit;
33140 }
33141 iop_a_src += 4;
33142 goto label__goto_parsed_a_leaf_value__break;
33143 } else if (v_match == 1) {
33144 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33145 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(20);
33146 goto label__outer__continue;
33147 }
33148 } else if (v_class == 11) {
33149 v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src,465676103172);
33150 if (v_match == 0) {
33151 *iop_a_dst++ = wuffs_base__make_token(
33152 (((uint64_t)(8388610)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33153 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33154 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
33155 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
33156 goto exit;
33157 }
33158 iop_a_src += 4;
33159 goto label__goto_parsed_a_leaf_value__break;
33160 } else if (v_match == 1) {
33161 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33162 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(21);
33163 goto label__outer__continue;
33164 }
33165 if (self->private_impl.f_quirks[14]) {
33166 if (a_dst) {
33167 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
33168 }
33169 if (a_src) {
33170 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33171 }
33172 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
33173 status = wuffs_json__decoder__decode_inf_nan(self, a_dst, a_src);
33174 if (a_dst) {
33175 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
33176 }
33177 if (a_src) {
33178 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33179 }
33180 if (status.repr) {
33181 goto suspend;
33182 }
33183 goto label__goto_parsed_a_leaf_value__break;
33184 }
33185 } else if (v_class == 12) {
33186 if (self->private_impl.f_quirks[11] || self->private_impl.f_quirks[12]) {
33187 if (a_dst) {
33188 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
33189 }
33190 if (a_src) {
33191 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33192 }
33193 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
33194 status = wuffs_json__decoder__decode_comment(self, a_dst, a_src);
33195 if (a_dst) {
33196 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
33197 }
33198 if (a_src) {
33199 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33200 }
33201 if (status.repr) {
33202 goto suspend;
33203 }
33204 if (self->private_impl.f_comment_type > 0) {
33205 goto label__outer__continue;
33206 }
33207 }
33208 }
33209 status = wuffs_base__make_status(wuffs_json__error__bad_input);
33210 goto exit;
33211 }
33212 label__goto_parsed_a_leaf_value__break:;
33213 if (v_depth == 0) {
33214 goto label__outer__break;
33215 }
33216 v_expect = v_expect_after_value;
33217 }
33218 label__outer__break:;
33219 if (self->private_impl.f_quirks[17] || self->private_impl.f_quirks[18]) {
33220 if (a_dst) {
33221 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
33222 }
33223 if (a_src) {
33224 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33225 }
33226 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
33227 status = wuffs_json__decoder__decode_trailer(self, a_dst, a_src);
33228 if (a_dst) {
33229 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
33230 }
33231 if (a_src) {
33232 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33233 }
33234 if (status.repr) {
33235 goto suspend;
33236 }
33237 }
33238 self->private_impl.f_end_of_data = true;
33239
Nigel Taoe360a532021-04-05 22:47:03 +100033240 ok:
33241 self->private_impl.p_decode_tokens[0] = 0;
33242 goto exit;
33243 }
33244
33245 goto suspend;
33246 suspend:
33247 self->private_impl.p_decode_tokens[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
33248 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
33249 self->private_data.s_decode_tokens[0].v_depth = v_depth;
33250 self->private_data.s_decode_tokens[0].v_expect = v_expect;
33251 self->private_data.s_decode_tokens[0].v_expect_after_value = v_expect_after_value;
33252
33253 goto exit;
33254 exit:
33255 if (a_dst) {
33256 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
33257 }
33258 if (a_src) {
33259 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33260 }
33261
33262 if (wuffs_base__status__is_error(&status)) {
33263 self->private_impl.magic = WUFFS_BASE__DISABLED;
33264 }
33265 return status;
33266}
33267
33268// -------- func json.decoder.decode_number
33269
33270static uint32_t
33271wuffs_json__decoder__decode_number(
33272 wuffs_json__decoder* self,
33273 wuffs_base__io_buffer* a_src) {
33274 uint8_t v_c = 0;
33275 uint32_t v_n = 0;
33276 uint32_t v_floating_point = 0;
33277
33278 const uint8_t* iop_a_src = NULL;
33279 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33280 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33281 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33282 if (a_src) {
33283 io0_a_src = a_src->data.ptr;
33284 io1_a_src = io0_a_src + a_src->meta.ri;
33285 iop_a_src = io1_a_src;
33286 io2_a_src = io0_a_src + a_src->meta.wi;
33287 }
33288
33289 while (true) {
33290 v_n = 0;
33291 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33292 if ( ! (a_src && a_src->meta.closed)) {
33293 v_n |= 768;
33294 }
33295 goto label__goto_done__break;
33296 }
33297 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33298 if (v_c != 45) {
33299 } else {
33300 v_n += 1;
33301 iop_a_src += 1;
33302 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33303 if ( ! (a_src && a_src->meta.closed)) {
33304 v_n |= 768;
33305 }
33306 v_n |= 256;
33307 goto label__goto_done__break;
33308 }
33309 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33310 }
33311 if (v_c == 48) {
33312 v_n += 1;
33313 iop_a_src += 1;
33314 } else {
33315 if (a_src) {
33316 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33317 }
33318 v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n);
33319 if (a_src) {
33320 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33321 }
33322 if (v_n > 99) {
33323 goto label__goto_done__break;
33324 }
33325 }
33326 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33327 if ( ! (a_src && a_src->meta.closed)) {
33328 v_n |= 768;
33329 }
33330 goto label__goto_done__break;
33331 }
33332 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33333 if (v_c != 46) {
33334 } else {
33335 if (v_n >= 99) {
33336 v_n |= 512;
33337 goto label__goto_done__break;
33338 }
33339 v_n += 1;
33340 iop_a_src += 1;
33341 v_floating_point = 128;
33342 if (a_src) {
33343 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33344 }
33345 v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n);
33346 if (a_src) {
33347 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33348 }
33349 if (v_n > 99) {
33350 goto label__goto_done__break;
33351 }
33352 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33353 if ( ! (a_src && a_src->meta.closed)) {
33354 v_n |= 768;
33355 }
33356 goto label__goto_done__break;
33357 }
33358 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33359 }
33360 if ((v_c != 69) && (v_c != 101)) {
33361 goto label__goto_done__break;
33362 }
33363 if (v_n >= 99) {
33364 v_n |= 512;
33365 goto label__goto_done__break;
33366 }
33367 v_n += 1;
33368 iop_a_src += 1;
33369 v_floating_point = 128;
33370 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33371 if ( ! (a_src && a_src->meta.closed)) {
33372 v_n |= 768;
33373 }
33374 v_n |= 256;
33375 goto label__goto_done__break;
33376 }
33377 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33378 if ((v_c != 43) && (v_c != 45)) {
33379 } else {
33380 if (v_n >= 99) {
33381 v_n |= 512;
33382 goto label__goto_done__break;
33383 }
33384 v_n += 1;
33385 iop_a_src += 1;
33386 }
33387 if (a_src) {
33388 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33389 }
33390 v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n);
33391 if (a_src) {
33392 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33393 }
33394 goto label__goto_done__break;
33395 }
33396 label__goto_done__break:;
33397 if (a_src) {
33398 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33399 }
33400 return (v_n | v_floating_point);
33401}
33402
33403// -------- func json.decoder.decode_digits
33404
33405static uint32_t
33406wuffs_json__decoder__decode_digits(
33407 wuffs_json__decoder* self,
33408 wuffs_base__io_buffer* a_src,
33409 uint32_t a_n) {
33410 uint8_t v_c = 0;
33411 uint32_t v_n = 0;
33412
33413 const uint8_t* iop_a_src = NULL;
33414 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33415 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33416 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33417 if (a_src) {
33418 io0_a_src = a_src->data.ptr;
33419 io1_a_src = io0_a_src + a_src->meta.ri;
33420 iop_a_src = io1_a_src;
33421 io2_a_src = io0_a_src + a_src->meta.wi;
33422 }
33423
33424 v_n = a_n;
33425 while (true) {
33426 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33427 if ( ! (a_src && a_src->meta.closed)) {
33428 v_n |= 768;
33429 }
33430 goto label__0__break;
33431 }
33432 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33433 if (0 == WUFFS_JSON__LUT_DECIMAL_DIGITS[v_c]) {
33434 goto label__0__break;
33435 }
33436 if (v_n >= 99) {
33437 v_n |= 512;
33438 goto label__0__break;
33439 }
33440 v_n += 1;
33441 iop_a_src += 1;
33442 }
33443 label__0__break:;
33444 if (v_n == a_n) {
33445 v_n |= 256;
33446 }
33447 if (a_src) {
33448 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33449 }
33450 return v_n;
33451}
33452
33453// -------- func json.decoder.decode_leading
33454
33455static wuffs_base__status
33456wuffs_json__decoder__decode_leading(
33457 wuffs_json__decoder* self,
33458 wuffs_base__token_buffer* a_dst,
33459 wuffs_base__io_buffer* a_src) {
33460 wuffs_base__status status = wuffs_base__make_status(NULL);
33461
33462 uint8_t v_c = 0;
33463 uint32_t v_u = 0;
33464
33465 wuffs_base__token* iop_a_dst = NULL;
33466 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33467 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33468 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33469 if (a_dst) {
33470 io0_a_dst = a_dst->data.ptr;
33471 io1_a_dst = io0_a_dst + a_dst->meta.wi;
33472 iop_a_dst = io1_a_dst;
33473 io2_a_dst = io0_a_dst + a_dst->data.len;
33474 if (a_dst->meta.closed) {
33475 io2_a_dst = iop_a_dst;
33476 }
33477 }
33478 const uint8_t* iop_a_src = NULL;
33479 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33480 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33481 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33482 if (a_src) {
33483 io0_a_src = a_src->data.ptr;
33484 io1_a_src = io0_a_src + a_src->meta.ri;
33485 iop_a_src = io1_a_src;
33486 io2_a_src = io0_a_src + a_src->meta.wi;
33487 }
33488
33489 uint32_t coro_susp_point = self->private_impl.p_decode_leading[0];
33490 switch (coro_susp_point) {
33491 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
33492
33493 self->private_impl.f_allow_leading_ars = self->private_impl.f_quirks[15];
33494 self->private_impl.f_allow_leading_ubom = self->private_impl.f_quirks[16];
33495 label__0__continue:;
33496 while (self->private_impl.f_allow_leading_ars || self->private_impl.f_allow_leading_ubom) {
33497 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
33498 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
33499 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
33500 goto label__0__continue;
33501 }
33502 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33503 if (a_src && a_src->meta.closed) {
33504 goto label__0__break;
33505 }
33506 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33507 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
33508 goto label__0__continue;
33509 }
33510 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33511 if ((v_c == 30) && self->private_impl.f_allow_leading_ars) {
33512 self->private_impl.f_allow_leading_ars = false;
33513 iop_a_src += 1;
33514 *iop_a_dst++ = wuffs_base__make_token(
33515 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33516 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33517 goto label__0__continue;
33518 } else if ((v_c == 239) && self->private_impl.f_allow_leading_ubom) {
33519 if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
33520 if (a_src && a_src->meta.closed) {
33521 goto label__0__break;
33522 }
33523 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33524 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
33525 goto label__0__continue;
33526 }
33527 v_u = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
33528 if (v_u == 12565487) {
33529 self->private_impl.f_allow_leading_ubom = false;
33530 iop_a_src += 3;
33531 *iop_a_dst++ = wuffs_base__make_token(
33532 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33533 (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33534 goto label__0__continue;
33535 }
33536 }
33537 goto label__0__break;
33538 }
33539 label__0__break:;
33540
Nigel Taoe360a532021-04-05 22:47:03 +100033541 ok:
33542 self->private_impl.p_decode_leading[0] = 0;
33543 goto exit;
33544 }
33545
33546 goto suspend;
33547 suspend:
33548 self->private_impl.p_decode_leading[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
33549
33550 goto exit;
33551 exit:
33552 if (a_dst) {
33553 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
33554 }
33555 if (a_src) {
33556 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33557 }
33558
33559 return status;
33560}
33561
33562// -------- func json.decoder.decode_comment
33563
33564static wuffs_base__status
33565wuffs_json__decoder__decode_comment(
33566 wuffs_json__decoder* self,
33567 wuffs_base__token_buffer* a_dst,
33568 wuffs_base__io_buffer* a_src) {
33569 wuffs_base__status status = wuffs_base__make_status(NULL);
33570
33571 uint8_t v_c = 0;
33572 uint16_t v_c2 = 0;
33573 uint32_t v_length = 0;
33574
33575 wuffs_base__token* iop_a_dst = NULL;
33576 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33577 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33578 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33579 if (a_dst) {
33580 io0_a_dst = a_dst->data.ptr;
33581 io1_a_dst = io0_a_dst + a_dst->meta.wi;
33582 iop_a_dst = io1_a_dst;
33583 io2_a_dst = io0_a_dst + a_dst->data.len;
33584 if (a_dst->meta.closed) {
33585 io2_a_dst = iop_a_dst;
33586 }
33587 }
33588 const uint8_t* iop_a_src = NULL;
33589 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33590 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33591 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33592 if (a_src) {
33593 io0_a_src = a_src->data.ptr;
33594 io1_a_src = io0_a_src + a_src->meta.ri;
33595 iop_a_src = io1_a_src;
33596 io2_a_src = io0_a_src + a_src->meta.wi;
33597 }
33598
33599 uint32_t coro_susp_point = self->private_impl.p_decode_comment[0];
33600 switch (coro_susp_point) {
33601 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
33602
33603 self->private_impl.f_comment_type = 0;
33604 label__0__continue:;
33605 while ((((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) || (((uint64_t)(io2_a_src - iop_a_src)) <= 1)) {
33606 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
33607 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
33608 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
33609 goto label__0__continue;
33610 }
33611 if (a_src && a_src->meta.closed) {
33612 status = wuffs_base__make_status(NULL);
33613 goto ok;
33614 }
33615 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33616 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
33617 }
33618 v_c2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
33619 if ((v_c2 == 10799) && self->private_impl.f_quirks[11]) {
33620 iop_a_src += 2;
33621 v_length = 2;
33622 label__comment_block__continue:;
33623 while (true) {
33624 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
33625 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
33626 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
33627 v_length = 0;
33628 goto label__comment_block__continue;
33629 }
33630 while (true) {
33631 if (((uint64_t)(io2_a_src - iop_a_src)) <= 1) {
33632 if (v_length > 0) {
33633 *iop_a_dst++ = wuffs_base__make_token(
33634 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33635 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
33636 (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33637 }
33638 if (a_src && a_src->meta.closed) {
33639 status = wuffs_base__make_status(wuffs_json__error__bad_input);
33640 goto exit;
33641 }
33642 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33643 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
33644 v_length = 0;
33645 goto label__comment_block__continue;
33646 }
33647 v_c2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
33648 if (v_c2 == 12074) {
33649 iop_a_src += 2;
33650 *iop_a_dst++ = wuffs_base__make_token(
33651 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33652 (((uint64_t)((v_length + 2))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33653 self->private_impl.f_comment_type = 1;
33654 status = wuffs_base__make_status(NULL);
33655 goto ok;
33656 }
33657 iop_a_src += 1;
33658 if (v_length >= 65533) {
33659 *iop_a_dst++ = wuffs_base__make_token(
33660 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33661 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
33662 (((uint64_t)((v_length + 1))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33663 v_length = 0;
33664 goto label__comment_block__continue;
33665 }
33666 v_length += 1;
33667 }
33668 }
33669 } else if ((v_c2 == 12079) && self->private_impl.f_quirks[12]) {
33670 iop_a_src += 2;
33671 v_length = 2;
33672 label__comment_line__continue:;
33673 while (true) {
33674 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
33675 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
33676 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
33677 v_length = 0;
33678 goto label__comment_line__continue;
33679 }
33680 while (true) {
33681 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
Nigel Tao600cd962021-07-20 14:22:02 +100033682 if (a_src && a_src->meta.closed) {
33683 *iop_a_dst++ = wuffs_base__make_token(
33684 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33685 (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33686 self->private_impl.f_comment_type = 2;
33687 status = wuffs_base__make_status(NULL);
33688 goto ok;
33689 } else if (v_length > 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100033690 *iop_a_dst++ = wuffs_base__make_token(
33691 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33692 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
33693 (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33694 }
Nigel Taoe360a532021-04-05 22:47:03 +100033695 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33696 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
33697 v_length = 0;
33698 goto label__comment_line__continue;
33699 }
33700 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33701 if (v_c == 10) {
Nigel Taoe360a532021-04-05 22:47:03 +100033702 *iop_a_dst++ = wuffs_base__make_token(
33703 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
Nigel Tao600cd962021-07-20 14:22:02 +100033704 (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
Nigel Taoe360a532021-04-05 22:47:03 +100033705 self->private_impl.f_comment_type = 2;
33706 status = wuffs_base__make_status(NULL);
33707 goto ok;
33708 }
33709 iop_a_src += 1;
33710 if (v_length >= 65533) {
33711 *iop_a_dst++ = wuffs_base__make_token(
33712 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33713 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
33714 (((uint64_t)((v_length + 1))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33715 v_length = 0;
33716 goto label__comment_line__continue;
33717 }
33718 v_length += 1;
33719 }
33720 }
33721 }
33722
Nigel Taoe360a532021-04-05 22:47:03 +100033723 ok:
33724 self->private_impl.p_decode_comment[0] = 0;
33725 goto exit;
33726 }
33727
33728 goto suspend;
33729 suspend:
33730 self->private_impl.p_decode_comment[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
33731
33732 goto exit;
33733 exit:
33734 if (a_dst) {
33735 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
33736 }
33737 if (a_src) {
33738 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33739 }
33740
33741 return status;
33742}
33743
33744// -------- func json.decoder.decode_inf_nan
33745
33746static wuffs_base__status
33747wuffs_json__decoder__decode_inf_nan(
33748 wuffs_json__decoder* self,
33749 wuffs_base__token_buffer* a_dst,
33750 wuffs_base__io_buffer* a_src) {
33751 wuffs_base__status status = wuffs_base__make_status(NULL);
33752
33753 uint32_t v_c4 = 0;
33754 uint32_t v_neg = 0;
33755
33756 wuffs_base__token* iop_a_dst = NULL;
33757 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33758 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33759 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33760 if (a_dst) {
33761 io0_a_dst = a_dst->data.ptr;
33762 io1_a_dst = io0_a_dst + a_dst->meta.wi;
33763 iop_a_dst = io1_a_dst;
33764 io2_a_dst = io0_a_dst + a_dst->data.len;
33765 if (a_dst->meta.closed) {
33766 io2_a_dst = iop_a_dst;
33767 }
33768 }
33769 const uint8_t* iop_a_src = NULL;
33770 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33771 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33772 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33773 if (a_src) {
33774 io0_a_src = a_src->data.ptr;
33775 io1_a_src = io0_a_src + a_src->meta.ri;
33776 iop_a_src = io1_a_src;
33777 io2_a_src = io0_a_src + a_src->meta.wi;
33778 }
33779
33780 uint32_t coro_susp_point = self->private_impl.p_decode_inf_nan[0];
33781 if (coro_susp_point) {
33782 v_neg = self->private_data.s_decode_inf_nan[0].v_neg;
33783 }
33784 switch (coro_susp_point) {
33785 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
33786
33787 label__0__continue:;
33788 while (true) {
33789 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
33790 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
33791 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
33792 goto label__0__continue;
33793 }
33794 if (((uint64_t)(io2_a_src - iop_a_src)) <= 2) {
33795 if (a_src && a_src->meta.closed) {
33796 status = wuffs_base__make_status(wuffs_json__error__bad_input);
33797 goto exit;
33798 }
33799 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33800 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
33801 goto label__0__continue;
33802 }
33803 v_c4 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
33804 if ((v_c4 | 2105376) == 6712937) {
33805 if (((uint64_t)(io2_a_src - iop_a_src)) > 7) {
33806 if ((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) | 2314885530818453536) == 8751735898823356009) {
33807 *iop_a_dst++ = wuffs_base__make_token(
33808 (((uint64_t)(10485792)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33809 (((uint64_t)(8)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33810 iop_a_src += 8;
33811 status = wuffs_base__make_status(NULL);
33812 goto ok;
33813 }
33814 } else if ( ! (a_src && a_src->meta.closed)) {
33815 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33816 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
33817 goto label__0__continue;
33818 }
33819 *iop_a_dst++ = wuffs_base__make_token(
33820 (((uint64_t)(10485792)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33821 (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33822 iop_a_src += 3;
33823 status = wuffs_base__make_status(NULL);
33824 goto ok;
33825 } else if ((v_c4 | 2105376) == 7233902) {
33826 *iop_a_dst++ = wuffs_base__make_token(
33827 (((uint64_t)(10485888)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33828 (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33829 iop_a_src += 3;
33830 status = wuffs_base__make_status(NULL);
33831 goto ok;
33832 } else if ((v_c4 & 255) == 43) {
33833 v_neg = 0;
33834 } else if ((v_c4 & 255) == 45) {
33835 v_neg = 1;
33836 } else {
33837 status = wuffs_base__make_status(wuffs_json__error__bad_input);
33838 goto exit;
33839 }
33840 if (((uint64_t)(io2_a_src - iop_a_src)) <= 3) {
33841 if (a_src && a_src->meta.closed) {
33842 status = wuffs_base__make_status(wuffs_json__error__bad_input);
33843 goto exit;
33844 }
33845 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33846 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
33847 goto label__0__continue;
33848 }
33849 v_c4 = (wuffs_base__peek_u32le__no_bounds_check(iop_a_src) >> 8);
33850 if ((v_c4 | 2105376) == 6712937) {
33851 if (((uint64_t)(io2_a_src - iop_a_src)) > 8) {
33852 if ((wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 1) | 2314885530818453536) == 8751735898823356009) {
33853 *iop_a_dst++ = wuffs_base__make_token(
33854 (((uint64_t)((10485760 | (((uint32_t)(32)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33855 (((uint64_t)(9)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33856 iop_a_src += 9;
33857 status = wuffs_base__make_status(NULL);
33858 goto ok;
33859 }
33860 } else if ( ! (a_src && a_src->meta.closed)) {
33861 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33862 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
33863 goto label__0__continue;
33864 }
33865 *iop_a_dst++ = wuffs_base__make_token(
33866 (((uint64_t)((10485760 | (((uint32_t)(32)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33867 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33868 iop_a_src += 4;
33869 status = wuffs_base__make_status(NULL);
33870 goto ok;
33871 } else if ((v_c4 | 2105376) == 7233902) {
33872 *iop_a_dst++ = wuffs_base__make_token(
33873 (((uint64_t)((10485760 | (((uint32_t)(128)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33874 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33875 iop_a_src += 4;
33876 status = wuffs_base__make_status(NULL);
33877 goto ok;
33878 }
33879 status = wuffs_base__make_status(wuffs_json__error__bad_input);
33880 goto exit;
33881 }
33882
Nigel Taoe360a532021-04-05 22:47:03 +100033883 ok:
33884 self->private_impl.p_decode_inf_nan[0] = 0;
33885 goto exit;
33886 }
33887
33888 goto suspend;
33889 suspend:
33890 self->private_impl.p_decode_inf_nan[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
33891 self->private_data.s_decode_inf_nan[0].v_neg = v_neg;
33892
33893 goto exit;
33894 exit:
33895 if (a_dst) {
33896 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
33897 }
33898 if (a_src) {
33899 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33900 }
33901
33902 return status;
33903}
33904
33905// -------- func json.decoder.decode_trailer
33906
33907static wuffs_base__status
33908wuffs_json__decoder__decode_trailer(
33909 wuffs_json__decoder* self,
33910 wuffs_base__token_buffer* a_dst,
33911 wuffs_base__io_buffer* a_src) {
33912 wuffs_base__status status = wuffs_base__make_status(NULL);
33913
33914 uint8_t v_c = 0;
33915 uint32_t v_whitespace_length = 0;
33916
33917 wuffs_base__token* iop_a_dst = NULL;
33918 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33919 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33920 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33921 if (a_dst) {
33922 io0_a_dst = a_dst->data.ptr;
33923 io1_a_dst = io0_a_dst + a_dst->meta.wi;
33924 iop_a_dst = io1_a_dst;
33925 io2_a_dst = io0_a_dst + a_dst->data.len;
33926 if (a_dst->meta.closed) {
33927 io2_a_dst = iop_a_dst;
33928 }
33929 }
33930 const uint8_t* iop_a_src = NULL;
33931 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33932 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33933 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33934 if (a_src) {
33935 io0_a_src = a_src->data.ptr;
33936 io1_a_src = io0_a_src + a_src->meta.ri;
33937 iop_a_src = io1_a_src;
33938 io2_a_src = io0_a_src + a_src->meta.wi;
33939 }
33940
33941 uint32_t coro_susp_point = self->private_impl.p_decode_trailer[0];
33942 switch (coro_susp_point) {
33943 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
33944
33945 if (self->private_impl.f_quirks[18]) {
33946 self->private_impl.f_trailer_stop = 10;
33947 } else {
33948 self->private_impl.f_trailer_stop = 0;
33949 }
33950 label__outer__continue:;
33951 while (true) {
33952 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
33953 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
33954 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
33955 v_whitespace_length = 0;
33956 goto label__outer__continue;
33957 }
33958 while (true) {
33959 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33960 if (v_whitespace_length > 0) {
33961 *iop_a_dst++ = wuffs_base__make_token(
33962 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33963 (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33964 v_whitespace_length = 0;
33965 }
33966 if (a_src && a_src->meta.closed) {
33967 goto label__outer__break;
33968 }
33969 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33970 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
33971 v_whitespace_length = 0;
33972 goto label__outer__continue;
33973 }
33974 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
33975 if (WUFFS_JSON__LUT_CLASSES[v_c] != 0) {
33976 if (v_whitespace_length > 0) {
33977 *iop_a_dst++ = wuffs_base__make_token(
33978 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
33979 (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
33980 v_whitespace_length = 0;
33981 }
33982 if (self->private_impl.f_trailer_stop > 0) {
33983 status = wuffs_base__make_status(wuffs_json__error__bad_input);
33984 goto exit;
33985 }
33986 if (a_dst) {
33987 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
33988 }
33989 if (a_src) {
33990 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33991 }
33992 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
33993 status = wuffs_json__decoder__decode_comment(self, a_dst, a_src);
33994 if (a_dst) {
33995 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
33996 }
33997 if (a_src) {
33998 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33999 }
34000 if (status.repr) {
34001 goto suspend;
34002 }
34003 v_c = 0;
34004 v_whitespace_length = 0;
34005 if (self->private_impl.f_comment_type > 0) {
34006 goto label__outer__continue;
34007 }
34008 status = wuffs_base__make_status(NULL);
34009 goto ok;
34010 }
34011 iop_a_src += 1;
34012 if ((v_whitespace_length >= 65534) || (v_c == self->private_impl.f_trailer_stop)) {
34013 *iop_a_dst++ = wuffs_base__make_token(
34014 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34015 (((uint64_t)((v_whitespace_length + 1))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34016 v_whitespace_length = 0;
34017 if (v_c == self->private_impl.f_trailer_stop) {
34018 status = wuffs_base__make_status(NULL);
34019 goto ok;
34020 }
34021 goto label__outer__continue;
34022 }
34023 v_whitespace_length += 1;
34024 }
34025 }
34026 label__outer__break:;
34027
Nigel Taoe360a532021-04-05 22:47:03 +100034028 ok:
34029 self->private_impl.p_decode_trailer[0] = 0;
34030 goto exit;
34031 }
34032
34033 goto suspend;
34034 suspend:
34035 self->private_impl.p_decode_trailer[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
34036
34037 goto exit;
34038 exit:
34039 if (a_dst) {
34040 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
34041 }
34042 if (a_src) {
34043 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
34044 }
34045
34046 return status;
34047}
34048
34049#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON)
34050
34051#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE)
34052
34053// ---------------- Status Codes Implementations
34054
34055const char wuffs_nie__error__bad_header[] = "#nie: bad header";
34056const char wuffs_nie__error__unsupported_nie_file[] = "#nie: unsupported NIE file";
34057const char wuffs_nie__note__internal_note_short_read[] = "@nie: internal note: short read";
34058
34059// ---------------- Private Consts
34060
34061// ---------------- Private Initializer Prototypes
34062
34063// ---------------- Private Function Prototypes
34064
34065static wuffs_base__status
34066wuffs_nie__decoder__swizzle(
34067 wuffs_nie__decoder* self,
34068 wuffs_base__pixel_buffer* a_dst,
34069 wuffs_base__io_buffer* a_src);
34070
34071// ---------------- VTables
34072
34073const wuffs_base__image_decoder__func_ptrs
34074wuffs_nie__decoder__func_ptrs_for__wuffs_base__image_decoder = {
34075 (wuffs_base__status(*)(void*,
34076 wuffs_base__pixel_buffer*,
34077 wuffs_base__io_buffer*,
34078 wuffs_base__pixel_blend,
34079 wuffs_base__slice_u8,
34080 wuffs_base__decode_frame_options*))(&wuffs_nie__decoder__decode_frame),
34081 (wuffs_base__status(*)(void*,
34082 wuffs_base__frame_config*,
34083 wuffs_base__io_buffer*))(&wuffs_nie__decoder__decode_frame_config),
34084 (wuffs_base__status(*)(void*,
34085 wuffs_base__image_config*,
34086 wuffs_base__io_buffer*))(&wuffs_nie__decoder__decode_image_config),
34087 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_nie__decoder__frame_dirty_rect),
34088 (uint32_t(*)(const void*))(&wuffs_nie__decoder__num_animation_loops),
34089 (uint64_t(*)(const void*))(&wuffs_nie__decoder__num_decoded_frame_configs),
34090 (uint64_t(*)(const void*))(&wuffs_nie__decoder__num_decoded_frames),
34091 (wuffs_base__status(*)(void*,
34092 uint64_t,
34093 uint64_t))(&wuffs_nie__decoder__restart_frame),
34094 (wuffs_base__empty_struct(*)(void*,
34095 uint32_t,
34096 bool))(&wuffs_nie__decoder__set_quirk_enabled),
34097 (wuffs_base__empty_struct(*)(void*,
34098 uint32_t,
34099 bool))(&wuffs_nie__decoder__set_report_metadata),
34100 (wuffs_base__status(*)(void*,
34101 wuffs_base__io_buffer*,
34102 wuffs_base__more_information*,
34103 wuffs_base__io_buffer*))(&wuffs_nie__decoder__tell_me_more),
34104 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_nie__decoder__workbuf_len),
34105};
34106
34107// ---------------- Initializer Implementations
34108
34109wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
34110wuffs_nie__decoder__initialize(
34111 wuffs_nie__decoder* self,
34112 size_t sizeof_star_self,
34113 uint64_t wuffs_version,
34114 uint32_t options){
34115 if (!self) {
34116 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34117 }
34118 if (sizeof(*self) != sizeof_star_self) {
34119 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
34120 }
34121 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
34122 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
34123 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
34124 }
34125
34126 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
34127 // The whole point of this if-check is to detect an uninitialized *self.
34128 // We disable the warning on GCC. Clang-5.0 does not have this warning.
34129#if !defined(__clang__) && defined(__GNUC__)
34130#pragma GCC diagnostic push
34131#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
34132#endif
34133 if (self->private_impl.magic != 0) {
34134 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
34135 }
34136#if !defined(__clang__) && defined(__GNUC__)
34137#pragma GCC diagnostic pop
34138#endif
34139 } else {
34140 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
34141 memset(self, 0, sizeof(*self));
34142 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
34143 } else {
34144 memset(&(self->private_impl), 0, sizeof(self->private_impl));
34145 }
34146 }
34147
34148 self->private_impl.magic = WUFFS_BASE__MAGIC;
34149 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
34150 wuffs_base__image_decoder__vtable_name;
34151 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
34152 (const void*)(&wuffs_nie__decoder__func_ptrs_for__wuffs_base__image_decoder);
34153 return wuffs_base__make_status(NULL);
34154}
34155
34156wuffs_nie__decoder*
34157wuffs_nie__decoder__alloc() {
34158 wuffs_nie__decoder* x =
34159 (wuffs_nie__decoder*)(calloc(sizeof(wuffs_nie__decoder), 1));
34160 if (!x) {
34161 return NULL;
34162 }
34163 if (wuffs_nie__decoder__initialize(
34164 x, sizeof(wuffs_nie__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
34165 free(x);
34166 return NULL;
34167 }
34168 return x;
34169}
34170
34171size_t
34172sizeof__wuffs_nie__decoder() {
34173 return sizeof(wuffs_nie__decoder);
34174}
34175
34176// ---------------- Function Implementations
34177
34178// -------- func nie.decoder.set_quirk_enabled
34179
34180WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
34181wuffs_nie__decoder__set_quirk_enabled(
34182 wuffs_nie__decoder* self,
34183 uint32_t a_quirk,
34184 bool a_enabled) {
34185 return wuffs_base__make_empty_struct();
34186}
34187
34188// -------- func nie.decoder.decode_image_config
34189
34190WUFFS_BASE__MAYBE_STATIC wuffs_base__status
34191wuffs_nie__decoder__decode_image_config(
34192 wuffs_nie__decoder* self,
34193 wuffs_base__image_config* a_dst,
34194 wuffs_base__io_buffer* a_src) {
34195 if (!self) {
34196 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34197 }
34198 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
34199 return wuffs_base__make_status(
34200 (self->private_impl.magic == WUFFS_BASE__DISABLED)
34201 ? wuffs_base__error__disabled_by_previous_error
34202 : wuffs_base__error__initialize_not_called);
34203 }
34204 if (!a_src) {
34205 self->private_impl.magic = WUFFS_BASE__DISABLED;
34206 return wuffs_base__make_status(wuffs_base__error__bad_argument);
34207 }
34208 if ((self->private_impl.active_coroutine != 0) &&
34209 (self->private_impl.active_coroutine != 1)) {
34210 self->private_impl.magic = WUFFS_BASE__DISABLED;
34211 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
34212 }
34213 self->private_impl.active_coroutine = 0;
34214 wuffs_base__status status = wuffs_base__make_status(NULL);
34215
34216 uint32_t v_a = 0;
34217
34218 const uint8_t* iop_a_src = NULL;
34219 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34220 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34221 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34222 if (a_src) {
34223 io0_a_src = a_src->data.ptr;
34224 io1_a_src = io0_a_src + a_src->meta.ri;
34225 iop_a_src = io1_a_src;
34226 io2_a_src = io0_a_src + a_src->meta.wi;
34227 }
34228
34229 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
34230 switch (coro_susp_point) {
34231 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
34232
34233 if (self->private_impl.f_call_sequence != 0) {
34234 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
34235 goto exit;
34236 }
34237 {
34238 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
34239 uint32_t t_0;
34240 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
34241 t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
34242 iop_a_src += 4;
34243 } else {
34244 self->private_data.s_decode_image_config[0].scratch = 0;
34245 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
34246 while (true) {
34247 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34248 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34249 goto suspend;
34250 }
34251 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
34252 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
34253 *scratch <<= 8;
34254 *scratch >>= 8;
34255 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
34256 if (num_bits_0 == 24) {
34257 t_0 = ((uint32_t)(*scratch));
34258 break;
34259 }
34260 num_bits_0 += 8;
34261 *scratch |= ((uint64_t)(num_bits_0)) << 56;
34262 }
34263 }
34264 v_a = t_0;
34265 }
34266 if (v_a != 1169146734) {
34267 status = wuffs_base__make_status(wuffs_nie__error__bad_header);
34268 goto exit;
34269 }
34270 {
34271 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
34272 uint32_t t_1;
34273 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
34274 t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
34275 iop_a_src += 4;
34276 } else {
34277 self->private_data.s_decode_image_config[0].scratch = 0;
34278 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
34279 while (true) {
34280 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34281 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34282 goto suspend;
34283 }
34284 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
34285 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
34286 *scratch <<= 8;
34287 *scratch >>= 8;
34288 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
34289 if (num_bits_1 == 24) {
34290 t_1 = ((uint32_t)(*scratch));
34291 break;
34292 }
34293 num_bits_1 += 8;
34294 *scratch |= ((uint64_t)(num_bits_1)) << 56;
34295 }
34296 }
34297 v_a = t_1;
34298 }
34299 if (v_a == 879649535) {
34300 self->private_impl.f_pixfmt = 2164295816;
34301 } else if (v_a == 946758399) {
34302 self->private_impl.f_pixfmt = 2164308923;
34303 } else if (v_a == 879780607) {
34304 status = wuffs_base__make_status(wuffs_nie__error__unsupported_nie_file);
34305 goto exit;
34306 } else if (v_a == 946889471) {
34307 status = wuffs_base__make_status(wuffs_nie__error__unsupported_nie_file);
34308 goto exit;
34309 } else {
34310 status = wuffs_base__make_status(wuffs_nie__error__bad_header);
34311 goto exit;
34312 }
34313 {
34314 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
34315 uint32_t t_2;
34316 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
34317 t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
34318 iop_a_src += 4;
34319 } else {
34320 self->private_data.s_decode_image_config[0].scratch = 0;
34321 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
34322 while (true) {
34323 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34324 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34325 goto suspend;
34326 }
34327 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
34328 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
34329 *scratch <<= 8;
34330 *scratch >>= 8;
34331 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
34332 if (num_bits_2 == 24) {
34333 t_2 = ((uint32_t)(*scratch));
34334 break;
34335 }
34336 num_bits_2 += 8;
34337 *scratch |= ((uint64_t)(num_bits_2)) << 56;
34338 }
34339 }
34340 v_a = t_2;
34341 }
34342 if (v_a >= 2147483648) {
34343 status = wuffs_base__make_status(wuffs_nie__error__bad_header);
34344 goto exit;
34345 }
34346 self->private_impl.f_width = v_a;
34347 {
34348 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
34349 uint32_t t_3;
34350 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
34351 t_3 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
34352 iop_a_src += 4;
34353 } else {
34354 self->private_data.s_decode_image_config[0].scratch = 0;
34355 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
34356 while (true) {
34357 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34358 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34359 goto suspend;
34360 }
34361 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
34362 uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
34363 *scratch <<= 8;
34364 *scratch >>= 8;
34365 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
34366 if (num_bits_3 == 24) {
34367 t_3 = ((uint32_t)(*scratch));
34368 break;
34369 }
34370 num_bits_3 += 8;
34371 *scratch |= ((uint64_t)(num_bits_3)) << 56;
34372 }
34373 }
34374 v_a = t_3;
34375 }
34376 if (v_a >= 2147483648) {
34377 status = wuffs_base__make_status(wuffs_nie__error__bad_header);
34378 goto exit;
34379 }
34380 self->private_impl.f_height = v_a;
34381 if (a_dst != NULL) {
34382 wuffs_base__image_config__set(
34383 a_dst,
34384 self->private_impl.f_pixfmt,
34385 0,
34386 self->private_impl.f_width,
34387 self->private_impl.f_height,
34388 16,
34389 false);
34390 }
34391 self->private_impl.f_call_sequence = 3;
34392
34393 goto ok;
34394 ok:
34395 self->private_impl.p_decode_image_config[0] = 0;
34396 goto exit;
34397 }
34398
34399 goto suspend;
34400 suspend:
34401 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
34402 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
34403
34404 goto exit;
34405 exit:
34406 if (a_src) {
34407 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
34408 }
34409
34410 if (wuffs_base__status__is_error(&status)) {
34411 self->private_impl.magic = WUFFS_BASE__DISABLED;
34412 }
34413 return status;
34414}
34415
34416// -------- func nie.decoder.decode_frame_config
34417
34418WUFFS_BASE__MAYBE_STATIC wuffs_base__status
34419wuffs_nie__decoder__decode_frame_config(
34420 wuffs_nie__decoder* self,
34421 wuffs_base__frame_config* a_dst,
34422 wuffs_base__io_buffer* a_src) {
34423 if (!self) {
34424 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34425 }
34426 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
34427 return wuffs_base__make_status(
34428 (self->private_impl.magic == WUFFS_BASE__DISABLED)
34429 ? wuffs_base__error__disabled_by_previous_error
34430 : wuffs_base__error__initialize_not_called);
34431 }
34432 if (!a_src) {
34433 self->private_impl.magic = WUFFS_BASE__DISABLED;
34434 return wuffs_base__make_status(wuffs_base__error__bad_argument);
34435 }
34436 if ((self->private_impl.active_coroutine != 0) &&
34437 (self->private_impl.active_coroutine != 2)) {
34438 self->private_impl.magic = WUFFS_BASE__DISABLED;
34439 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
34440 }
34441 self->private_impl.active_coroutine = 0;
34442 wuffs_base__status status = wuffs_base__make_status(NULL);
34443
34444 const uint8_t* iop_a_src = NULL;
34445 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34446 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34447 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34448 if (a_src) {
34449 io0_a_src = a_src->data.ptr;
34450 io1_a_src = io0_a_src + a_src->meta.ri;
34451 iop_a_src = io1_a_src;
34452 io2_a_src = io0_a_src + a_src->meta.wi;
34453 }
34454
34455 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
34456 switch (coro_susp_point) {
34457 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
34458
34459 if (self->private_impl.f_call_sequence < 3) {
34460 if (a_src) {
34461 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
34462 }
34463 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
34464 status = wuffs_nie__decoder__decode_image_config(self, NULL, a_src);
34465 if (a_src) {
34466 iop_a_src = a_src->data.ptr + a_src->meta.ri;
34467 }
34468 if (status.repr) {
34469 goto suspend;
34470 }
34471 } else if (self->private_impl.f_call_sequence == 3) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100034472 if (16 != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) {
Nigel Taoe360a532021-04-05 22:47:03 +100034473 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
34474 goto exit;
34475 }
34476 } else if (self->private_impl.f_call_sequence == 4) {
34477 self->private_impl.f_call_sequence = 255;
34478 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
34479 goto ok;
34480 } else {
34481 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
34482 goto ok;
34483 }
34484 if (a_dst != NULL) {
34485 wuffs_base__frame_config__set(
34486 a_dst,
34487 wuffs_base__utility__make_rect_ie_u32(
34488 0,
34489 0,
34490 self->private_impl.f_width,
34491 self->private_impl.f_height),
34492 ((wuffs_base__flicks)(0)),
34493 0,
34494 16,
34495 0,
34496 false,
34497 false,
34498 0);
34499 }
34500 self->private_impl.f_call_sequence = 4;
34501
Nigel Taoe360a532021-04-05 22:47:03 +100034502 ok:
34503 self->private_impl.p_decode_frame_config[0] = 0;
34504 goto exit;
34505 }
34506
34507 goto suspend;
34508 suspend:
34509 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
34510 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
34511
34512 goto exit;
34513 exit:
34514 if (a_src) {
34515 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
34516 }
34517
34518 if (wuffs_base__status__is_error(&status)) {
34519 self->private_impl.magic = WUFFS_BASE__DISABLED;
34520 }
34521 return status;
34522}
34523
34524// -------- func nie.decoder.decode_frame
34525
34526WUFFS_BASE__MAYBE_STATIC wuffs_base__status
34527wuffs_nie__decoder__decode_frame(
34528 wuffs_nie__decoder* self,
34529 wuffs_base__pixel_buffer* a_dst,
34530 wuffs_base__io_buffer* a_src,
34531 wuffs_base__pixel_blend a_blend,
34532 wuffs_base__slice_u8 a_workbuf,
34533 wuffs_base__decode_frame_options* a_opts) {
34534 if (!self) {
34535 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34536 }
34537 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
34538 return wuffs_base__make_status(
34539 (self->private_impl.magic == WUFFS_BASE__DISABLED)
34540 ? wuffs_base__error__disabled_by_previous_error
34541 : wuffs_base__error__initialize_not_called);
34542 }
34543 if (!a_dst || !a_src) {
34544 self->private_impl.magic = WUFFS_BASE__DISABLED;
34545 return wuffs_base__make_status(wuffs_base__error__bad_argument);
34546 }
34547 if ((self->private_impl.active_coroutine != 0) &&
34548 (self->private_impl.active_coroutine != 3)) {
34549 self->private_impl.magic = WUFFS_BASE__DISABLED;
34550 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
34551 }
34552 self->private_impl.active_coroutine = 0;
34553 wuffs_base__status status = wuffs_base__make_status(NULL);
34554
34555 wuffs_base__status v_status = wuffs_base__make_status(NULL);
34556
34557 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
34558 switch (coro_susp_point) {
34559 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
34560
34561 if (self->private_impl.f_call_sequence < 4) {
34562 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
34563 status = wuffs_nie__decoder__decode_frame_config(self, NULL, a_src);
34564 if (status.repr) {
34565 goto suspend;
34566 }
34567 } else if (self->private_impl.f_call_sequence == 4) {
34568 } else {
34569 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
34570 goto ok;
34571 }
34572 self->private_impl.f_dst_x = 0;
34573 self->private_impl.f_dst_y = 0;
34574 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
34575 wuffs_base__pixel_buffer__pixel_format(a_dst),
34576 wuffs_base__pixel_buffer__palette(a_dst),
34577 wuffs_base__utility__make_pixel_format(self->private_impl.f_pixfmt),
34578 wuffs_base__utility__empty_slice_u8(),
34579 a_blend);
34580 if ( ! wuffs_base__status__is_ok(&v_status)) {
34581 status = v_status;
34582 if (wuffs_base__status__is_error(&status)) {
34583 goto exit;
34584 } else if (wuffs_base__status__is_suspension(&status)) {
34585 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
34586 goto exit;
34587 }
34588 goto ok;
34589 }
34590 while (true) {
34591 v_status = wuffs_nie__decoder__swizzle(self, a_dst, a_src);
34592 if (wuffs_base__status__is_ok(&v_status)) {
34593 goto label__0__break;
34594 } else if (v_status.repr != wuffs_nie__note__internal_note_short_read) {
34595 status = v_status;
34596 if (wuffs_base__status__is_error(&status)) {
34597 goto exit;
34598 } else if (wuffs_base__status__is_suspension(&status)) {
34599 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
34600 goto exit;
34601 }
34602 goto ok;
34603 }
34604 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34605 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
34606 }
34607 label__0__break:;
34608 self->private_impl.f_call_sequence = 255;
34609
Nigel Taoe360a532021-04-05 22:47:03 +100034610 ok:
34611 self->private_impl.p_decode_frame[0] = 0;
34612 goto exit;
34613 }
34614
34615 goto suspend;
34616 suspend:
34617 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
34618 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
34619
34620 goto exit;
34621 exit:
34622 if (wuffs_base__status__is_error(&status)) {
34623 self->private_impl.magic = WUFFS_BASE__DISABLED;
34624 }
34625 return status;
34626}
34627
34628// -------- func nie.decoder.swizzle
34629
34630static wuffs_base__status
34631wuffs_nie__decoder__swizzle(
34632 wuffs_nie__decoder* self,
34633 wuffs_base__pixel_buffer* a_dst,
34634 wuffs_base__io_buffer* a_src) {
34635 wuffs_base__status status = wuffs_base__make_status(NULL);
34636
34637 wuffs_base__pixel_format v_dst_pixfmt = {0};
34638 uint32_t v_dst_bits_per_pixel = 0;
34639 uint64_t v_dst_bytes_per_pixel = 0;
34640 uint64_t v_dst_bytes_per_row = 0;
34641 wuffs_base__table_u8 v_tab = {0};
34642 wuffs_base__slice_u8 v_dst = {0};
34643 uint64_t v_i = 0;
34644 uint64_t v_n = 0;
34645
34646 const uint8_t* iop_a_src = NULL;
34647 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34648 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34649 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34650 if (a_src) {
34651 io0_a_src = a_src->data.ptr;
34652 io1_a_src = io0_a_src + a_src->meta.ri;
34653 iop_a_src = io1_a_src;
34654 io2_a_src = io0_a_src + a_src->meta.wi;
34655 }
34656
34657 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
34658 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
34659 if ((v_dst_bits_per_pixel & 7) != 0) {
34660 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
34661 goto exit;
34662 }
34663 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
34664 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
34665 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
34666 label__0__continue:;
34667 while (true) {
34668 if (self->private_impl.f_dst_x == self->private_impl.f_width) {
34669 self->private_impl.f_dst_x = 0;
34670 self->private_impl.f_dst_y += 1;
34671 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
34672 goto label__0__break;
34673 }
34674 }
Nigel Taobf9dab32021-11-18 19:19:55 +110034675 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100034676 if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) {
34677 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row);
34678 }
34679 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
34680 if (v_i >= ((uint64_t)(v_dst.len))) {
34681 goto label__0__continue;
34682 }
34683 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
34684 &self->private_impl.f_swizzler,
34685 wuffs_base__slice_u8__subslice_i(v_dst, v_i),
34686 wuffs_base__pixel_buffer__palette(a_dst),
34687 &iop_a_src,
34688 io2_a_src);
34689 if (v_n == 0) {
34690 status = wuffs_base__make_status(wuffs_nie__note__internal_note_short_read);
34691 goto ok;
34692 }
34693 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
34694 }
34695 label__0__break:;
34696 status = wuffs_base__make_status(NULL);
34697 goto ok;
34698
Nigel Taoe360a532021-04-05 22:47:03 +100034699 ok:
34700 goto exit;
34701 exit:
34702 if (a_src) {
34703 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
34704 }
34705
34706 return status;
34707}
34708
34709// -------- func nie.decoder.frame_dirty_rect
34710
34711WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
34712wuffs_nie__decoder__frame_dirty_rect(
34713 const wuffs_nie__decoder* self) {
34714 if (!self) {
34715 return wuffs_base__utility__empty_rect_ie_u32();
34716 }
34717 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
34718 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
34719 return wuffs_base__utility__empty_rect_ie_u32();
34720 }
34721
34722 return wuffs_base__utility__make_rect_ie_u32(
34723 0,
34724 0,
34725 self->private_impl.f_width,
34726 self->private_impl.f_height);
34727}
34728
34729// -------- func nie.decoder.num_animation_loops
34730
34731WUFFS_BASE__MAYBE_STATIC uint32_t
34732wuffs_nie__decoder__num_animation_loops(
34733 const wuffs_nie__decoder* self) {
34734 if (!self) {
34735 return 0;
34736 }
34737 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
34738 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
34739 return 0;
34740 }
34741
34742 return 0;
34743}
34744
34745// -------- func nie.decoder.num_decoded_frame_configs
34746
34747WUFFS_BASE__MAYBE_STATIC uint64_t
34748wuffs_nie__decoder__num_decoded_frame_configs(
34749 const wuffs_nie__decoder* self) {
34750 if (!self) {
34751 return 0;
34752 }
34753 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
34754 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
34755 return 0;
34756 }
34757
34758 if (self->private_impl.f_call_sequence > 3) {
34759 return 1;
34760 }
34761 return 0;
34762}
34763
34764// -------- func nie.decoder.num_decoded_frames
34765
34766WUFFS_BASE__MAYBE_STATIC uint64_t
34767wuffs_nie__decoder__num_decoded_frames(
34768 const wuffs_nie__decoder* self) {
34769 if (!self) {
34770 return 0;
34771 }
34772 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
34773 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
34774 return 0;
34775 }
34776
34777 if (self->private_impl.f_call_sequence > 4) {
34778 return 1;
34779 }
34780 return 0;
34781}
34782
34783// -------- func nie.decoder.restart_frame
34784
34785WUFFS_BASE__MAYBE_STATIC wuffs_base__status
34786wuffs_nie__decoder__restart_frame(
34787 wuffs_nie__decoder* self,
34788 uint64_t a_index,
34789 uint64_t a_io_position) {
34790 if (!self) {
34791 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34792 }
34793 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
34794 return wuffs_base__make_status(
34795 (self->private_impl.magic == WUFFS_BASE__DISABLED)
34796 ? wuffs_base__error__disabled_by_previous_error
34797 : wuffs_base__error__initialize_not_called);
34798 }
34799
34800 if (self->private_impl.f_call_sequence < 3) {
34801 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
34802 }
34803 if ((a_index != 0) || (a_io_position != 16)) {
34804 return wuffs_base__make_status(wuffs_base__error__bad_argument);
34805 }
34806 self->private_impl.f_call_sequence = 3;
34807 return wuffs_base__make_status(NULL);
34808}
34809
34810// -------- func nie.decoder.set_report_metadata
34811
34812WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
34813wuffs_nie__decoder__set_report_metadata(
34814 wuffs_nie__decoder* self,
34815 uint32_t a_fourcc,
34816 bool a_report) {
34817 return wuffs_base__make_empty_struct();
34818}
34819
34820// -------- func nie.decoder.tell_me_more
34821
34822WUFFS_BASE__MAYBE_STATIC wuffs_base__status
34823wuffs_nie__decoder__tell_me_more(
34824 wuffs_nie__decoder* self,
34825 wuffs_base__io_buffer* a_dst,
34826 wuffs_base__more_information* a_minfo,
34827 wuffs_base__io_buffer* a_src) {
34828 if (!self) {
34829 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34830 }
34831 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
34832 return wuffs_base__make_status(
34833 (self->private_impl.magic == WUFFS_BASE__DISABLED)
34834 ? wuffs_base__error__disabled_by_previous_error
34835 : wuffs_base__error__initialize_not_called);
34836 }
34837 if (!a_dst || !a_src) {
34838 self->private_impl.magic = WUFFS_BASE__DISABLED;
34839 return wuffs_base__make_status(wuffs_base__error__bad_argument);
34840 }
34841 if ((self->private_impl.active_coroutine != 0) &&
34842 (self->private_impl.active_coroutine != 4)) {
34843 self->private_impl.magic = WUFFS_BASE__DISABLED;
34844 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
34845 }
34846 self->private_impl.active_coroutine = 0;
34847 wuffs_base__status status = wuffs_base__make_status(NULL);
34848
34849 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
34850 goto exit;
34851
34852 goto ok;
34853 ok:
34854 goto exit;
34855 exit:
34856 if (wuffs_base__status__is_error(&status)) {
34857 self->private_impl.magic = WUFFS_BASE__DISABLED;
34858 }
34859 return status;
34860}
34861
34862// -------- func nie.decoder.workbuf_len
34863
34864WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
34865wuffs_nie__decoder__workbuf_len(
34866 const wuffs_nie__decoder* self) {
34867 if (!self) {
34868 return wuffs_base__utility__empty_range_ii_u64();
34869 }
34870 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
34871 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
34872 return wuffs_base__utility__empty_range_ii_u64();
34873 }
34874
34875 return wuffs_base__utility__make_range_ii_u64(0, 0);
34876}
34877
34878#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE)
34879
34880#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB)
34881
34882// ---------------- Status Codes Implementations
34883
34884const char wuffs_zlib__note__dictionary_required[] = "@zlib: dictionary required";
34885const char wuffs_zlib__error__bad_checksum[] = "#zlib: bad checksum";
34886const char wuffs_zlib__error__bad_compression_method[] = "#zlib: bad compression method";
34887const char wuffs_zlib__error__bad_compression_window_size[] = "#zlib: bad compression window size";
34888const char wuffs_zlib__error__bad_parity_check[] = "#zlib: bad parity check";
34889const char wuffs_zlib__error__incorrect_dictionary[] = "#zlib: incorrect dictionary";
34890
34891// ---------------- Private Consts
34892
34893// ---------------- Private Initializer Prototypes
34894
34895// ---------------- Private Function Prototypes
34896
34897// ---------------- VTables
34898
34899const wuffs_base__io_transformer__func_ptrs
34900wuffs_zlib__decoder__func_ptrs_for__wuffs_base__io_transformer = {
34901 (wuffs_base__empty_struct(*)(void*,
34902 uint32_t,
34903 bool))(&wuffs_zlib__decoder__set_quirk_enabled),
34904 (wuffs_base__status(*)(void*,
34905 wuffs_base__io_buffer*,
34906 wuffs_base__io_buffer*,
34907 wuffs_base__slice_u8))(&wuffs_zlib__decoder__transform_io),
34908 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_zlib__decoder__workbuf_len),
34909};
34910
34911// ---------------- Initializer Implementations
34912
34913wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
34914wuffs_zlib__decoder__initialize(
34915 wuffs_zlib__decoder* self,
34916 size_t sizeof_star_self,
34917 uint64_t wuffs_version,
34918 uint32_t options){
34919 if (!self) {
34920 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34921 }
34922 if (sizeof(*self) != sizeof_star_self) {
34923 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
34924 }
34925 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
34926 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
34927 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
34928 }
34929
34930 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
34931 // The whole point of this if-check is to detect an uninitialized *self.
34932 // We disable the warning on GCC. Clang-5.0 does not have this warning.
34933#if !defined(__clang__) && defined(__GNUC__)
34934#pragma GCC diagnostic push
34935#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
34936#endif
34937 if (self->private_impl.magic != 0) {
34938 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
34939 }
34940#if !defined(__clang__) && defined(__GNUC__)
34941#pragma GCC diagnostic pop
34942#endif
34943 } else {
34944 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
34945 memset(self, 0, sizeof(*self));
34946 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
34947 } else {
34948 memset(&(self->private_impl), 0, sizeof(self->private_impl));
34949 }
34950 }
34951
34952 {
34953 wuffs_base__status z = wuffs_adler32__hasher__initialize(
34954 &self->private_data.f_checksum, sizeof(self->private_data.f_checksum), WUFFS_VERSION, options);
34955 if (z.repr) {
34956 return z;
34957 }
34958 }
34959 {
34960 wuffs_base__status z = wuffs_adler32__hasher__initialize(
34961 &self->private_data.f_dict_id_hasher, sizeof(self->private_data.f_dict_id_hasher), WUFFS_VERSION, options);
34962 if (z.repr) {
34963 return z;
34964 }
34965 }
34966 {
34967 wuffs_base__status z = wuffs_deflate__decoder__initialize(
34968 &self->private_data.f_flate, sizeof(self->private_data.f_flate), WUFFS_VERSION, options);
34969 if (z.repr) {
34970 return z;
34971 }
34972 }
34973 self->private_impl.magic = WUFFS_BASE__MAGIC;
34974 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
34975 wuffs_base__io_transformer__vtable_name;
34976 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
34977 (const void*)(&wuffs_zlib__decoder__func_ptrs_for__wuffs_base__io_transformer);
34978 return wuffs_base__make_status(NULL);
34979}
34980
34981wuffs_zlib__decoder*
34982wuffs_zlib__decoder__alloc() {
34983 wuffs_zlib__decoder* x =
34984 (wuffs_zlib__decoder*)(calloc(sizeof(wuffs_zlib__decoder), 1));
34985 if (!x) {
34986 return NULL;
34987 }
34988 if (wuffs_zlib__decoder__initialize(
34989 x, sizeof(wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
34990 free(x);
34991 return NULL;
34992 }
34993 return x;
34994}
34995
34996size_t
34997sizeof__wuffs_zlib__decoder() {
34998 return sizeof(wuffs_zlib__decoder);
34999}
35000
35001// ---------------- Function Implementations
35002
35003// -------- func zlib.decoder.dictionary_id
35004
35005WUFFS_BASE__MAYBE_STATIC uint32_t
35006wuffs_zlib__decoder__dictionary_id(
35007 const wuffs_zlib__decoder* self) {
35008 if (!self) {
35009 return 0;
35010 }
35011 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
35012 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
35013 return 0;
35014 }
35015
35016 return self->private_impl.f_dict_id_want;
35017}
35018
35019// -------- func zlib.decoder.add_dictionary
35020
35021WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
35022wuffs_zlib__decoder__add_dictionary(
35023 wuffs_zlib__decoder* self,
35024 wuffs_base__slice_u8 a_dict) {
35025 if (!self) {
35026 return wuffs_base__make_empty_struct();
35027 }
35028 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
35029 return wuffs_base__make_empty_struct();
35030 }
35031
35032 if (self->private_impl.f_header_complete) {
35033 self->private_impl.f_bad_call_sequence = true;
35034 } else {
35035 self->private_impl.f_dict_id_got = wuffs_adler32__hasher__update_u32(&self->private_data.f_dict_id_hasher, a_dict);
35036 wuffs_deflate__decoder__add_history(&self->private_data.f_flate, a_dict);
35037 }
35038 self->private_impl.f_got_dictionary = true;
35039 return wuffs_base__make_empty_struct();
35040}
35041
35042// -------- func zlib.decoder.set_quirk_enabled
35043
35044WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
35045wuffs_zlib__decoder__set_quirk_enabled(
35046 wuffs_zlib__decoder* self,
35047 uint32_t a_quirk,
35048 bool a_enabled) {
35049 if (!self) {
35050 return wuffs_base__make_empty_struct();
35051 }
35052 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
35053 return wuffs_base__make_empty_struct();
35054 }
35055
35056 if (a_quirk == 1) {
35057 self->private_impl.f_ignore_checksum = a_enabled;
35058 }
35059 return wuffs_base__make_empty_struct();
35060}
35061
35062// -------- func zlib.decoder.workbuf_len
35063
35064WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
35065wuffs_zlib__decoder__workbuf_len(
35066 const wuffs_zlib__decoder* self) {
35067 if (!self) {
35068 return wuffs_base__utility__empty_range_ii_u64();
35069 }
35070 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
35071 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
35072 return wuffs_base__utility__empty_range_ii_u64();
35073 }
35074
35075 return wuffs_base__utility__make_range_ii_u64(1, 1);
35076}
35077
35078// -------- func zlib.decoder.transform_io
35079
35080WUFFS_BASE__MAYBE_STATIC wuffs_base__status
35081wuffs_zlib__decoder__transform_io(
35082 wuffs_zlib__decoder* self,
35083 wuffs_base__io_buffer* a_dst,
35084 wuffs_base__io_buffer* a_src,
35085 wuffs_base__slice_u8 a_workbuf) {
35086 if (!self) {
35087 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
35088 }
35089 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
35090 return wuffs_base__make_status(
35091 (self->private_impl.magic == WUFFS_BASE__DISABLED)
35092 ? wuffs_base__error__disabled_by_previous_error
35093 : wuffs_base__error__initialize_not_called);
35094 }
35095 if (!a_dst || !a_src) {
35096 self->private_impl.magic = WUFFS_BASE__DISABLED;
35097 return wuffs_base__make_status(wuffs_base__error__bad_argument);
35098 }
35099 if ((self->private_impl.active_coroutine != 0) &&
35100 (self->private_impl.active_coroutine != 1)) {
35101 self->private_impl.magic = WUFFS_BASE__DISABLED;
35102 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
35103 }
35104 self->private_impl.active_coroutine = 0;
35105 wuffs_base__status status = wuffs_base__make_status(NULL);
35106
35107 uint16_t v_x = 0;
35108 uint32_t v_checksum_got = 0;
35109 wuffs_base__status v_status = wuffs_base__make_status(NULL);
35110 uint32_t v_checksum_want = 0;
35111 uint64_t v_mark = 0;
35112
35113 uint8_t* iop_a_dst = NULL;
35114 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35115 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35116 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35117 if (a_dst) {
35118 io0_a_dst = a_dst->data.ptr;
35119 io1_a_dst = io0_a_dst + a_dst->meta.wi;
35120 iop_a_dst = io1_a_dst;
35121 io2_a_dst = io0_a_dst + a_dst->data.len;
35122 if (a_dst->meta.closed) {
35123 io2_a_dst = iop_a_dst;
35124 }
35125 }
35126 const uint8_t* iop_a_src = NULL;
35127 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35128 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35129 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35130 if (a_src) {
35131 io0_a_src = a_src->data.ptr;
35132 io1_a_src = io0_a_src + a_src->meta.ri;
35133 iop_a_src = io1_a_src;
35134 io2_a_src = io0_a_src + a_src->meta.wi;
35135 }
35136
35137 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
35138 if (coro_susp_point) {
35139 v_checksum_got = self->private_data.s_transform_io[0].v_checksum_got;
35140 }
35141 switch (coro_susp_point) {
35142 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
35143
35144 if (self->private_impl.f_bad_call_sequence) {
35145 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
35146 goto exit;
35147 } else if ( ! self->private_impl.f_want_dictionary) {
35148 {
35149 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
35150 uint16_t t_0;
35151 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
35152 t_0 = wuffs_base__peek_u16be__no_bounds_check(iop_a_src);
35153 iop_a_src += 2;
35154 } else {
35155 self->private_data.s_transform_io[0].scratch = 0;
35156 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
35157 while (true) {
35158 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
35159 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35160 goto suspend;
35161 }
35162 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
35163 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
35164 *scratch >>= 8;
35165 *scratch <<= 8;
35166 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
35167 if (num_bits_0 == 8) {
35168 t_0 = ((uint16_t)(*scratch >> 48));
35169 break;
35170 }
35171 num_bits_0 += 8;
35172 *scratch |= ((uint64_t)(num_bits_0));
35173 }
35174 }
35175 v_x = t_0;
35176 }
35177 if (((v_x >> 8) & 15) != 8) {
35178 status = wuffs_base__make_status(wuffs_zlib__error__bad_compression_method);
35179 goto exit;
35180 }
35181 if ((v_x >> 12) > 7) {
35182 status = wuffs_base__make_status(wuffs_zlib__error__bad_compression_window_size);
35183 goto exit;
35184 }
35185 if ((v_x % 31) != 0) {
35186 status = wuffs_base__make_status(wuffs_zlib__error__bad_parity_check);
35187 goto exit;
35188 }
35189 self->private_impl.f_want_dictionary = ((v_x & 32) != 0);
35190 if (self->private_impl.f_want_dictionary) {
35191 self->private_impl.f_dict_id_got = 1;
35192 {
35193 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
35194 uint32_t t_1;
35195 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
35196 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
35197 iop_a_src += 4;
35198 } else {
35199 self->private_data.s_transform_io[0].scratch = 0;
35200 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
35201 while (true) {
35202 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
35203 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35204 goto suspend;
35205 }
35206 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
35207 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
35208 *scratch >>= 8;
35209 *scratch <<= 8;
35210 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
35211 if (num_bits_1 == 24) {
35212 t_1 = ((uint32_t)(*scratch >> 32));
35213 break;
35214 }
35215 num_bits_1 += 8;
35216 *scratch |= ((uint64_t)(num_bits_1));
35217 }
35218 }
35219 self->private_impl.f_dict_id_want = t_1;
35220 }
35221 status = wuffs_base__make_status(wuffs_zlib__note__dictionary_required);
35222 goto ok;
35223 } else if (self->private_impl.f_got_dictionary) {
35224 status = wuffs_base__make_status(wuffs_zlib__error__incorrect_dictionary);
35225 goto exit;
35226 }
35227 } else if (self->private_impl.f_dict_id_got != self->private_impl.f_dict_id_want) {
35228 if (self->private_impl.f_got_dictionary) {
35229 status = wuffs_base__make_status(wuffs_zlib__error__incorrect_dictionary);
35230 goto exit;
35231 }
35232 status = wuffs_base__make_status(wuffs_zlib__note__dictionary_required);
35233 goto ok;
35234 }
35235 self->private_impl.f_header_complete = true;
35236 while (true) {
35237 v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
35238 {
35239 if (a_dst) {
35240 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
35241 }
35242 if (a_src) {
35243 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35244 }
35245 wuffs_base__status t_2 = wuffs_deflate__decoder__transform_io(&self->private_data.f_flate, a_dst, a_src, a_workbuf);
35246 v_status = t_2;
35247 if (a_dst) {
35248 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
35249 }
35250 if (a_src) {
35251 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35252 }
35253 }
35254 if ( ! self->private_impl.f_ignore_checksum) {
35255 v_checksum_got = wuffs_adler32__hasher__update_u32(&self->private_data.f_checksum, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst));
35256 }
35257 if (wuffs_base__status__is_ok(&v_status)) {
35258 goto label__0__break;
35259 }
35260 status = v_status;
35261 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
35262 }
35263 label__0__break:;
35264 {
35265 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
35266 uint32_t t_3;
35267 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
35268 t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
35269 iop_a_src += 4;
35270 } else {
35271 self->private_data.s_transform_io[0].scratch = 0;
35272 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
35273 while (true) {
35274 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
35275 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35276 goto suspend;
35277 }
35278 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
35279 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
35280 *scratch >>= 8;
35281 *scratch <<= 8;
35282 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
35283 if (num_bits_3 == 24) {
35284 t_3 = ((uint32_t)(*scratch >> 32));
35285 break;
35286 }
35287 num_bits_3 += 8;
35288 *scratch |= ((uint64_t)(num_bits_3));
35289 }
35290 }
35291 v_checksum_want = t_3;
35292 }
35293 if ( ! self->private_impl.f_ignore_checksum && (v_checksum_got != v_checksum_want)) {
35294 status = wuffs_base__make_status(wuffs_zlib__error__bad_checksum);
35295 goto exit;
35296 }
35297
Nigel Taoe360a532021-04-05 22:47:03 +100035298 ok:
35299 self->private_impl.p_transform_io[0] = 0;
35300 goto exit;
35301 }
35302
35303 goto suspend;
35304 suspend:
35305 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
35306 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
35307 self->private_data.s_transform_io[0].v_checksum_got = v_checksum_got;
35308
35309 goto exit;
35310 exit:
35311 if (a_dst) {
35312 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
35313 }
35314 if (a_src) {
35315 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35316 }
35317
35318 if (wuffs_base__status__is_error(&status)) {
35319 self->private_impl.magic = WUFFS_BASE__DISABLED;
35320 }
35321 return status;
35322}
35323
35324#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB)
35325
35326#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG)
35327
35328// ---------------- Status Codes Implementations
35329
Nigel Taobf9dab32021-11-18 19:19:55 +110035330const char wuffs_png__error__bad_animation_sequence_number[] = "#png: bad animation sequence number";
Nigel Taoe360a532021-04-05 22:47:03 +100035331const char wuffs_png__error__bad_checksum[] = "#png: bad checksum";
35332const char wuffs_png__error__bad_chunk[] = "#png: bad chunk";
35333const char wuffs_png__error__bad_filter[] = "#png: bad filter";
35334const char wuffs_png__error__bad_header[] = "#png: bad header";
Nigel Taobf9dab32021-11-18 19:19:55 +110035335const char wuffs_png__error__bad_text_chunk_not_latin_1[] = "#png: bad text chunk (not Latin-1)";
Nigel Taoe360a532021-04-05 22:47:03 +100035336const char wuffs_png__error__missing_palette[] = "#png: missing palette";
Nigel Taobf9dab32021-11-18 19:19:55 +110035337const char wuffs_png__error__unsupported_png_compression_method[] = "#png: unsupported PNG compression method";
Nigel Taoe360a532021-04-05 22:47:03 +100035338const char wuffs_png__error__unsupported_png_file[] = "#png: unsupported PNG file";
Nigel Taobf9dab32021-11-18 19:19:55 +110035339const char wuffs_png__error__internal_error_inconsistent_i_o[] = "#png: internal error: inconsistent I/O";
35340const char wuffs_png__error__internal_error_inconsistent_chunk_type[] = "#png: internal error: inconsistent chunk type";
35341const char wuffs_png__error__internal_error_inconsistent_frame_bounds[] = "#png: internal error: inconsistent frame bounds";
Nigel Taoe360a532021-04-05 22:47:03 +100035342const char wuffs_png__error__internal_error_inconsistent_workbuf_length[] = "#png: internal error: inconsistent workbuf length";
35343const char wuffs_png__error__internal_error_zlib_decoder_did_not_exhaust_its_input[] = "#png: internal error: zlib decoder did not exhaust its input";
35344
35345// ---------------- Private Consts
35346
Nigel Taobf9dab32021-11-18 19:19:55 +110035347#define WUFFS_PNG__ANCILLARY_BIT 32
35348
Nigel Taoe360a532021-04-05 22:47:03 +100035349static const uint8_t
35350WUFFS_PNG__INTERLACING[8][6] WUFFS_BASE__POTENTIALLY_UNUSED = {
35351 {
35352 0, 0, 0, 0, 0, 0,
35353 }, {
35354 3, 7, 0, 3, 7, 0,
35355 }, {
35356 3, 3, 4, 3, 7, 0,
35357 }, {
35358 2, 3, 0, 3, 3, 4,
35359 }, {
35360 2, 1, 2, 2, 3, 0,
35361 }, {
35362 1, 1, 0, 2, 1, 2,
35363 }, {
35364 1, 0, 1, 1, 1, 0,
35365 }, {
35366 0, 0, 0, 1, 0, 1,
35367 },
35368};
35369
35370static const uint8_t
35371WUFFS_PNG__LOW_BIT_DEPTH_MULTIPLIERS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
35372 0, 255, 85, 0, 17, 0, 0, 0,
35373};
35374
35375static const uint8_t
35376WUFFS_PNG__LOW_BIT_DEPTH_NUM_PACKS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
35377 0, 8, 4, 0, 2, 0, 0, 0,
35378};
35379
35380static const uint8_t
35381WUFFS_PNG__NUM_CHANNELS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
35382 1, 0, 3, 1, 2, 0, 4, 0,
35383};
35384
Nigel Taobf9dab32021-11-18 19:19:55 +110035385static const uint16_t
35386WUFFS_PNG__LATIN_1[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
35387 0, 0, 0, 0, 0, 0, 0, 0,
35388 0, 0, 0, 0, 0, 0, 0, 0,
35389 0, 0, 0, 0, 0, 0, 0, 0,
35390 0, 0, 0, 0, 0, 0, 0, 0,
35391 32, 33, 34, 35, 36, 37, 38, 39,
35392 40, 41, 42, 43, 44, 45, 46, 47,
35393 48, 49, 50, 51, 52, 53, 54, 55,
35394 56, 57, 58, 59, 60, 61, 62, 63,
35395 64, 65, 66, 67, 68, 69, 70, 71,
35396 72, 73, 74, 75, 76, 77, 78, 79,
35397 80, 81, 82, 83, 84, 85, 86, 87,
35398 88, 89, 90, 91, 92, 93, 94, 95,
35399 96, 97, 98, 99, 100, 101, 102, 103,
35400 104, 105, 106, 107, 108, 109, 110, 111,
35401 112, 113, 114, 115, 116, 117, 118, 119,
35402 120, 121, 122, 123, 124, 125, 126, 0,
35403 0, 0, 0, 0, 0, 0, 0, 0,
35404 0, 0, 0, 0, 0, 0, 0, 0,
35405 0, 0, 0, 0, 0, 0, 0, 0,
35406 0, 0, 0, 0, 0, 0, 0, 0,
35407 0, 41410, 41666, 41922, 42178, 42434, 42690, 42946,
35408 43202, 43458, 43714, 43970, 44226, 44482, 44738, 44994,
35409 45250, 45506, 45762, 46018, 46274, 46530, 46786, 47042,
35410 47298, 47554, 47810, 48066, 48322, 48578, 48834, 49090,
35411 32963, 33219, 33475, 33731, 33987, 34243, 34499, 34755,
35412 35011, 35267, 35523, 35779, 36035, 36291, 36547, 36803,
35413 37059, 37315, 37571, 37827, 38083, 38339, 38595, 38851,
35414 39107, 39363, 39619, 39875, 40131, 40387, 40643, 40899,
35415 41155, 41411, 41667, 41923, 42179, 42435, 42691, 42947,
35416 43203, 43459, 43715, 43971, 44227, 44483, 44739, 44995,
35417 45251, 45507, 45763, 46019, 46275, 46531, 46787, 47043,
35418 47299, 47555, 47811, 48067, 48323, 48579, 48835, 49091,
35419};
35420
Nigel Taoe360a532021-04-05 22:47:03 +100035421// ---------------- Private Initializer Prototypes
35422
35423// ---------------- Private Function Prototypes
35424
35425#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35426static wuffs_base__empty_struct
35427wuffs_png__decoder__filter_1_distance_4_arm_neon(
35428 wuffs_png__decoder* self,
35429 wuffs_base__slice_u8 a_curr);
35430#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35431
35432#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35433static wuffs_base__empty_struct
35434wuffs_png__decoder__filter_3_distance_4_arm_neon(
35435 wuffs_png__decoder* self,
35436 wuffs_base__slice_u8 a_curr,
35437 wuffs_base__slice_u8 a_prev);
35438#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35439
35440#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35441static wuffs_base__empty_struct
35442wuffs_png__decoder__filter_4_distance_3_arm_neon(
35443 wuffs_png__decoder* self,
35444 wuffs_base__slice_u8 a_curr,
35445 wuffs_base__slice_u8 a_prev);
35446#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35447
35448#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35449static wuffs_base__empty_struct
35450wuffs_png__decoder__filter_4_distance_4_arm_neon(
35451 wuffs_png__decoder* self,
35452 wuffs_base__slice_u8 a_curr,
35453 wuffs_base__slice_u8 a_prev);
35454#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35455
35456static wuffs_base__empty_struct
35457wuffs_png__decoder__filter_1(
35458 wuffs_png__decoder* self,
35459 wuffs_base__slice_u8 a_curr);
35460
35461static wuffs_base__empty_struct
35462wuffs_png__decoder__filter_1__choosy_default(
35463 wuffs_png__decoder* self,
35464 wuffs_base__slice_u8 a_curr);
35465
35466static wuffs_base__empty_struct
35467wuffs_png__decoder__filter_1_distance_3_fallback(
35468 wuffs_png__decoder* self,
35469 wuffs_base__slice_u8 a_curr);
35470
35471static wuffs_base__empty_struct
35472wuffs_png__decoder__filter_1_distance_4_fallback(
35473 wuffs_png__decoder* self,
35474 wuffs_base__slice_u8 a_curr);
35475
35476static wuffs_base__empty_struct
35477wuffs_png__decoder__filter_2(
35478 wuffs_png__decoder* self,
35479 wuffs_base__slice_u8 a_curr,
35480 wuffs_base__slice_u8 a_prev);
35481
35482static wuffs_base__empty_struct
35483wuffs_png__decoder__filter_3(
35484 wuffs_png__decoder* self,
35485 wuffs_base__slice_u8 a_curr,
35486 wuffs_base__slice_u8 a_prev);
35487
35488static wuffs_base__empty_struct
35489wuffs_png__decoder__filter_3__choosy_default(
35490 wuffs_png__decoder* self,
35491 wuffs_base__slice_u8 a_curr,
35492 wuffs_base__slice_u8 a_prev);
35493
35494static wuffs_base__empty_struct
35495wuffs_png__decoder__filter_3_distance_3_fallback(
35496 wuffs_png__decoder* self,
35497 wuffs_base__slice_u8 a_curr,
35498 wuffs_base__slice_u8 a_prev);
35499
35500static wuffs_base__empty_struct
35501wuffs_png__decoder__filter_3_distance_4_fallback(
35502 wuffs_png__decoder* self,
35503 wuffs_base__slice_u8 a_curr,
35504 wuffs_base__slice_u8 a_prev);
35505
35506static wuffs_base__empty_struct
35507wuffs_png__decoder__filter_4(
35508 wuffs_png__decoder* self,
35509 wuffs_base__slice_u8 a_curr,
35510 wuffs_base__slice_u8 a_prev);
35511
35512static wuffs_base__empty_struct
35513wuffs_png__decoder__filter_4__choosy_default(
35514 wuffs_png__decoder* self,
35515 wuffs_base__slice_u8 a_curr,
35516 wuffs_base__slice_u8 a_prev);
35517
35518static wuffs_base__empty_struct
35519wuffs_png__decoder__filter_4_distance_3_fallback(
35520 wuffs_png__decoder* self,
35521 wuffs_base__slice_u8 a_curr,
35522 wuffs_base__slice_u8 a_prev);
35523
35524static wuffs_base__empty_struct
35525wuffs_png__decoder__filter_4_distance_4_fallback(
35526 wuffs_png__decoder* self,
35527 wuffs_base__slice_u8 a_curr,
35528 wuffs_base__slice_u8 a_prev);
35529
Nigel Tao7804ffe2021-10-07 21:58:26 +110035530#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100035531static wuffs_base__empty_struct
35532wuffs_png__decoder__filter_1_distance_4_x86_sse42(
35533 wuffs_png__decoder* self,
35534 wuffs_base__slice_u8 a_curr);
Nigel Tao7804ffe2021-10-07 21:58:26 +110035535#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100035536
Nigel Tao7804ffe2021-10-07 21:58:26 +110035537#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100035538static wuffs_base__empty_struct
35539wuffs_png__decoder__filter_3_distance_4_x86_sse42(
35540 wuffs_png__decoder* self,
35541 wuffs_base__slice_u8 a_curr,
35542 wuffs_base__slice_u8 a_prev);
Nigel Tao7804ffe2021-10-07 21:58:26 +110035543#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100035544
Nigel Tao7804ffe2021-10-07 21:58:26 +110035545#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100035546static wuffs_base__empty_struct
35547wuffs_png__decoder__filter_4_distance_3_x86_sse42(
35548 wuffs_png__decoder* self,
35549 wuffs_base__slice_u8 a_curr,
35550 wuffs_base__slice_u8 a_prev);
Nigel Tao7804ffe2021-10-07 21:58:26 +110035551#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100035552
Nigel Tao7804ffe2021-10-07 21:58:26 +110035553#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100035554static wuffs_base__empty_struct
35555wuffs_png__decoder__filter_4_distance_4_x86_sse42(
35556 wuffs_png__decoder* self,
35557 wuffs_base__slice_u8 a_curr,
35558 wuffs_base__slice_u8 a_prev);
Nigel Tao7804ffe2021-10-07 21:58:26 +110035559#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100035560
35561static wuffs_base__status
35562wuffs_png__decoder__decode_ihdr(
35563 wuffs_png__decoder* self,
35564 wuffs_base__io_buffer* a_src);
35565
35566static wuffs_base__empty_struct
35567wuffs_png__decoder__assign_filter_distance(
35568 wuffs_png__decoder* self);
35569
35570static uint64_t
35571wuffs_png__decoder__calculate_bytes_per_row(
35572 const wuffs_png__decoder* self,
35573 uint32_t a_width);
35574
35575static wuffs_base__empty_struct
35576wuffs_png__decoder__choose_filter_implementations(
35577 wuffs_png__decoder* self);
35578
35579static wuffs_base__status
35580wuffs_png__decoder__decode_other_chunk(
35581 wuffs_png__decoder* self,
35582 wuffs_base__io_buffer* a_src);
35583
35584static wuffs_base__status
Nigel Taobf9dab32021-11-18 19:19:55 +110035585wuffs_png__decoder__decode_actl(
35586 wuffs_png__decoder* self,
35587 wuffs_base__io_buffer* a_src);
35588
35589static wuffs_base__status
35590wuffs_png__decoder__decode_chrm(
35591 wuffs_png__decoder* self,
35592 wuffs_base__io_buffer* a_src);
35593
35594static wuffs_base__status
35595wuffs_png__decoder__decode_fctl(
35596 wuffs_png__decoder* self,
35597 wuffs_base__io_buffer* a_src);
35598
35599static wuffs_base__status
35600wuffs_png__decoder__decode_gama(
35601 wuffs_png__decoder* self,
35602 wuffs_base__io_buffer* a_src);
35603
35604static wuffs_base__status
35605wuffs_png__decoder__decode_iccp(
35606 wuffs_png__decoder* self,
35607 wuffs_base__io_buffer* a_src);
35608
35609static wuffs_base__status
Nigel Taoe360a532021-04-05 22:47:03 +100035610wuffs_png__decoder__decode_plte(
35611 wuffs_png__decoder* self,
35612 wuffs_base__io_buffer* a_src);
35613
35614static wuffs_base__status
Nigel Taobf9dab32021-11-18 19:19:55 +110035615wuffs_png__decoder__decode_srgb(
35616 wuffs_png__decoder* self,
35617 wuffs_base__io_buffer* a_src);
35618
35619static wuffs_base__status
Nigel Taoe360a532021-04-05 22:47:03 +100035620wuffs_png__decoder__decode_trns(
35621 wuffs_png__decoder* self,
35622 wuffs_base__io_buffer* a_src);
35623
35624static wuffs_base__status
Nigel Taobf9dab32021-11-18 19:19:55 +110035625wuffs_png__decoder__skip_frame(
35626 wuffs_png__decoder* self,
35627 wuffs_base__io_buffer* a_src);
35628
35629static wuffs_base__status
Nigel Taoe360a532021-04-05 22:47:03 +100035630wuffs_png__decoder__decode_pass(
35631 wuffs_png__decoder* self,
35632 wuffs_base__io_buffer* a_src,
35633 wuffs_base__slice_u8 a_workbuf);
35634
35635static wuffs_base__status
35636wuffs_png__decoder__filter_and_swizzle(
35637 wuffs_png__decoder* self,
35638 wuffs_base__pixel_buffer* a_dst,
35639 wuffs_base__slice_u8 a_workbuf);
35640
35641static wuffs_base__status
35642wuffs_png__decoder__filter_and_swizzle__choosy_default(
35643 wuffs_png__decoder* self,
35644 wuffs_base__pixel_buffer* a_dst,
35645 wuffs_base__slice_u8 a_workbuf);
35646
35647static wuffs_base__status
35648wuffs_png__decoder__filter_and_swizzle_tricky(
35649 wuffs_png__decoder* self,
35650 wuffs_base__pixel_buffer* a_dst,
35651 wuffs_base__slice_u8 a_workbuf);
35652
35653// ---------------- VTables
35654
35655const wuffs_base__image_decoder__func_ptrs
35656wuffs_png__decoder__func_ptrs_for__wuffs_base__image_decoder = {
35657 (wuffs_base__status(*)(void*,
35658 wuffs_base__pixel_buffer*,
35659 wuffs_base__io_buffer*,
35660 wuffs_base__pixel_blend,
35661 wuffs_base__slice_u8,
35662 wuffs_base__decode_frame_options*))(&wuffs_png__decoder__decode_frame),
35663 (wuffs_base__status(*)(void*,
35664 wuffs_base__frame_config*,
35665 wuffs_base__io_buffer*))(&wuffs_png__decoder__decode_frame_config),
35666 (wuffs_base__status(*)(void*,
35667 wuffs_base__image_config*,
35668 wuffs_base__io_buffer*))(&wuffs_png__decoder__decode_image_config),
35669 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_png__decoder__frame_dirty_rect),
35670 (uint32_t(*)(const void*))(&wuffs_png__decoder__num_animation_loops),
35671 (uint64_t(*)(const void*))(&wuffs_png__decoder__num_decoded_frame_configs),
35672 (uint64_t(*)(const void*))(&wuffs_png__decoder__num_decoded_frames),
35673 (wuffs_base__status(*)(void*,
35674 uint64_t,
35675 uint64_t))(&wuffs_png__decoder__restart_frame),
35676 (wuffs_base__empty_struct(*)(void*,
35677 uint32_t,
35678 bool))(&wuffs_png__decoder__set_quirk_enabled),
35679 (wuffs_base__empty_struct(*)(void*,
35680 uint32_t,
35681 bool))(&wuffs_png__decoder__set_report_metadata),
35682 (wuffs_base__status(*)(void*,
35683 wuffs_base__io_buffer*,
35684 wuffs_base__more_information*,
35685 wuffs_base__io_buffer*))(&wuffs_png__decoder__tell_me_more),
35686 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_png__decoder__workbuf_len),
35687};
35688
35689// ---------------- Initializer Implementations
35690
35691wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
35692wuffs_png__decoder__initialize(
35693 wuffs_png__decoder* self,
35694 size_t sizeof_star_self,
35695 uint64_t wuffs_version,
35696 uint32_t options){
35697 if (!self) {
35698 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
35699 }
35700 if (sizeof(*self) != sizeof_star_self) {
35701 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
35702 }
35703 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
35704 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
35705 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
35706 }
35707
35708 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
35709 // The whole point of this if-check is to detect an uninitialized *self.
35710 // We disable the warning on GCC. Clang-5.0 does not have this warning.
35711#if !defined(__clang__) && defined(__GNUC__)
35712#pragma GCC diagnostic push
35713#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
35714#endif
35715 if (self->private_impl.magic != 0) {
35716 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
35717 }
35718#if !defined(__clang__) && defined(__GNUC__)
35719#pragma GCC diagnostic pop
35720#endif
35721 } else {
35722 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
35723 memset(self, 0, sizeof(*self));
35724 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
35725 } else {
35726 memset(&(self->private_impl), 0, sizeof(self->private_impl));
35727 }
35728 }
35729
35730 self->private_impl.choosy_filter_1 = &wuffs_png__decoder__filter_1__choosy_default;
35731 self->private_impl.choosy_filter_3 = &wuffs_png__decoder__filter_3__choosy_default;
35732 self->private_impl.choosy_filter_4 = &wuffs_png__decoder__filter_4__choosy_default;
35733 self->private_impl.choosy_filter_and_swizzle = &wuffs_png__decoder__filter_and_swizzle__choosy_default;
35734
35735 {
35736 wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize(
35737 &self->private_data.f_crc32, sizeof(self->private_data.f_crc32), WUFFS_VERSION, options);
35738 if (z.repr) {
35739 return z;
35740 }
35741 }
35742 {
35743 wuffs_base__status z = wuffs_zlib__decoder__initialize(
35744 &self->private_data.f_zlib, sizeof(self->private_data.f_zlib), WUFFS_VERSION, options);
35745 if (z.repr) {
35746 return z;
35747 }
35748 }
35749 self->private_impl.magic = WUFFS_BASE__MAGIC;
35750 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
35751 wuffs_base__image_decoder__vtable_name;
35752 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
35753 (const void*)(&wuffs_png__decoder__func_ptrs_for__wuffs_base__image_decoder);
35754 return wuffs_base__make_status(NULL);
35755}
35756
35757wuffs_png__decoder*
35758wuffs_png__decoder__alloc() {
35759 wuffs_png__decoder* x =
35760 (wuffs_png__decoder*)(calloc(sizeof(wuffs_png__decoder), 1));
35761 if (!x) {
35762 return NULL;
35763 }
35764 if (wuffs_png__decoder__initialize(
35765 x, sizeof(wuffs_png__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
35766 free(x);
35767 return NULL;
35768 }
35769 return x;
35770}
35771
35772size_t
35773sizeof__wuffs_png__decoder() {
35774 return sizeof(wuffs_png__decoder);
35775}
35776
35777// ---------------- Function Implementations
35778
35779// ‼ WUFFS MULTI-FILE SECTION +arm_neon
35780// -------- func png.decoder.filter_1_distance_4_arm_neon
35781
35782#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35783static wuffs_base__empty_struct
35784wuffs_png__decoder__filter_1_distance_4_arm_neon(
35785 wuffs_png__decoder* self,
35786 wuffs_base__slice_u8 a_curr) {
35787 wuffs_base__slice_u8 v_curr = {0};
35788 uint8x8_t v_fa = {0};
35789 uint8x8_t v_fx = {0};
35790
35791 {
35792 wuffs_base__slice_u8 i_slice_curr = a_curr;
35793 v_curr.ptr = i_slice_curr.ptr;
35794 v_curr.len = 4;
35795 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
35796 while (v_curr.ptr < i_end0_curr) {
35797 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35798 v_fx = vadd_u8(v_fx, v_fa);
35799 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35800 v_fa = v_fx;
35801 v_curr.ptr += 4;
35802 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35803 v_fx = vadd_u8(v_fx, v_fa);
35804 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35805 v_fa = v_fx;
35806 v_curr.ptr += 4;
35807 }
35808 v_curr.len = 4;
35809 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
35810 while (v_curr.ptr < i_end1_curr) {
35811 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35812 v_fx = vadd_u8(v_fx, v_fa);
35813 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35814 v_fa = v_fx;
35815 v_curr.ptr += 4;
35816 }
35817 v_curr.len = 0;
35818 }
35819 return wuffs_base__make_empty_struct();
35820}
35821#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35822// ‼ WUFFS MULTI-FILE SECTION -arm_neon
35823
35824// ‼ WUFFS MULTI-FILE SECTION +arm_neon
35825// -------- func png.decoder.filter_3_distance_4_arm_neon
35826
35827#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35828static wuffs_base__empty_struct
35829wuffs_png__decoder__filter_3_distance_4_arm_neon(
35830 wuffs_png__decoder* self,
35831 wuffs_base__slice_u8 a_curr,
35832 wuffs_base__slice_u8 a_prev) {
35833 wuffs_base__slice_u8 v_curr = {0};
35834 wuffs_base__slice_u8 v_prev = {0};
35835 uint8x8_t v_fa = {0};
35836 uint8x8_t v_fb = {0};
35837 uint8x8_t v_fx = {0};
35838
35839 if (((uint64_t)(a_prev.len)) == 0) {
35840 {
35841 wuffs_base__slice_u8 i_slice_curr = a_curr;
35842 v_curr.ptr = i_slice_curr.ptr;
35843 v_curr.len = 4;
35844 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
35845 while (v_curr.ptr < i_end0_curr) {
35846 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35847 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
35848 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35849 v_fa = v_fx;
35850 v_curr.ptr += 4;
35851 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35852 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
35853 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35854 v_fa = v_fx;
35855 v_curr.ptr += 4;
35856 }
35857 v_curr.len = 4;
35858 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
35859 while (v_curr.ptr < i_end1_curr) {
35860 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35861 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
35862 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35863 v_fa = v_fx;
35864 v_curr.ptr += 4;
35865 }
35866 v_curr.len = 0;
35867 }
35868 } else {
35869 {
35870 wuffs_base__slice_u8 i_slice_curr = a_curr;
35871 v_curr.ptr = i_slice_curr.ptr;
35872 wuffs_base__slice_u8 i_slice_prev = a_prev;
35873 v_prev.ptr = i_slice_prev.ptr;
35874 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
35875 v_curr.len = 4;
35876 v_prev.len = 4;
35877 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
35878 while (v_curr.ptr < i_end0_curr) {
35879 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
35880 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35881 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
35882 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35883 v_fa = v_fx;
35884 v_curr.ptr += 4;
35885 v_prev.ptr += 4;
35886 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
35887 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35888 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
35889 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35890 v_fa = v_fx;
35891 v_curr.ptr += 4;
35892 v_prev.ptr += 4;
35893 }
35894 v_curr.len = 4;
35895 v_prev.len = 4;
35896 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
35897 while (v_curr.ptr < i_end1_curr) {
35898 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
35899 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35900 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
35901 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35902 v_fa = v_fx;
35903 v_curr.ptr += 4;
35904 v_prev.ptr += 4;
35905 }
35906 v_curr.len = 0;
35907 v_prev.len = 0;
35908 }
35909 }
35910 return wuffs_base__make_empty_struct();
35911}
35912#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35913// ‼ WUFFS MULTI-FILE SECTION -arm_neon
35914
35915// ‼ WUFFS MULTI-FILE SECTION +arm_neon
35916// -------- func png.decoder.filter_4_distance_3_arm_neon
35917
35918#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
35919static wuffs_base__empty_struct
35920wuffs_png__decoder__filter_4_distance_3_arm_neon(
35921 wuffs_png__decoder* self,
35922 wuffs_base__slice_u8 a_curr,
35923 wuffs_base__slice_u8 a_prev) {
35924 wuffs_base__slice_u8 v_curr = {0};
35925 wuffs_base__slice_u8 v_prev = {0};
35926 uint8x8_t v_fa = {0};
35927 uint8x8_t v_fb = {0};
35928 uint8x8_t v_fc = {0};
35929 uint8x8_t v_fx = {0};
35930 uint16x8_t v_fafb = {0};
35931 uint16x8_t v_fcfc = {0};
35932 uint16x8_t v_pa = {0};
35933 uint16x8_t v_pb = {0};
35934 uint16x8_t v_pc = {0};
35935 uint16x8_t v_cmpab = {0};
35936 uint16x8_t v_cmpac = {0};
35937 uint8x8_t v_picka = {0};
35938 uint8x8_t v_pickb = {0};
35939
35940 {
35941 wuffs_base__slice_u8 i_slice_curr = a_curr;
35942 v_curr.ptr = i_slice_curr.ptr;
35943 wuffs_base__slice_u8 i_slice_prev = a_prev;
35944 v_prev.ptr = i_slice_prev.ptr;
35945 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
35946 v_curr.len = 4;
35947 v_prev.len = 4;
35948 uint8_t* i_end0_curr = v_curr.ptr + wuffs_base__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 7, 6);
35949 while (v_curr.ptr < i_end0_curr) {
35950 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
35951 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35952 v_fafb = vaddl_u8(v_fa, v_fb);
35953 v_fcfc = vaddl_u8(v_fc, v_fc);
35954 v_pa = vabdl_u8(v_fb, v_fc);
35955 v_pb = vabdl_u8(v_fa, v_fc);
35956 v_pc = vabdq_u16(v_fafb, v_fcfc);
35957 v_cmpab = vcleq_u16(v_pa, v_pb);
35958 v_cmpac = vcleq_u16(v_pa, v_pc);
35959 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
35960 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
35961 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
35962 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35963 v_fc = v_fb;
35964 v_fa = v_fx;
35965 v_curr.ptr += 3;
35966 v_prev.ptr += 3;
35967 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
35968 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35969 v_fafb = vaddl_u8(v_fa, v_fb);
35970 v_fcfc = vaddl_u8(v_fc, v_fc);
35971 v_pa = vabdl_u8(v_fb, v_fc);
35972 v_pb = vabdl_u8(v_fa, v_fc);
35973 v_pc = vabdq_u16(v_fafb, v_fcfc);
35974 v_cmpab = vcleq_u16(v_pa, v_pb);
35975 v_cmpac = vcleq_u16(v_pa, v_pc);
35976 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
35977 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
35978 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
35979 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
35980 v_fc = v_fb;
35981 v_fa = v_fx;
35982 v_curr.ptr += 3;
35983 v_prev.ptr += 3;
35984 }
35985 v_curr.len = 4;
35986 v_prev.len = 4;
35987 uint8_t* i_end1_curr = v_curr.ptr + wuffs_base__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 4, 3);
35988 while (v_curr.ptr < i_end1_curr) {
35989 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
35990 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
35991 v_fafb = vaddl_u8(v_fa, v_fb);
35992 v_fcfc = vaddl_u8(v_fc, v_fc);
35993 v_pa = vabdl_u8(v_fb, v_fc);
35994 v_pb = vabdl_u8(v_fa, v_fc);
35995 v_pc = vabdq_u16(v_fafb, v_fcfc);
35996 v_cmpab = vcleq_u16(v_pa, v_pb);
35997 v_cmpac = vcleq_u16(v_pa, v_pc);
35998 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
35999 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
36000 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
36001 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
36002 v_fc = v_fb;
36003 v_fa = v_fx;
36004 v_curr.ptr += 3;
36005 v_prev.ptr += 3;
36006 }
36007 v_curr.len = 3;
36008 v_prev.len = 3;
36009 uint8_t* i_end2_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
36010 while (v_curr.ptr < i_end2_curr) {
36011 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u24le__no_bounds_check(v_prev.ptr)));
36012 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u24le__no_bounds_check(v_curr.ptr)));
36013 v_fafb = vaddl_u8(v_fa, v_fb);
36014 v_fcfc = vaddl_u8(v_fc, v_fc);
36015 v_pa = vabdl_u8(v_fb, v_fc);
36016 v_pb = vabdl_u8(v_fa, v_fc);
36017 v_pc = vabdq_u16(v_fafb, v_fcfc);
36018 v_cmpab = vcleq_u16(v_pa, v_pb);
36019 v_cmpac = vcleq_u16(v_pa, v_pc);
36020 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
36021 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
36022 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
36023 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
36024 v_curr.ptr += 3;
36025 v_prev.ptr += 3;
36026 }
36027 v_curr.len = 0;
36028 v_prev.len = 0;
36029 }
36030 return wuffs_base__make_empty_struct();
36031}
36032#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
36033// ‼ WUFFS MULTI-FILE SECTION -arm_neon
36034
36035// ‼ WUFFS MULTI-FILE SECTION +arm_neon
36036// -------- func png.decoder.filter_4_distance_4_arm_neon
36037
36038#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
36039static wuffs_base__empty_struct
36040wuffs_png__decoder__filter_4_distance_4_arm_neon(
36041 wuffs_png__decoder* self,
36042 wuffs_base__slice_u8 a_curr,
36043 wuffs_base__slice_u8 a_prev) {
36044 wuffs_base__slice_u8 v_curr = {0};
36045 wuffs_base__slice_u8 v_prev = {0};
36046 uint8x8_t v_fa = {0};
36047 uint8x8_t v_fb = {0};
36048 uint8x8_t v_fc = {0};
36049 uint8x8_t v_fx = {0};
36050 uint16x8_t v_fafb = {0};
36051 uint16x8_t v_fcfc = {0};
36052 uint16x8_t v_pa = {0};
36053 uint16x8_t v_pb = {0};
36054 uint16x8_t v_pc = {0};
36055 uint16x8_t v_cmpab = {0};
36056 uint16x8_t v_cmpac = {0};
36057 uint8x8_t v_picka = {0};
36058 uint8x8_t v_pickb = {0};
36059
36060 {
36061 wuffs_base__slice_u8 i_slice_curr = a_curr;
36062 v_curr.ptr = i_slice_curr.ptr;
36063 wuffs_base__slice_u8 i_slice_prev = a_prev;
36064 v_prev.ptr = i_slice_prev.ptr;
36065 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
36066 v_curr.len = 4;
36067 v_prev.len = 4;
36068 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
36069 while (v_curr.ptr < i_end0_curr) {
36070 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
36071 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36072 v_fafb = vaddl_u8(v_fa, v_fb);
36073 v_fcfc = vaddl_u8(v_fc, v_fc);
36074 v_pa = vabdl_u8(v_fb, v_fc);
36075 v_pb = vabdl_u8(v_fa, v_fc);
36076 v_pc = vabdq_u16(v_fafb, v_fcfc);
36077 v_cmpab = vcleq_u16(v_pa, v_pb);
36078 v_cmpac = vcleq_u16(v_pa, v_pc);
36079 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
36080 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
36081 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
36082 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
36083 v_fc = v_fb;
36084 v_fa = v_fx;
36085 v_curr.ptr += 4;
36086 v_prev.ptr += 4;
36087 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
36088 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36089 v_fafb = vaddl_u8(v_fa, v_fb);
36090 v_fcfc = vaddl_u8(v_fc, v_fc);
36091 v_pa = vabdl_u8(v_fb, v_fc);
36092 v_pb = vabdl_u8(v_fa, v_fc);
36093 v_pc = vabdq_u16(v_fafb, v_fcfc);
36094 v_cmpab = vcleq_u16(v_pa, v_pb);
36095 v_cmpac = vcleq_u16(v_pa, v_pc);
36096 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
36097 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
36098 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
36099 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
36100 v_fc = v_fb;
36101 v_fa = v_fx;
36102 v_curr.ptr += 4;
36103 v_prev.ptr += 4;
36104 }
36105 v_curr.len = 4;
36106 v_prev.len = 4;
36107 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
36108 while (v_curr.ptr < i_end1_curr) {
36109 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
36110 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36111 v_fafb = vaddl_u8(v_fa, v_fb);
36112 v_fcfc = vaddl_u8(v_fc, v_fc);
36113 v_pa = vabdl_u8(v_fb, v_fc);
36114 v_pb = vabdl_u8(v_fa, v_fc);
36115 v_pc = vabdq_u16(v_fafb, v_fcfc);
36116 v_cmpab = vcleq_u16(v_pa, v_pb);
36117 v_cmpac = vcleq_u16(v_pa, v_pc);
36118 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
36119 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
36120 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
36121 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
36122 v_fc = v_fb;
36123 v_fa = v_fx;
36124 v_curr.ptr += 4;
36125 v_prev.ptr += 4;
36126 }
36127 v_curr.len = 0;
36128 v_prev.len = 0;
36129 }
36130 return wuffs_base__make_empty_struct();
36131}
36132#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
36133// ‼ WUFFS MULTI-FILE SECTION -arm_neon
36134
36135// -------- func png.decoder.filter_1
36136
36137static wuffs_base__empty_struct
36138wuffs_png__decoder__filter_1(
36139 wuffs_png__decoder* self,
36140 wuffs_base__slice_u8 a_curr) {
36141 return (*self->private_impl.choosy_filter_1)(self, a_curr);
36142}
36143
36144static wuffs_base__empty_struct
36145wuffs_png__decoder__filter_1__choosy_default(
36146 wuffs_png__decoder* self,
36147 wuffs_base__slice_u8 a_curr) {
36148 uint64_t v_filter_distance = 0;
36149 uint8_t v_fa = 0;
36150 uint64_t v_i_start = 0;
36151 uint64_t v_i = 0;
36152
36153 v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance));
36154 v_i_start = 0;
36155 while (v_i_start < v_filter_distance) {
36156 v_fa = 0;
36157 v_i = v_i_start;
36158 while (v_i < ((uint64_t)(a_curr.len))) {
36159 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + v_fa));
36160 v_fa = a_curr.ptr[v_i];
36161 v_i += v_filter_distance;
36162 }
36163 v_i_start += 1;
36164 }
36165 return wuffs_base__make_empty_struct();
36166}
36167
36168// -------- func png.decoder.filter_1_distance_3_fallback
36169
36170static wuffs_base__empty_struct
36171wuffs_png__decoder__filter_1_distance_3_fallback(
36172 wuffs_png__decoder* self,
36173 wuffs_base__slice_u8 a_curr) {
36174 wuffs_base__slice_u8 v_curr = {0};
36175 uint8_t v_fa0 = 0;
36176 uint8_t v_fa1 = 0;
36177 uint8_t v_fa2 = 0;
36178
36179 {
36180 wuffs_base__slice_u8 i_slice_curr = a_curr;
36181 v_curr.ptr = i_slice_curr.ptr;
36182 v_curr.len = 3;
36183 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6);
36184 while (v_curr.ptr < i_end0_curr) {
36185 v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0]));
36186 v_curr.ptr[0] = v_fa0;
36187 v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1]));
36188 v_curr.ptr[1] = v_fa1;
36189 v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2]));
36190 v_curr.ptr[2] = v_fa2;
36191 v_curr.ptr += 3;
36192 v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0]));
36193 v_curr.ptr[0] = v_fa0;
36194 v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1]));
36195 v_curr.ptr[1] = v_fa1;
36196 v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2]));
36197 v_curr.ptr[2] = v_fa2;
36198 v_curr.ptr += 3;
36199 }
36200 v_curr.len = 3;
36201 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
36202 while (v_curr.ptr < i_end1_curr) {
36203 v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0]));
36204 v_curr.ptr[0] = v_fa0;
36205 v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1]));
36206 v_curr.ptr[1] = v_fa1;
36207 v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2]));
36208 v_curr.ptr[2] = v_fa2;
36209 v_curr.ptr += 3;
36210 }
36211 v_curr.len = 0;
36212 }
36213 return wuffs_base__make_empty_struct();
36214}
36215
36216// -------- func png.decoder.filter_1_distance_4_fallback
36217
36218static wuffs_base__empty_struct
36219wuffs_png__decoder__filter_1_distance_4_fallback(
36220 wuffs_png__decoder* self,
36221 wuffs_base__slice_u8 a_curr) {
36222 wuffs_base__slice_u8 v_curr = {0};
36223 uint8_t v_fa0 = 0;
36224 uint8_t v_fa1 = 0;
36225 uint8_t v_fa2 = 0;
36226 uint8_t v_fa3 = 0;
36227
36228 {
36229 wuffs_base__slice_u8 i_slice_curr = a_curr;
36230 v_curr.ptr = i_slice_curr.ptr;
36231 v_curr.len = 4;
36232 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
36233 while (v_curr.ptr < i_end0_curr) {
36234 v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0]));
36235 v_curr.ptr[0] = v_fa0;
36236 v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1]));
36237 v_curr.ptr[1] = v_fa1;
36238 v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2]));
36239 v_curr.ptr[2] = v_fa2;
36240 v_fa3 = ((uint8_t)(v_fa3 + v_curr.ptr[3]));
36241 v_curr.ptr[3] = v_fa3;
36242 v_curr.ptr += 4;
36243 }
36244 v_curr.len = 0;
36245 }
36246 return wuffs_base__make_empty_struct();
36247}
36248
36249// -------- func png.decoder.filter_2
36250
36251static wuffs_base__empty_struct
36252wuffs_png__decoder__filter_2(
36253 wuffs_png__decoder* self,
36254 wuffs_base__slice_u8 a_curr,
36255 wuffs_base__slice_u8 a_prev) {
36256 uint64_t v_n = 0;
36257 uint64_t v_i = 0;
36258
36259 v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len)));
36260 v_i = 0;
36261 while (v_i < v_n) {
36262 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + a_prev.ptr[v_i]));
36263 v_i += 1;
36264 }
36265 return wuffs_base__make_empty_struct();
36266}
36267
36268// -------- func png.decoder.filter_3
36269
36270static wuffs_base__empty_struct
36271wuffs_png__decoder__filter_3(
36272 wuffs_png__decoder* self,
36273 wuffs_base__slice_u8 a_curr,
36274 wuffs_base__slice_u8 a_prev) {
36275 return (*self->private_impl.choosy_filter_3)(self, a_curr, a_prev);
36276}
36277
36278static wuffs_base__empty_struct
36279wuffs_png__decoder__filter_3__choosy_default(
36280 wuffs_png__decoder* self,
36281 wuffs_base__slice_u8 a_curr,
36282 wuffs_base__slice_u8 a_prev) {
36283 uint64_t v_filter_distance = 0;
36284 uint64_t v_n = 0;
36285 uint64_t v_i = 0;
36286
36287 v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance));
36288 if (((uint64_t)(a_prev.len)) == 0) {
36289 v_i = v_filter_distance;
36290 while (v_i < ((uint64_t)(a_curr.len))) {
36291 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + (a_curr.ptr[(v_i - v_filter_distance)] / 2)));
36292 v_i += 1;
36293 }
36294 } else {
36295 v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len)));
36296 v_i = 0;
36297 while ((v_i < v_n) && (v_i < v_filter_distance)) {
36298 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + (a_prev.ptr[v_i] / 2)));
36299 v_i += 1;
36300 }
36301 v_i = v_filter_distance;
36302 while (v_i < v_n) {
36303 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)(((((uint32_t)(a_curr.ptr[(v_i - v_filter_distance)])) + ((uint32_t)(a_prev.ptr[v_i]))) / 2)))));
36304 v_i += 1;
36305 }
36306 }
36307 return wuffs_base__make_empty_struct();
36308}
36309
36310// -------- func png.decoder.filter_3_distance_3_fallback
36311
36312static wuffs_base__empty_struct
36313wuffs_png__decoder__filter_3_distance_3_fallback(
36314 wuffs_png__decoder* self,
36315 wuffs_base__slice_u8 a_curr,
36316 wuffs_base__slice_u8 a_prev) {
36317 wuffs_base__slice_u8 v_curr = {0};
36318 wuffs_base__slice_u8 v_prev = {0};
36319 uint8_t v_fa0 = 0;
36320 uint8_t v_fa1 = 0;
36321 uint8_t v_fa2 = 0;
36322
36323 if (((uint64_t)(a_prev.len)) == 0) {
36324 {
36325 wuffs_base__slice_u8 i_slice_curr = a_curr;
36326 v_curr.ptr = i_slice_curr.ptr;
36327 v_curr.len = 3;
36328 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6);
36329 while (v_curr.ptr < i_end0_curr) {
36330 v_fa0 = ((uint8_t)((v_fa0 / 2) + v_curr.ptr[0]));
36331 v_curr.ptr[0] = v_fa0;
36332 v_fa1 = ((uint8_t)((v_fa1 / 2) + v_curr.ptr[1]));
36333 v_curr.ptr[1] = v_fa1;
36334 v_fa2 = ((uint8_t)((v_fa2 / 2) + v_curr.ptr[2]));
36335 v_curr.ptr[2] = v_fa2;
36336 v_curr.ptr += 3;
36337 v_fa0 = ((uint8_t)((v_fa0 / 2) + v_curr.ptr[0]));
36338 v_curr.ptr[0] = v_fa0;
36339 v_fa1 = ((uint8_t)((v_fa1 / 2) + v_curr.ptr[1]));
36340 v_curr.ptr[1] = v_fa1;
36341 v_fa2 = ((uint8_t)((v_fa2 / 2) + v_curr.ptr[2]));
36342 v_curr.ptr[2] = v_fa2;
36343 v_curr.ptr += 3;
36344 }
36345 v_curr.len = 3;
36346 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
36347 while (v_curr.ptr < i_end1_curr) {
36348 v_fa0 = ((uint8_t)((v_fa0 / 2) + v_curr.ptr[0]));
36349 v_curr.ptr[0] = v_fa0;
36350 v_fa1 = ((uint8_t)((v_fa1 / 2) + v_curr.ptr[1]));
36351 v_curr.ptr[1] = v_fa1;
36352 v_fa2 = ((uint8_t)((v_fa2 / 2) + v_curr.ptr[2]));
36353 v_curr.ptr[2] = v_fa2;
36354 v_curr.ptr += 3;
36355 }
36356 v_curr.len = 0;
36357 }
36358 } else {
36359 {
36360 wuffs_base__slice_u8 i_slice_curr = a_curr;
36361 v_curr.ptr = i_slice_curr.ptr;
36362 wuffs_base__slice_u8 i_slice_prev = a_prev;
36363 v_prev.ptr = i_slice_prev.ptr;
36364 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
36365 v_curr.len = 3;
36366 v_prev.len = 3;
36367 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6);
36368 while (v_curr.ptr < i_end0_curr) {
36369 v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0]))) / 2))) + v_curr.ptr[0]));
36370 v_curr.ptr[0] = v_fa0;
36371 v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1]))) / 2))) + v_curr.ptr[1]));
36372 v_curr.ptr[1] = v_fa1;
36373 v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2]))) / 2))) + v_curr.ptr[2]));
36374 v_curr.ptr[2] = v_fa2;
36375 v_curr.ptr += 3;
36376 v_prev.ptr += 3;
36377 v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0]))) / 2))) + v_curr.ptr[0]));
36378 v_curr.ptr[0] = v_fa0;
36379 v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1]))) / 2))) + v_curr.ptr[1]));
36380 v_curr.ptr[1] = v_fa1;
36381 v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2]))) / 2))) + v_curr.ptr[2]));
36382 v_curr.ptr[2] = v_fa2;
36383 v_curr.ptr += 3;
36384 v_prev.ptr += 3;
36385 }
36386 v_curr.len = 3;
36387 v_prev.len = 3;
36388 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
36389 while (v_curr.ptr < i_end1_curr) {
36390 v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0]))) / 2))) + v_curr.ptr[0]));
36391 v_curr.ptr[0] = v_fa0;
36392 v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1]))) / 2))) + v_curr.ptr[1]));
36393 v_curr.ptr[1] = v_fa1;
36394 v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2]))) / 2))) + v_curr.ptr[2]));
36395 v_curr.ptr[2] = v_fa2;
36396 v_curr.ptr += 3;
36397 v_prev.ptr += 3;
36398 }
36399 v_curr.len = 0;
36400 v_prev.len = 0;
36401 }
36402 }
36403 return wuffs_base__make_empty_struct();
36404}
36405
36406// -------- func png.decoder.filter_3_distance_4_fallback
36407
36408static wuffs_base__empty_struct
36409wuffs_png__decoder__filter_3_distance_4_fallback(
36410 wuffs_png__decoder* self,
36411 wuffs_base__slice_u8 a_curr,
36412 wuffs_base__slice_u8 a_prev) {
36413 wuffs_base__slice_u8 v_curr = {0};
36414 wuffs_base__slice_u8 v_prev = {0};
36415 uint8_t v_fa0 = 0;
36416 uint8_t v_fa1 = 0;
36417 uint8_t v_fa2 = 0;
36418 uint8_t v_fa3 = 0;
36419
36420 if (((uint64_t)(a_prev.len)) == 0) {
36421 {
36422 wuffs_base__slice_u8 i_slice_curr = a_curr;
36423 v_curr.ptr = i_slice_curr.ptr;
36424 v_curr.len = 4;
36425 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
36426 while (v_curr.ptr < i_end0_curr) {
36427 v_fa0 = ((uint8_t)((v_fa0 / 2) + v_curr.ptr[0]));
36428 v_curr.ptr[0] = v_fa0;
36429 v_fa1 = ((uint8_t)((v_fa1 / 2) + v_curr.ptr[1]));
36430 v_curr.ptr[1] = v_fa1;
36431 v_fa2 = ((uint8_t)((v_fa2 / 2) + v_curr.ptr[2]));
36432 v_curr.ptr[2] = v_fa2;
36433 v_fa3 = ((uint8_t)((v_fa3 / 2) + v_curr.ptr[3]));
36434 v_curr.ptr[3] = v_fa3;
36435 v_curr.ptr += 4;
36436 }
36437 v_curr.len = 0;
36438 }
36439 } else {
36440 {
36441 wuffs_base__slice_u8 i_slice_curr = a_curr;
36442 v_curr.ptr = i_slice_curr.ptr;
36443 wuffs_base__slice_u8 i_slice_prev = a_prev;
36444 v_prev.ptr = i_slice_prev.ptr;
36445 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
36446 v_curr.len = 4;
36447 v_prev.len = 4;
36448 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
36449 while (v_curr.ptr < i_end0_curr) {
36450 v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0]))) / 2))) + v_curr.ptr[0]));
36451 v_curr.ptr[0] = v_fa0;
36452 v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1]))) / 2))) + v_curr.ptr[1]));
36453 v_curr.ptr[1] = v_fa1;
36454 v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2]))) / 2))) + v_curr.ptr[2]));
36455 v_curr.ptr[2] = v_fa2;
36456 v_fa3 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa3)) + ((uint32_t)(v_prev.ptr[3]))) / 2))) + v_curr.ptr[3]));
36457 v_curr.ptr[3] = v_fa3;
36458 v_curr.ptr += 4;
36459 v_prev.ptr += 4;
36460 }
36461 v_curr.len = 0;
36462 v_prev.len = 0;
36463 }
36464 }
36465 return wuffs_base__make_empty_struct();
36466}
36467
36468// -------- func png.decoder.filter_4
36469
36470static wuffs_base__empty_struct
36471wuffs_png__decoder__filter_4(
36472 wuffs_png__decoder* self,
36473 wuffs_base__slice_u8 a_curr,
36474 wuffs_base__slice_u8 a_prev) {
36475 return (*self->private_impl.choosy_filter_4)(self, a_curr, a_prev);
36476}
36477
36478static wuffs_base__empty_struct
36479wuffs_png__decoder__filter_4__choosy_default(
36480 wuffs_png__decoder* self,
36481 wuffs_base__slice_u8 a_curr,
36482 wuffs_base__slice_u8 a_prev) {
36483 uint64_t v_filter_distance = 0;
36484 uint64_t v_n = 0;
36485 uint64_t v_i = 0;
36486 uint32_t v_fa = 0;
36487 uint32_t v_fb = 0;
36488 uint32_t v_fc = 0;
36489 uint32_t v_pp = 0;
36490 uint32_t v_pa = 0;
36491 uint32_t v_pb = 0;
36492 uint32_t v_pc = 0;
36493
36494 v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance));
36495 v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len)));
36496 v_i = 0;
36497 while ((v_i < v_n) && (v_i < v_filter_distance)) {
36498 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + a_prev.ptr[v_i]));
36499 v_i += 1;
36500 }
36501 v_i = v_filter_distance;
36502 while (v_i < v_n) {
36503 v_fa = ((uint32_t)(a_curr.ptr[(v_i - v_filter_distance)]));
36504 v_fb = ((uint32_t)(a_prev.ptr[v_i]));
36505 v_fc = ((uint32_t)(a_prev.ptr[(v_i - v_filter_distance)]));
36506 v_pp = ((uint32_t)(((uint32_t)(v_fa + v_fb)) - v_fc));
36507 v_pa = ((uint32_t)(v_pp - v_fa));
36508 if (v_pa >= 2147483648) {
36509 v_pa = ((uint32_t)(0 - v_pa));
36510 }
36511 v_pb = ((uint32_t)(v_pp - v_fb));
36512 if (v_pb >= 2147483648) {
36513 v_pb = ((uint32_t)(0 - v_pb));
36514 }
36515 v_pc = ((uint32_t)(v_pp - v_fc));
36516 if (v_pc >= 2147483648) {
36517 v_pc = ((uint32_t)(0 - v_pc));
36518 }
36519 if ((v_pa <= v_pb) && (v_pa <= v_pc)) {
36520 } else if (v_pb <= v_pc) {
36521 v_fa = v_fb;
36522 } else {
36523 v_fa = v_fc;
36524 }
36525 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)((v_fa & 255)))));
36526 v_i += 1;
36527 }
36528 return wuffs_base__make_empty_struct();
36529}
36530
36531// -------- func png.decoder.filter_4_distance_3_fallback
36532
36533static wuffs_base__empty_struct
36534wuffs_png__decoder__filter_4_distance_3_fallback(
36535 wuffs_png__decoder* self,
36536 wuffs_base__slice_u8 a_curr,
36537 wuffs_base__slice_u8 a_prev) {
36538 wuffs_base__slice_u8 v_curr = {0};
36539 wuffs_base__slice_u8 v_prev = {0};
36540 uint32_t v_fa0 = 0;
36541 uint32_t v_fa1 = 0;
36542 uint32_t v_fa2 = 0;
36543 uint32_t v_fb0 = 0;
36544 uint32_t v_fb1 = 0;
36545 uint32_t v_fb2 = 0;
36546 uint32_t v_fc0 = 0;
36547 uint32_t v_fc1 = 0;
36548 uint32_t v_fc2 = 0;
36549 uint32_t v_pp0 = 0;
36550 uint32_t v_pp1 = 0;
36551 uint32_t v_pp2 = 0;
36552 uint32_t v_pa0 = 0;
36553 uint32_t v_pa1 = 0;
36554 uint32_t v_pa2 = 0;
36555 uint32_t v_pb0 = 0;
36556 uint32_t v_pb1 = 0;
36557 uint32_t v_pb2 = 0;
36558 uint32_t v_pc0 = 0;
36559 uint32_t v_pc1 = 0;
36560 uint32_t v_pc2 = 0;
36561
36562 {
36563 wuffs_base__slice_u8 i_slice_curr = a_curr;
36564 v_curr.ptr = i_slice_curr.ptr;
36565 wuffs_base__slice_u8 i_slice_prev = a_prev;
36566 v_prev.ptr = i_slice_prev.ptr;
36567 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
36568 v_curr.len = 3;
36569 v_prev.len = 3;
36570 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
36571 while (v_curr.ptr < i_end0_curr) {
36572 v_fb0 = ((uint32_t)(v_prev.ptr[0]));
36573 v_pp0 = ((uint32_t)(((uint32_t)(v_fa0 + v_fb0)) - v_fc0));
36574 v_pa0 = ((uint32_t)(v_pp0 - v_fa0));
36575 if (v_pa0 >= 2147483648) {
36576 v_pa0 = ((uint32_t)(0 - v_pa0));
36577 }
36578 v_pb0 = ((uint32_t)(v_pp0 - v_fb0));
36579 if (v_pb0 >= 2147483648) {
36580 v_pb0 = ((uint32_t)(0 - v_pb0));
36581 }
36582 v_pc0 = ((uint32_t)(v_pp0 - v_fc0));
36583 if (v_pc0 >= 2147483648) {
36584 v_pc0 = ((uint32_t)(0 - v_pc0));
36585 }
36586 if ((v_pa0 <= v_pb0) && (v_pa0 <= v_pc0)) {
36587 } else if (v_pb0 <= v_pc0) {
36588 v_fa0 = v_fb0;
36589 } else {
36590 v_fa0 = v_fc0;
36591 }
36592 v_curr.ptr[0] = ((uint8_t)(v_curr.ptr[0] + ((uint8_t)((v_fa0 & 255)))));
36593 v_fa0 = ((uint32_t)(v_curr.ptr[0]));
36594 v_fc0 = v_fb0;
36595 v_fb1 = ((uint32_t)(v_prev.ptr[1]));
36596 v_pp1 = ((uint32_t)(((uint32_t)(v_fa1 + v_fb1)) - v_fc1));
36597 v_pa1 = ((uint32_t)(v_pp1 - v_fa1));
36598 if (v_pa1 >= 2147483648) {
36599 v_pa1 = ((uint32_t)(0 - v_pa1));
36600 }
36601 v_pb1 = ((uint32_t)(v_pp1 - v_fb1));
36602 if (v_pb1 >= 2147483648) {
36603 v_pb1 = ((uint32_t)(0 - v_pb1));
36604 }
36605 v_pc1 = ((uint32_t)(v_pp1 - v_fc1));
36606 if (v_pc1 >= 2147483648) {
36607 v_pc1 = ((uint32_t)(0 - v_pc1));
36608 }
36609 if ((v_pa1 <= v_pb1) && (v_pa1 <= v_pc1)) {
36610 } else if (v_pb1 <= v_pc1) {
36611 v_fa1 = v_fb1;
36612 } else {
36613 v_fa1 = v_fc1;
36614 }
36615 v_curr.ptr[1] = ((uint8_t)(v_curr.ptr[1] + ((uint8_t)((v_fa1 & 255)))));
36616 v_fa1 = ((uint32_t)(v_curr.ptr[1]));
36617 v_fc1 = v_fb1;
36618 v_fb2 = ((uint32_t)(v_prev.ptr[2]));
36619 v_pp2 = ((uint32_t)(((uint32_t)(v_fa2 + v_fb2)) - v_fc2));
36620 v_pa2 = ((uint32_t)(v_pp2 - v_fa2));
36621 if (v_pa2 >= 2147483648) {
36622 v_pa2 = ((uint32_t)(0 - v_pa2));
36623 }
36624 v_pb2 = ((uint32_t)(v_pp2 - v_fb2));
36625 if (v_pb2 >= 2147483648) {
36626 v_pb2 = ((uint32_t)(0 - v_pb2));
36627 }
36628 v_pc2 = ((uint32_t)(v_pp2 - v_fc2));
36629 if (v_pc2 >= 2147483648) {
36630 v_pc2 = ((uint32_t)(0 - v_pc2));
36631 }
36632 if ((v_pa2 <= v_pb2) && (v_pa2 <= v_pc2)) {
36633 } else if (v_pb2 <= v_pc2) {
36634 v_fa2 = v_fb2;
36635 } else {
36636 v_fa2 = v_fc2;
36637 }
36638 v_curr.ptr[2] = ((uint8_t)(v_curr.ptr[2] + ((uint8_t)((v_fa2 & 255)))));
36639 v_fa2 = ((uint32_t)(v_curr.ptr[2]));
36640 v_fc2 = v_fb2;
36641 v_curr.ptr += 3;
36642 v_prev.ptr += 3;
36643 }
36644 v_curr.len = 0;
36645 v_prev.len = 0;
36646 }
36647 return wuffs_base__make_empty_struct();
36648}
36649
36650// -------- func png.decoder.filter_4_distance_4_fallback
36651
36652static wuffs_base__empty_struct
36653wuffs_png__decoder__filter_4_distance_4_fallback(
36654 wuffs_png__decoder* self,
36655 wuffs_base__slice_u8 a_curr,
36656 wuffs_base__slice_u8 a_prev) {
36657 wuffs_base__slice_u8 v_curr = {0};
36658 wuffs_base__slice_u8 v_prev = {0};
36659 uint32_t v_fa0 = 0;
36660 uint32_t v_fa1 = 0;
36661 uint32_t v_fa2 = 0;
36662 uint32_t v_fa3 = 0;
36663 uint32_t v_fb0 = 0;
36664 uint32_t v_fb1 = 0;
36665 uint32_t v_fb2 = 0;
36666 uint32_t v_fb3 = 0;
36667 uint32_t v_fc0 = 0;
36668 uint32_t v_fc1 = 0;
36669 uint32_t v_fc2 = 0;
36670 uint32_t v_fc3 = 0;
36671 uint32_t v_pp0 = 0;
36672 uint32_t v_pp1 = 0;
36673 uint32_t v_pp2 = 0;
36674 uint32_t v_pp3 = 0;
36675 uint32_t v_pa0 = 0;
36676 uint32_t v_pa1 = 0;
36677 uint32_t v_pa2 = 0;
36678 uint32_t v_pa3 = 0;
36679 uint32_t v_pb0 = 0;
36680 uint32_t v_pb1 = 0;
36681 uint32_t v_pb2 = 0;
36682 uint32_t v_pb3 = 0;
36683 uint32_t v_pc0 = 0;
36684 uint32_t v_pc1 = 0;
36685 uint32_t v_pc2 = 0;
36686 uint32_t v_pc3 = 0;
36687
36688 {
36689 wuffs_base__slice_u8 i_slice_curr = a_curr;
36690 v_curr.ptr = i_slice_curr.ptr;
36691 wuffs_base__slice_u8 i_slice_prev = a_prev;
36692 v_prev.ptr = i_slice_prev.ptr;
36693 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
36694 v_curr.len = 4;
36695 v_prev.len = 4;
36696 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
36697 while (v_curr.ptr < i_end0_curr) {
36698 v_fb0 = ((uint32_t)(v_prev.ptr[0]));
36699 v_pp0 = ((uint32_t)(((uint32_t)(v_fa0 + v_fb0)) - v_fc0));
36700 v_pa0 = ((uint32_t)(v_pp0 - v_fa0));
36701 if (v_pa0 >= 2147483648) {
36702 v_pa0 = ((uint32_t)(0 - v_pa0));
36703 }
36704 v_pb0 = ((uint32_t)(v_pp0 - v_fb0));
36705 if (v_pb0 >= 2147483648) {
36706 v_pb0 = ((uint32_t)(0 - v_pb0));
36707 }
36708 v_pc0 = ((uint32_t)(v_pp0 - v_fc0));
36709 if (v_pc0 >= 2147483648) {
36710 v_pc0 = ((uint32_t)(0 - v_pc0));
36711 }
36712 if ((v_pa0 <= v_pb0) && (v_pa0 <= v_pc0)) {
36713 } else if (v_pb0 <= v_pc0) {
36714 v_fa0 = v_fb0;
36715 } else {
36716 v_fa0 = v_fc0;
36717 }
36718 v_curr.ptr[0] = ((uint8_t)(v_curr.ptr[0] + ((uint8_t)((v_fa0 & 255)))));
36719 v_fa0 = ((uint32_t)(v_curr.ptr[0]));
36720 v_fc0 = v_fb0;
36721 v_fb1 = ((uint32_t)(v_prev.ptr[1]));
36722 v_pp1 = ((uint32_t)(((uint32_t)(v_fa1 + v_fb1)) - v_fc1));
36723 v_pa1 = ((uint32_t)(v_pp1 - v_fa1));
36724 if (v_pa1 >= 2147483648) {
36725 v_pa1 = ((uint32_t)(0 - v_pa1));
36726 }
36727 v_pb1 = ((uint32_t)(v_pp1 - v_fb1));
36728 if (v_pb1 >= 2147483648) {
36729 v_pb1 = ((uint32_t)(0 - v_pb1));
36730 }
36731 v_pc1 = ((uint32_t)(v_pp1 - v_fc1));
36732 if (v_pc1 >= 2147483648) {
36733 v_pc1 = ((uint32_t)(0 - v_pc1));
36734 }
36735 if ((v_pa1 <= v_pb1) && (v_pa1 <= v_pc1)) {
36736 } else if (v_pb1 <= v_pc1) {
36737 v_fa1 = v_fb1;
36738 } else {
36739 v_fa1 = v_fc1;
36740 }
36741 v_curr.ptr[1] = ((uint8_t)(v_curr.ptr[1] + ((uint8_t)((v_fa1 & 255)))));
36742 v_fa1 = ((uint32_t)(v_curr.ptr[1]));
36743 v_fc1 = v_fb1;
36744 v_fb2 = ((uint32_t)(v_prev.ptr[2]));
36745 v_pp2 = ((uint32_t)(((uint32_t)(v_fa2 + v_fb2)) - v_fc2));
36746 v_pa2 = ((uint32_t)(v_pp2 - v_fa2));
36747 if (v_pa2 >= 2147483648) {
36748 v_pa2 = ((uint32_t)(0 - v_pa2));
36749 }
36750 v_pb2 = ((uint32_t)(v_pp2 - v_fb2));
36751 if (v_pb2 >= 2147483648) {
36752 v_pb2 = ((uint32_t)(0 - v_pb2));
36753 }
36754 v_pc2 = ((uint32_t)(v_pp2 - v_fc2));
36755 if (v_pc2 >= 2147483648) {
36756 v_pc2 = ((uint32_t)(0 - v_pc2));
36757 }
36758 if ((v_pa2 <= v_pb2) && (v_pa2 <= v_pc2)) {
36759 } else if (v_pb2 <= v_pc2) {
36760 v_fa2 = v_fb2;
36761 } else {
36762 v_fa2 = v_fc2;
36763 }
36764 v_curr.ptr[2] = ((uint8_t)(v_curr.ptr[2] + ((uint8_t)((v_fa2 & 255)))));
36765 v_fa2 = ((uint32_t)(v_curr.ptr[2]));
36766 v_fc2 = v_fb2;
36767 v_fb3 = ((uint32_t)(v_prev.ptr[3]));
36768 v_pp3 = ((uint32_t)(((uint32_t)(v_fa3 + v_fb3)) - v_fc3));
36769 v_pa3 = ((uint32_t)(v_pp3 - v_fa3));
36770 if (v_pa3 >= 2147483648) {
36771 v_pa3 = ((uint32_t)(0 - v_pa3));
36772 }
36773 v_pb3 = ((uint32_t)(v_pp3 - v_fb3));
36774 if (v_pb3 >= 2147483648) {
36775 v_pb3 = ((uint32_t)(0 - v_pb3));
36776 }
36777 v_pc3 = ((uint32_t)(v_pp3 - v_fc3));
36778 if (v_pc3 >= 2147483648) {
36779 v_pc3 = ((uint32_t)(0 - v_pc3));
36780 }
36781 if ((v_pa3 <= v_pb3) && (v_pa3 <= v_pc3)) {
36782 } else if (v_pb3 <= v_pc3) {
36783 v_fa3 = v_fb3;
36784 } else {
36785 v_fa3 = v_fc3;
36786 }
36787 v_curr.ptr[3] = ((uint8_t)(v_curr.ptr[3] + ((uint8_t)((v_fa3 & 255)))));
36788 v_fa3 = ((uint32_t)(v_curr.ptr[3]));
36789 v_fc3 = v_fb3;
36790 v_curr.ptr += 4;
36791 v_prev.ptr += 4;
36792 }
36793 v_curr.len = 0;
36794 v_prev.len = 0;
36795 }
36796 return wuffs_base__make_empty_struct();
36797}
36798
36799// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
36800// -------- func png.decoder.filter_1_distance_4_x86_sse42
36801
Nigel Tao7804ffe2021-10-07 21:58:26 +110036802#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100036803WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
36804static wuffs_base__empty_struct
36805wuffs_png__decoder__filter_1_distance_4_x86_sse42(
36806 wuffs_png__decoder* self,
36807 wuffs_base__slice_u8 a_curr) {
36808 wuffs_base__slice_u8 v_curr = {0};
36809 __m128i v_x128 = {0};
36810 __m128i v_a128 = {0};
36811
36812 {
36813 wuffs_base__slice_u8 i_slice_curr = a_curr;
36814 v_curr.ptr = i_slice_curr.ptr;
36815 v_curr.len = 4;
36816 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
36817 while (v_curr.ptr < i_end0_curr) {
36818 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36819 v_x128 = _mm_add_epi8(v_x128, v_a128);
36820 v_a128 = v_x128;
36821 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36822 v_curr.ptr += 4;
36823 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36824 v_x128 = _mm_add_epi8(v_x128, v_a128);
36825 v_a128 = v_x128;
36826 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36827 v_curr.ptr += 4;
36828 }
36829 v_curr.len = 4;
36830 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
36831 while (v_curr.ptr < i_end1_curr) {
36832 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36833 v_x128 = _mm_add_epi8(v_x128, v_a128);
36834 v_a128 = v_x128;
36835 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36836 v_curr.ptr += 4;
36837 }
36838 v_curr.len = 0;
36839 }
36840 return wuffs_base__make_empty_struct();
36841}
Nigel Tao7804ffe2021-10-07 21:58:26 +110036842#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100036843// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
36844
36845// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
36846// -------- func png.decoder.filter_3_distance_4_x86_sse42
36847
Nigel Tao7804ffe2021-10-07 21:58:26 +110036848#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100036849WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
36850static wuffs_base__empty_struct
36851wuffs_png__decoder__filter_3_distance_4_x86_sse42(
36852 wuffs_png__decoder* self,
36853 wuffs_base__slice_u8 a_curr,
36854 wuffs_base__slice_u8 a_prev) {
36855 wuffs_base__slice_u8 v_curr = {0};
36856 wuffs_base__slice_u8 v_prev = {0};
36857 __m128i v_x128 = {0};
36858 __m128i v_a128 = {0};
36859 __m128i v_b128 = {0};
36860 __m128i v_p128 = {0};
36861 __m128i v_k128 = {0};
36862
36863 if (((uint64_t)(a_prev.len)) == 0) {
36864 v_k128 = _mm_set1_epi8((int8_t)(254));
36865 {
36866 wuffs_base__slice_u8 i_slice_curr = a_curr;
36867 v_curr.ptr = i_slice_curr.ptr;
36868 v_curr.len = 4;
36869 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
36870 while (v_curr.ptr < i_end0_curr) {
36871 v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128);
36872 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36873 v_x128 = _mm_add_epi8(v_x128, v_p128);
36874 v_a128 = v_x128;
36875 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36876 v_curr.ptr += 4;
36877 v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128);
36878 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36879 v_x128 = _mm_add_epi8(v_x128, v_p128);
36880 v_a128 = v_x128;
36881 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36882 v_curr.ptr += 4;
36883 }
36884 v_curr.len = 4;
36885 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
36886 while (v_curr.ptr < i_end1_curr) {
36887 v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128);
36888 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36889 v_x128 = _mm_add_epi8(v_x128, v_p128);
36890 v_a128 = v_x128;
36891 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36892 v_curr.ptr += 4;
36893 }
36894 v_curr.len = 0;
36895 }
36896 } else {
36897 v_k128 = _mm_set1_epi8((int8_t)(1));
36898 {
36899 wuffs_base__slice_u8 i_slice_curr = a_curr;
36900 v_curr.ptr = i_slice_curr.ptr;
36901 wuffs_base__slice_u8 i_slice_prev = a_prev;
36902 v_prev.ptr = i_slice_prev.ptr;
36903 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
36904 v_curr.len = 4;
36905 v_prev.len = 4;
36906 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
36907 while (v_curr.ptr < i_end0_curr) {
36908 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
36909 v_p128 = _mm_avg_epu8(v_a128, v_b128);
36910 v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128)));
36911 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36912 v_x128 = _mm_add_epi8(v_x128, v_p128);
36913 v_a128 = v_x128;
36914 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36915 v_curr.ptr += 4;
36916 v_prev.ptr += 4;
36917 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
36918 v_p128 = _mm_avg_epu8(v_a128, v_b128);
36919 v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128)));
36920 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36921 v_x128 = _mm_add_epi8(v_x128, v_p128);
36922 v_a128 = v_x128;
36923 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36924 v_curr.ptr += 4;
36925 v_prev.ptr += 4;
36926 }
36927 v_curr.len = 4;
36928 v_prev.len = 4;
36929 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
36930 while (v_curr.ptr < i_end1_curr) {
36931 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
36932 v_p128 = _mm_avg_epu8(v_a128, v_b128);
36933 v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128)));
36934 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36935 v_x128 = _mm_add_epi8(v_x128, v_p128);
36936 v_a128 = v_x128;
36937 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
36938 v_curr.ptr += 4;
36939 v_prev.ptr += 4;
36940 }
36941 v_curr.len = 0;
36942 v_prev.len = 0;
36943 }
36944 }
36945 return wuffs_base__make_empty_struct();
36946}
Nigel Tao7804ffe2021-10-07 21:58:26 +110036947#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100036948// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
36949
36950// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
36951// -------- func png.decoder.filter_4_distance_3_x86_sse42
36952
Nigel Tao7804ffe2021-10-07 21:58:26 +110036953#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100036954WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
36955static wuffs_base__empty_struct
36956wuffs_png__decoder__filter_4_distance_3_x86_sse42(
36957 wuffs_png__decoder* self,
36958 wuffs_base__slice_u8 a_curr,
36959 wuffs_base__slice_u8 a_prev) {
36960 wuffs_base__slice_u8 v_curr = {0};
36961 wuffs_base__slice_u8 v_prev = {0};
36962 __m128i v_x128 = {0};
36963 __m128i v_a128 = {0};
36964 __m128i v_b128 = {0};
36965 __m128i v_c128 = {0};
36966 __m128i v_p128 = {0};
36967 __m128i v_pa128 = {0};
36968 __m128i v_pb128 = {0};
36969 __m128i v_pc128 = {0};
36970 __m128i v_smallest128 = {0};
36971 __m128i v_z128 = {0};
36972
36973 {
36974 wuffs_base__slice_u8 i_slice_curr = a_curr;
36975 v_curr.ptr = i_slice_curr.ptr;
36976 wuffs_base__slice_u8 i_slice_prev = a_prev;
36977 v_prev.ptr = i_slice_prev.ptr;
36978 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
36979 v_curr.len = 4;
36980 v_prev.len = 4;
36981 uint8_t* i_end0_curr = v_curr.ptr + wuffs_base__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 7, 6);
36982 while (v_curr.ptr < i_end0_curr) {
36983 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
36984 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
36985 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
36986 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
36987 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
36988 v_pa128 = _mm_abs_epi16(v_pa128);
36989 v_pb128 = _mm_abs_epi16(v_pb128);
36990 v_pc128 = _mm_abs_epi16(v_pc128);
36991 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
36992 v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128));
36993 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
36994 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
36995 v_x128 = _mm_add_epi8(v_x128, v_p128);
36996 v_a128 = v_x128;
36997 v_c128 = v_b128;
36998 v_x128 = _mm_packus_epi16(v_x128, v_x128);
36999 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
37000 v_curr.ptr += 3;
37001 v_prev.ptr += 3;
37002 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
37003 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
37004 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
37005 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
37006 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
37007 v_pa128 = _mm_abs_epi16(v_pa128);
37008 v_pb128 = _mm_abs_epi16(v_pb128);
37009 v_pc128 = _mm_abs_epi16(v_pc128);
37010 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
37011 v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128));
37012 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
37013 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
37014 v_x128 = _mm_add_epi8(v_x128, v_p128);
37015 v_a128 = v_x128;
37016 v_c128 = v_b128;
37017 v_x128 = _mm_packus_epi16(v_x128, v_x128);
37018 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
37019 v_curr.ptr += 3;
37020 v_prev.ptr += 3;
37021 }
37022 v_curr.len = 4;
37023 v_prev.len = 4;
37024 uint8_t* i_end1_curr = v_curr.ptr + wuffs_base__iterate_total_advance((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)), 4, 3);
37025 while (v_curr.ptr < i_end1_curr) {
37026 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
37027 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
37028 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
37029 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
37030 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
37031 v_pa128 = _mm_abs_epi16(v_pa128);
37032 v_pb128 = _mm_abs_epi16(v_pb128);
37033 v_pc128 = _mm_abs_epi16(v_pc128);
37034 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
37035 v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128));
37036 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
37037 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
37038 v_x128 = _mm_add_epi8(v_x128, v_p128);
37039 v_a128 = v_x128;
37040 v_c128 = v_b128;
37041 v_x128 = _mm_packus_epi16(v_x128, v_x128);
37042 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
37043 v_curr.ptr += 3;
37044 v_prev.ptr += 3;
37045 }
37046 v_curr.len = 3;
37047 v_prev.len = 3;
37048 uint8_t* i_end2_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
37049 while (v_curr.ptr < i_end2_curr) {
37050 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u24le__no_bounds_check(v_prev.ptr)));
37051 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
37052 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
37053 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
37054 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
37055 v_pa128 = _mm_abs_epi16(v_pa128);
37056 v_pb128 = _mm_abs_epi16(v_pb128);
37057 v_pc128 = _mm_abs_epi16(v_pc128);
37058 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
37059 v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128));
37060 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u24le__no_bounds_check(v_curr.ptr)));
37061 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
37062 v_x128 = _mm_add_epi8(v_x128, v_p128);
37063 v_x128 = _mm_packus_epi16(v_x128, v_x128);
37064 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
37065 v_curr.ptr += 3;
37066 v_prev.ptr += 3;
37067 }
37068 v_curr.len = 0;
37069 v_prev.len = 0;
37070 }
37071 return wuffs_base__make_empty_struct();
37072}
Nigel Tao7804ffe2021-10-07 21:58:26 +110037073#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037074// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
37075
37076// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
37077// -------- func png.decoder.filter_4_distance_4_x86_sse42
37078
Nigel Tao7804ffe2021-10-07 21:58:26 +110037079#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037080WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
37081static wuffs_base__empty_struct
37082wuffs_png__decoder__filter_4_distance_4_x86_sse42(
37083 wuffs_png__decoder* self,
37084 wuffs_base__slice_u8 a_curr,
37085 wuffs_base__slice_u8 a_prev) {
37086 wuffs_base__slice_u8 v_curr = {0};
37087 wuffs_base__slice_u8 v_prev = {0};
37088 __m128i v_x128 = {0};
37089 __m128i v_a128 = {0};
37090 __m128i v_b128 = {0};
37091 __m128i v_c128 = {0};
37092 __m128i v_p128 = {0};
37093 __m128i v_pa128 = {0};
37094 __m128i v_pb128 = {0};
37095 __m128i v_pc128 = {0};
37096 __m128i v_smallest128 = {0};
37097 __m128i v_z128 = {0};
37098
37099 {
37100 wuffs_base__slice_u8 i_slice_curr = a_curr;
37101 v_curr.ptr = i_slice_curr.ptr;
37102 wuffs_base__slice_u8 i_slice_prev = a_prev;
37103 v_prev.ptr = i_slice_prev.ptr;
37104 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
37105 v_curr.len = 4;
37106 v_prev.len = 4;
37107 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
37108 while (v_curr.ptr < i_end0_curr) {
37109 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
37110 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
37111 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
37112 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
37113 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
37114 v_pa128 = _mm_abs_epi16(v_pa128);
37115 v_pb128 = _mm_abs_epi16(v_pb128);
37116 v_pc128 = _mm_abs_epi16(v_pc128);
37117 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
37118 v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128));
37119 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
37120 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
37121 v_x128 = _mm_add_epi8(v_x128, v_p128);
37122 v_a128 = v_x128;
37123 v_c128 = v_b128;
37124 v_x128 = _mm_packus_epi16(v_x128, v_x128);
37125 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
37126 v_curr.ptr += 4;
37127 v_prev.ptr += 4;
37128 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
37129 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
37130 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
37131 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
37132 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
37133 v_pa128 = _mm_abs_epi16(v_pa128);
37134 v_pb128 = _mm_abs_epi16(v_pb128);
37135 v_pc128 = _mm_abs_epi16(v_pc128);
37136 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
37137 v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128));
37138 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
37139 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
37140 v_x128 = _mm_add_epi8(v_x128, v_p128);
37141 v_a128 = v_x128;
37142 v_c128 = v_b128;
37143 v_x128 = _mm_packus_epi16(v_x128, v_x128);
37144 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
37145 v_curr.ptr += 4;
37146 v_prev.ptr += 4;
37147 }
37148 v_curr.len = 4;
37149 v_prev.len = 4;
37150 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
37151 while (v_curr.ptr < i_end1_curr) {
37152 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
37153 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
37154 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
37155 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
37156 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
37157 v_pa128 = _mm_abs_epi16(v_pa128);
37158 v_pb128 = _mm_abs_epi16(v_pb128);
37159 v_pc128 = _mm_abs_epi16(v_pc128);
37160 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
37161 v_p128 = _mm_blendv_epi8(_mm_blendv_epi8(v_c128, v_b128, _mm_cmpeq_epi16(v_smallest128, v_pb128)), v_a128, _mm_cmpeq_epi16(v_smallest128, v_pa128));
37162 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
37163 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
37164 v_x128 = _mm_add_epi8(v_x128, v_p128);
37165 v_a128 = v_x128;
37166 v_c128 = v_b128;
37167 v_x128 = _mm_packus_epi16(v_x128, v_x128);
37168 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
37169 v_curr.ptr += 4;
37170 v_prev.ptr += 4;
37171 }
37172 v_curr.len = 0;
37173 v_prev.len = 0;
37174 }
37175 return wuffs_base__make_empty_struct();
37176}
Nigel Tao7804ffe2021-10-07 21:58:26 +110037177#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037178// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
37179
37180// -------- func png.decoder.set_quirk_enabled
37181
37182WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
37183wuffs_png__decoder__set_quirk_enabled(
37184 wuffs_png__decoder* self,
37185 uint32_t a_quirk,
37186 bool a_enabled) {
37187 if (!self) {
37188 return wuffs_base__make_empty_struct();
37189 }
37190 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
37191 return wuffs_base__make_empty_struct();
37192 }
37193
37194 if (a_quirk == 1) {
37195 self->private_impl.f_ignore_checksum = a_enabled;
37196 wuffs_zlib__decoder__set_quirk_enabled(&self->private_data.f_zlib, a_quirk, a_enabled);
37197 }
37198 return wuffs_base__make_empty_struct();
37199}
37200
37201// -------- func png.decoder.decode_image_config
37202
37203WUFFS_BASE__MAYBE_STATIC wuffs_base__status
37204wuffs_png__decoder__decode_image_config(
37205 wuffs_png__decoder* self,
37206 wuffs_base__image_config* a_dst,
37207 wuffs_base__io_buffer* a_src) {
37208 if (!self) {
37209 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
37210 }
37211 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
37212 return wuffs_base__make_status(
37213 (self->private_impl.magic == WUFFS_BASE__DISABLED)
37214 ? wuffs_base__error__disabled_by_previous_error
37215 : wuffs_base__error__initialize_not_called);
37216 }
37217 if (!a_src) {
37218 self->private_impl.magic = WUFFS_BASE__DISABLED;
37219 return wuffs_base__make_status(wuffs_base__error__bad_argument);
37220 }
37221 if ((self->private_impl.active_coroutine != 0) &&
37222 (self->private_impl.active_coroutine != 1)) {
37223 self->private_impl.magic = WUFFS_BASE__DISABLED;
37224 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
37225 }
37226 self->private_impl.active_coroutine = 0;
37227 wuffs_base__status status = wuffs_base__make_status(NULL);
37228
37229 uint64_t v_magic = 0;
37230 uint64_t v_mark = 0;
37231 uint32_t v_checksum_have = 0;
37232 uint32_t v_checksum_want = 0;
37233 wuffs_base__status v_status = wuffs_base__make_status(NULL);
37234
37235 const uint8_t* iop_a_src = NULL;
37236 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37237 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37238 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37239 if (a_src) {
37240 io0_a_src = a_src->data.ptr;
37241 io1_a_src = io0_a_src + a_src->meta.ri;
37242 iop_a_src = io1_a_src;
37243 io2_a_src = io0_a_src + a_src->meta.wi;
37244 }
37245
37246 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
37247 if (coro_susp_point) {
37248 v_checksum_have = self->private_data.s_decode_image_config[0].v_checksum_have;
37249 }
37250 switch (coro_susp_point) {
37251 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
37252
Nigel Taobf9dab32021-11-18 19:19:55 +110037253 if (self->private_impl.f_call_sequence == 2) {
37254 if (self->private_impl.f_metadata_fourcc != 0) {
37255 self->private_impl.f_call_sequence = 1;
37256 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
37257 goto ok;
37258 }
37259 } else if (self->private_impl.f_call_sequence != 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100037260 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
37261 goto exit;
Nigel Taobf9dab32021-11-18 19:19:55 +110037262 } else {
Nigel Taoe360a532021-04-05 22:47:03 +100037263 {
Nigel Taobf9dab32021-11-18 19:19:55 +110037264 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
37265 uint64_t t_0;
37266 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) {
37267 t_0 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src);
37268 iop_a_src += 8;
Nigel Taoe360a532021-04-05 22:47:03 +100037269 } else {
37270 self->private_data.s_decode_image_config[0].scratch = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110037271 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
Nigel Taoe360a532021-04-05 22:47:03 +100037272 while (true) {
37273 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37274 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37275 goto suspend;
37276 }
37277 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
Nigel Taobf9dab32021-11-18 19:19:55 +110037278 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
Nigel Taoe360a532021-04-05 22:47:03 +100037279 *scratch <<= 8;
Nigel Taobf9dab32021-11-18 19:19:55 +110037280 *scratch >>= 8;
37281 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
37282 if (num_bits_0 == 56) {
37283 t_0 = ((uint64_t)(*scratch));
Nigel Taoe360a532021-04-05 22:47:03 +100037284 break;
37285 }
Nigel Taobf9dab32021-11-18 19:19:55 +110037286 num_bits_0 += 8;
37287 *scratch |= ((uint64_t)(num_bits_0)) << 56;
Nigel Taoe360a532021-04-05 22:47:03 +100037288 }
37289 }
Nigel Taobf9dab32021-11-18 19:19:55 +110037290 v_magic = t_0;
37291 }
37292 if (v_magic != 727905341920923785) {
37293 status = wuffs_base__make_status(wuffs_png__error__bad_header);
37294 goto exit;
37295 }
37296 {
37297 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
37298 uint64_t t_1;
37299 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) {
37300 t_1 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src);
37301 iop_a_src += 8;
37302 } else {
37303 self->private_data.s_decode_image_config[0].scratch = 0;
37304 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
37305 while (true) {
37306 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37307 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37308 goto suspend;
37309 }
37310 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
37311 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
37312 *scratch <<= 8;
37313 *scratch >>= 8;
37314 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
37315 if (num_bits_1 == 56) {
37316 t_1 = ((uint64_t)(*scratch));
37317 break;
37318 }
37319 num_bits_1 += 8;
37320 *scratch |= ((uint64_t)(num_bits_1)) << 56;
37321 }
37322 }
37323 v_magic = t_1;
37324 }
37325 if (v_magic != 5927942488114331648) {
37326 status = wuffs_base__make_status(wuffs_png__error__bad_header);
37327 goto exit;
37328 }
37329 self->private_impl.f_chunk_type_array[0] = 73;
37330 self->private_impl.f_chunk_type_array[1] = 72;
37331 self->private_impl.f_chunk_type_array[2] = 68;
37332 self->private_impl.f_chunk_type_array[3] = 82;
37333 wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32,
37334 sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
37335 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4));
37336 while (true) {
37337 v_mark = ((uint64_t)(iop_a_src - io0_a_src));
37338 {
37339 if (a_src) {
37340 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37341 }
37342 wuffs_base__status t_2 = wuffs_png__decoder__decode_ihdr(self, a_src);
37343 v_status = t_2;
37344 if (a_src) {
37345 iop_a_src = a_src->data.ptr + a_src->meta.ri;
37346 }
37347 }
37348 if ( ! self->private_impl.f_ignore_checksum) {
37349 v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src));
37350 }
37351 if (wuffs_base__status__is_ok(&v_status)) {
37352 goto label__0__break;
37353 }
37354 status = v_status;
37355 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
37356 }
37357 label__0__break:;
37358 {
37359 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
37360 uint32_t t_3;
37361 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
37362 t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
37363 iop_a_src += 4;
37364 } else {
37365 self->private_data.s_decode_image_config[0].scratch = 0;
37366 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
37367 while (true) {
37368 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37369 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37370 goto suspend;
37371 }
37372 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
37373 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
37374 *scratch >>= 8;
37375 *scratch <<= 8;
37376 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
37377 if (num_bits_3 == 24) {
37378 t_3 = ((uint32_t)(*scratch >> 32));
37379 break;
37380 }
37381 num_bits_3 += 8;
37382 *scratch |= ((uint64_t)(num_bits_3));
37383 }
37384 }
37385 v_checksum_want = t_3;
37386 }
37387 if ( ! self->private_impl.f_ignore_checksum && (v_checksum_have != v_checksum_want)) {
37388 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
37389 goto exit;
37390 }
37391 }
37392 while (true) {
37393 while (((uint64_t)(io2_a_src - iop_a_src)) < 8) {
37394 if (a_src && a_src->meta.closed) {
37395 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
37396 goto exit;
37397 }
37398 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37399 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
37400 }
37401 self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
37402 self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32)));
37403 if (self->private_impl.f_chunk_type == 1413563465) {
37404 if ( ! self->private_impl.f_seen_actl || self->private_impl.f_seen_fctl) {
37405 goto label__1__break;
37406 }
37407 self->private_impl.f_seen_idat = true;
37408 } else if (self->private_impl.f_chunk_type == 1413571686) {
37409 if (self->private_impl.f_seen_idat && self->private_impl.f_seen_fctl) {
37410 goto label__1__break;
37411 }
37412 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
37413 goto exit;
37414 }
37415 iop_a_src += 8;
37416 if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32) == 0)) {
37417 self->private_impl.f_chunk_type_array[0] = ((uint8_t)(((self->private_impl.f_chunk_type >> 0) & 255)));
37418 self->private_impl.f_chunk_type_array[1] = ((uint8_t)(((self->private_impl.f_chunk_type >> 8) & 255)));
37419 self->private_impl.f_chunk_type_array[2] = ((uint8_t)(((self->private_impl.f_chunk_type >> 16) & 255)));
37420 self->private_impl.f_chunk_type_array[3] = ((uint8_t)(((self->private_impl.f_chunk_type >> 24) & 255)));
37421 wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32,
37422 sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
37423 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4));
37424 }
37425 while (true) {
37426 v_mark = ((uint64_t)(iop_a_src - io0_a_src));
37427 {
37428 if (a_src) {
37429 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37430 }
37431 wuffs_base__status t_4 = wuffs_png__decoder__decode_other_chunk(self, a_src);
37432 v_status = t_4;
37433 if (a_src) {
37434 iop_a_src = a_src->data.ptr + a_src->meta.ri;
37435 }
37436 }
37437 if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32) == 0)) {
37438 v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src));
37439 }
37440 if (wuffs_base__status__is_ok(&v_status)) {
37441 goto label__2__break;
37442 }
37443 status = v_status;
37444 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
37445 }
37446 label__2__break:;
37447 if (self->private_impl.f_metadata_fourcc != 0) {
37448 self->private_impl.f_call_sequence = 1;
37449 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
37450 goto ok;
Nigel Taoe360a532021-04-05 22:47:03 +100037451 }
37452 {
37453 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
37454 uint32_t t_5;
37455 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
Nigel Taobf9dab32021-11-18 19:19:55 +110037456 t_5 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
Nigel Taoe360a532021-04-05 22:47:03 +100037457 iop_a_src += 4;
37458 } else {
37459 self->private_data.s_decode_image_config[0].scratch = 0;
37460 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
37461 while (true) {
37462 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37463 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37464 goto suspend;
37465 }
37466 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
Nigel Taobf9dab32021-11-18 19:19:55 +110037467 uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFF));
Nigel Taoe360a532021-04-05 22:47:03 +100037468 *scratch >>= 8;
Nigel Taobf9dab32021-11-18 19:19:55 +110037469 *scratch <<= 8;
37470 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5);
Nigel Taoe360a532021-04-05 22:47:03 +100037471 if (num_bits_5 == 24) {
Nigel Taobf9dab32021-11-18 19:19:55 +110037472 t_5 = ((uint32_t)(*scratch >> 32));
Nigel Taoe360a532021-04-05 22:47:03 +100037473 break;
37474 }
37475 num_bits_5 += 8;
Nigel Taobf9dab32021-11-18 19:19:55 +110037476 *scratch |= ((uint64_t)(num_bits_5));
Nigel Taoe360a532021-04-05 22:47:03 +100037477 }
37478 }
Nigel Taobf9dab32021-11-18 19:19:55 +110037479 v_checksum_want = t_5;
Nigel Taoe360a532021-04-05 22:47:03 +100037480 }
Nigel Taobf9dab32021-11-18 19:19:55 +110037481 if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32) == 0) && (v_checksum_have != v_checksum_want)) {
Nigel Taoe360a532021-04-05 22:47:03 +100037482 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
37483 goto exit;
37484 }
37485 }
37486 label__1__break:;
37487 if ((self->private_impl.f_color_type == 3) && ! self->private_impl.f_seen_plte) {
37488 status = wuffs_base__make_status(wuffs_png__error__missing_palette);
37489 goto exit;
37490 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100037491 self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)));
Nigel Taobf9dab32021-11-18 19:19:55 +110037492 self->private_impl.f_first_config_io_position = self->private_impl.f_frame_config_io_position;
Nigel Taoe360a532021-04-05 22:47:03 +100037493 if (a_dst != NULL) {
37494 wuffs_base__image_config__set(
37495 a_dst,
37496 self->private_impl.f_dst_pixfmt,
37497 0,
37498 self->private_impl.f_width,
37499 self->private_impl.f_height,
Nigel Taobf9dab32021-11-18 19:19:55 +110037500 self->private_impl.f_first_config_io_position,
Nigel Taoe360a532021-04-05 22:47:03 +100037501 ((self->private_impl.f_color_type <= 3) && ! self->private_impl.f_seen_trns));
37502 }
Nigel Taobf9dab32021-11-18 19:19:55 +110037503 if ( ! self->private_impl.f_seen_actl) {
37504 self->private_impl.f_num_animation_frames_value = 1;
37505 self->private_impl.f_first_rect_x0 = 0;
37506 self->private_impl.f_first_rect_y0 = 0;
37507 self->private_impl.f_first_rect_x1 = self->private_impl.f_width;
37508 self->private_impl.f_first_rect_y1 = self->private_impl.f_height;
37509 self->private_impl.f_first_duration = 0;
37510 self->private_impl.f_first_disposal = 0;
37511 self->private_impl.f_first_overwrite_instead_of_blend = false;
37512 }
Nigel Taoe360a532021-04-05 22:47:03 +100037513 self->private_impl.f_call_sequence = 3;
37514
Nigel Taoe360a532021-04-05 22:47:03 +100037515 ok:
37516 self->private_impl.p_decode_image_config[0] = 0;
37517 goto exit;
37518 }
37519
37520 goto suspend;
37521 suspend:
37522 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
37523 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
37524 self->private_data.s_decode_image_config[0].v_checksum_have = v_checksum_have;
37525
37526 goto exit;
37527 exit:
37528 if (a_src) {
37529 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37530 }
37531
37532 if (wuffs_base__status__is_error(&status)) {
37533 self->private_impl.magic = WUFFS_BASE__DISABLED;
37534 }
37535 return status;
37536}
37537
37538// -------- func png.decoder.decode_ihdr
37539
37540static wuffs_base__status
37541wuffs_png__decoder__decode_ihdr(
37542 wuffs_png__decoder* self,
37543 wuffs_base__io_buffer* a_src) {
37544 wuffs_base__status status = wuffs_base__make_status(NULL);
37545
37546 uint32_t v_a32 = 0;
37547 uint8_t v_a8 = 0;
37548
37549 const uint8_t* iop_a_src = NULL;
37550 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37551 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37552 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37553 if (a_src) {
37554 io0_a_src = a_src->data.ptr;
37555 io1_a_src = io0_a_src + a_src->meta.ri;
37556 iop_a_src = io1_a_src;
37557 io2_a_src = io0_a_src + a_src->meta.wi;
37558 }
37559
37560 uint32_t coro_susp_point = self->private_impl.p_decode_ihdr[0];
37561 switch (coro_susp_point) {
37562 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
37563
37564 {
37565 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
37566 uint32_t t_0;
37567 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
37568 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
37569 iop_a_src += 4;
37570 } else {
37571 self->private_data.s_decode_ihdr[0].scratch = 0;
37572 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
37573 while (true) {
37574 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37575 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37576 goto suspend;
37577 }
37578 uint64_t* scratch = &self->private_data.s_decode_ihdr[0].scratch;
37579 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
37580 *scratch >>= 8;
37581 *scratch <<= 8;
37582 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
37583 if (num_bits_0 == 24) {
37584 t_0 = ((uint32_t)(*scratch >> 32));
37585 break;
37586 }
37587 num_bits_0 += 8;
37588 *scratch |= ((uint64_t)(num_bits_0));
37589 }
37590 }
37591 v_a32 = t_0;
37592 }
Nigel Tao5571bfe2021-06-24 22:44:29 +100037593 if ((v_a32 == 0) || (v_a32 >= 2147483648)) {
Nigel Taoe360a532021-04-05 22:47:03 +100037594 status = wuffs_base__make_status(wuffs_png__error__bad_header);
37595 goto exit;
37596 } else if (v_a32 >= 16777216) {
37597 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
37598 goto exit;
37599 }
37600 self->private_impl.f_width = v_a32;
37601 {
37602 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
37603 uint32_t t_1;
37604 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
37605 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
37606 iop_a_src += 4;
37607 } else {
37608 self->private_data.s_decode_ihdr[0].scratch = 0;
37609 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
37610 while (true) {
37611 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37612 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37613 goto suspend;
37614 }
37615 uint64_t* scratch = &self->private_data.s_decode_ihdr[0].scratch;
37616 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
37617 *scratch >>= 8;
37618 *scratch <<= 8;
37619 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
37620 if (num_bits_1 == 24) {
37621 t_1 = ((uint32_t)(*scratch >> 32));
37622 break;
37623 }
37624 num_bits_1 += 8;
37625 *scratch |= ((uint64_t)(num_bits_1));
37626 }
37627 }
37628 v_a32 = t_1;
37629 }
Nigel Tao5571bfe2021-06-24 22:44:29 +100037630 if ((v_a32 == 0) || (v_a32 >= 2147483648)) {
Nigel Taoe360a532021-04-05 22:47:03 +100037631 status = wuffs_base__make_status(wuffs_png__error__bad_header);
37632 goto exit;
37633 } else if (v_a32 >= 16777216) {
37634 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
37635 goto exit;
37636 }
37637 self->private_impl.f_height = v_a32;
37638 {
37639 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
37640 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37641 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37642 goto suspend;
37643 }
37644 uint8_t t_2 = *iop_a_src++;
37645 v_a8 = t_2;
37646 }
37647 if (v_a8 > 16) {
37648 status = wuffs_base__make_status(wuffs_png__error__bad_header);
37649 goto exit;
37650 }
37651 self->private_impl.f_depth = v_a8;
37652 {
37653 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
37654 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37655 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37656 goto suspend;
37657 }
37658 uint8_t t_3 = *iop_a_src++;
37659 v_a8 = t_3;
37660 }
37661 if ((v_a8 == 1) || (v_a8 == 5) || (v_a8 > 6)) {
37662 status = wuffs_base__make_status(wuffs_png__error__bad_header);
37663 goto exit;
37664 }
37665 self->private_impl.f_color_type = v_a8;
37666 {
37667 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
37668 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37669 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37670 goto suspend;
37671 }
37672 uint8_t t_4 = *iop_a_src++;
37673 v_a8 = t_4;
37674 }
37675 if (v_a8 != 0) {
Nigel Taobf9dab32021-11-18 19:19:55 +110037676 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method);
Nigel Taoe360a532021-04-05 22:47:03 +100037677 goto exit;
37678 }
37679 {
37680 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
37681 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37682 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37683 goto suspend;
37684 }
37685 uint8_t t_5 = *iop_a_src++;
37686 v_a8 = t_5;
37687 }
37688 if (v_a8 != 0) {
37689 status = wuffs_base__make_status(wuffs_png__error__bad_header);
37690 goto exit;
37691 }
37692 {
37693 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
37694 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37695 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37696 goto suspend;
37697 }
37698 uint8_t t_6 = *iop_a_src++;
37699 v_a8 = t_6;
37700 }
37701 if (v_a8 == 0) {
37702 self->private_impl.f_interlace_pass = 0;
37703 } else if (v_a8 == 1) {
37704 self->private_impl.f_interlace_pass = 1;
37705 self->private_impl.choosy_filter_and_swizzle = (
37706 &wuffs_png__decoder__filter_and_swizzle_tricky);
37707 } else {
37708 status = wuffs_base__make_status(wuffs_png__error__bad_header);
37709 goto exit;
37710 }
37711 self->private_impl.f_filter_distance = 0;
37712 wuffs_png__decoder__assign_filter_distance(self);
37713 if (self->private_impl.f_filter_distance == 0) {
Nigel Taobf9dab32021-11-18 19:19:55 +110037714 status = wuffs_base__make_status(wuffs_png__error__bad_header);
Nigel Taoe360a532021-04-05 22:47:03 +100037715 goto exit;
37716 }
37717 self->private_impl.f_overall_workbuf_length = (((uint64_t)(self->private_impl.f_height)) * (1 + wuffs_png__decoder__calculate_bytes_per_row(self, self->private_impl.f_width)));
37718 wuffs_png__decoder__choose_filter_implementations(self);
37719
37720 goto ok;
37721 ok:
37722 self->private_impl.p_decode_ihdr[0] = 0;
37723 goto exit;
37724 }
37725
37726 goto suspend;
37727 suspend:
37728 self->private_impl.p_decode_ihdr[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
37729
37730 goto exit;
37731 exit:
37732 if (a_src) {
37733 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37734 }
37735
37736 return status;
37737}
37738
37739// -------- func png.decoder.assign_filter_distance
37740
37741static wuffs_base__empty_struct
37742wuffs_png__decoder__assign_filter_distance(
37743 wuffs_png__decoder* self) {
37744 if (self->private_impl.f_depth < 8) {
Nigel Taobf9dab32021-11-18 19:19:55 +110037745 if ((self->private_impl.f_depth != 1) && (self->private_impl.f_depth != 2) && (self->private_impl.f_depth != 4)) {
37746 return wuffs_base__make_empty_struct();
37747 } else if (self->private_impl.f_color_type == 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100037748 self->private_impl.f_dst_pixfmt = 536870920;
37749 self->private_impl.f_src_pixfmt = 536870920;
37750 } else if (self->private_impl.f_color_type == 3) {
37751 self->private_impl.f_dst_pixfmt = 2198077448;
37752 self->private_impl.f_src_pixfmt = 2198077448;
37753 } else {
37754 return wuffs_base__make_empty_struct();
37755 }
37756 self->private_impl.f_filter_distance = 1;
37757 self->private_impl.choosy_filter_and_swizzle = (
37758 &wuffs_png__decoder__filter_and_swizzle_tricky);
37759 } else if (self->private_impl.f_color_type == 0) {
37760 if (self->private_impl.f_depth == 8) {
37761 self->private_impl.f_dst_pixfmt = 536870920;
37762 self->private_impl.f_src_pixfmt = 536870920;
37763 self->private_impl.f_filter_distance = 1;
37764 } else if (self->private_impl.f_depth == 16) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100037765 self->private_impl.f_dst_pixfmt = 536870923;
Nigel Taoe360a532021-04-05 22:47:03 +100037766 self->private_impl.f_src_pixfmt = 537919499;
37767 self->private_impl.f_filter_distance = 2;
37768 }
37769 } else if (self->private_impl.f_color_type == 2) {
37770 if (self->private_impl.f_depth == 8) {
37771 self->private_impl.f_dst_pixfmt = 2147485832;
37772 self->private_impl.f_src_pixfmt = 2684356744;
37773 self->private_impl.f_filter_distance = 3;
37774 } else if (self->private_impl.f_depth == 16) {
37775 self->private_impl.f_dst_pixfmt = 2164308923;
37776 self->private_impl.f_src_pixfmt = 2164308923;
37777 self->private_impl.f_filter_distance = 6;
37778 self->private_impl.choosy_filter_and_swizzle = (
37779 &wuffs_png__decoder__filter_and_swizzle_tricky);
37780 }
37781 } else if (self->private_impl.f_color_type == 3) {
37782 if (self->private_impl.f_depth == 8) {
37783 self->private_impl.f_dst_pixfmt = 2198077448;
37784 self->private_impl.f_src_pixfmt = 2198077448;
37785 self->private_impl.f_filter_distance = 1;
37786 }
37787 } else if (self->private_impl.f_color_type == 4) {
37788 if (self->private_impl.f_depth == 8) {
37789 self->private_impl.f_dst_pixfmt = 2164295816;
37790 self->private_impl.f_src_pixfmt = 2164295816;
37791 self->private_impl.f_filter_distance = 2;
37792 self->private_impl.choosy_filter_and_swizzle = (
37793 &wuffs_png__decoder__filter_and_swizzle_tricky);
37794 } else if (self->private_impl.f_depth == 16) {
37795 self->private_impl.f_dst_pixfmt = 2164308923;
37796 self->private_impl.f_src_pixfmt = 2164308923;
37797 self->private_impl.f_filter_distance = 4;
37798 self->private_impl.choosy_filter_and_swizzle = (
37799 &wuffs_png__decoder__filter_and_swizzle_tricky);
37800 }
37801 } else if (self->private_impl.f_color_type == 6) {
37802 if (self->private_impl.f_depth == 8) {
37803 self->private_impl.f_dst_pixfmt = 2164295816;
37804 self->private_impl.f_src_pixfmt = 2701166728;
37805 self->private_impl.f_filter_distance = 4;
37806 } else if (self->private_impl.f_depth == 16) {
37807 self->private_impl.f_dst_pixfmt = 2164308923;
37808 self->private_impl.f_src_pixfmt = 2164308923;
37809 self->private_impl.f_filter_distance = 8;
37810 self->private_impl.choosy_filter_and_swizzle = (
37811 &wuffs_png__decoder__filter_and_swizzle_tricky);
37812 }
37813 }
37814 return wuffs_base__make_empty_struct();
37815}
37816
37817// -------- func png.decoder.calculate_bytes_per_row
37818
37819static uint64_t
37820wuffs_png__decoder__calculate_bytes_per_row(
37821 const wuffs_png__decoder* self,
37822 uint32_t a_width) {
37823 uint64_t v_bytes_per_channel = 0;
37824
37825 if (self->private_impl.f_depth == 1) {
37826 return ((uint64_t)(((a_width + 7) / 8)));
37827 } else if (self->private_impl.f_depth == 2) {
37828 return ((uint64_t)(((a_width + 3) / 4)));
37829 } else if (self->private_impl.f_depth == 4) {
37830 return ((uint64_t)(((a_width + 1) / 2)));
37831 }
37832 v_bytes_per_channel = ((uint64_t)((self->private_impl.f_depth >> 3)));
37833 return (((uint64_t)(a_width)) * v_bytes_per_channel * ((uint64_t)(WUFFS_PNG__NUM_CHANNELS[self->private_impl.f_color_type])));
37834}
37835
37836// -------- func png.decoder.choose_filter_implementations
37837
37838static wuffs_base__empty_struct
37839wuffs_png__decoder__choose_filter_implementations(
37840 wuffs_png__decoder* self) {
37841 if (self->private_impl.f_filter_distance == 3) {
37842 self->private_impl.choosy_filter_1 = (
37843 &wuffs_png__decoder__filter_1_distance_3_fallback);
37844 self->private_impl.choosy_filter_3 = (
37845 &wuffs_png__decoder__filter_3_distance_3_fallback);
37846 self->private_impl.choosy_filter_4 = (
37847#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37848 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_4_distance_3_arm_neon :
37849#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110037850#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037851 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_4_distance_3_x86_sse42 :
37852#endif
37853 &wuffs_png__decoder__filter_4_distance_3_fallback);
37854 } else if (self->private_impl.f_filter_distance == 4) {
37855 self->private_impl.choosy_filter_1 = (
37856#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37857 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_1_distance_4_arm_neon :
37858#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110037859#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037860 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_1_distance_4_x86_sse42 :
37861#endif
37862 &wuffs_png__decoder__filter_1_distance_4_fallback);
37863 self->private_impl.choosy_filter_3 = (
37864#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37865 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_3_distance_4_arm_neon :
37866#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110037867#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037868 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_3_distance_4_x86_sse42 :
37869#endif
37870 &wuffs_png__decoder__filter_3_distance_4_fallback);
37871 self->private_impl.choosy_filter_4 = (
37872#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37873 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_4_distance_4_arm_neon :
37874#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110037875#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037876 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_4_distance_4_x86_sse42 :
37877#endif
37878 &wuffs_png__decoder__filter_4_distance_4_fallback);
37879 }
37880 return wuffs_base__make_empty_struct();
37881}
37882
37883// -------- func png.decoder.decode_other_chunk
37884
37885static wuffs_base__status
37886wuffs_png__decoder__decode_other_chunk(
37887 wuffs_png__decoder* self,
37888 wuffs_base__io_buffer* a_src) {
37889 wuffs_base__status status = wuffs_base__make_status(NULL);
37890
37891 const uint8_t* iop_a_src = NULL;
37892 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37893 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37894 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37895 if (a_src) {
37896 io0_a_src = a_src->data.ptr;
37897 io1_a_src = io0_a_src + a_src->meta.ri;
37898 iop_a_src = io1_a_src;
37899 io2_a_src = io0_a_src + a_src->meta.wi;
37900 }
37901
37902 uint32_t coro_susp_point = self->private_impl.p_decode_other_chunk[0];
37903 switch (coro_susp_point) {
37904 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
37905
37906 if (self->private_impl.f_chunk_type == 1163152464) {
37907 if (self->private_impl.f_seen_plte || (self->private_impl.f_color_type != 3)) {
37908 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
37909 goto exit;
37910 }
37911 if (a_src) {
37912 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37913 }
37914 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
37915 status = wuffs_png__decoder__decode_plte(self, a_src);
37916 if (a_src) {
37917 iop_a_src = a_src->data.ptr + a_src->meta.ri;
37918 }
37919 if (status.repr) {
37920 goto suspend;
37921 }
37922 self->private_impl.f_seen_plte = true;
Nigel Taobf9dab32021-11-18 19:19:55 +110037923 } else if ((self->private_impl.f_chunk_type & 32) == 0) {
37924 if (self->private_impl.f_chunk_type != 1413563465) {
37925 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
37926 goto exit;
37927 }
37928 } else if (self->private_impl.f_chunk_type == 1280598881) {
37929 if (self->private_impl.f_seen_actl) {
37930 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
37931 goto exit;
37932 }
37933 if (a_src) {
37934 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37935 }
37936 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
37937 status = wuffs_png__decoder__decode_actl(self, a_src);
37938 if (a_src) {
37939 iop_a_src = a_src->data.ptr + a_src->meta.ri;
37940 }
37941 if (status.repr) {
37942 goto suspend;
37943 }
37944 self->private_impl.f_seen_actl = true;
37945 } else if (self->private_impl.f_chunk_type == 1297238115) {
37946 if (self->private_impl.f_report_metadata_chrm) {
37947 if (self->private_impl.f_seen_chrm) {
37948 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
37949 goto exit;
37950 }
37951 if (a_src) {
37952 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37953 }
37954 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
37955 status = wuffs_png__decoder__decode_chrm(self, a_src);
37956 if (a_src) {
37957 iop_a_src = a_src->data.ptr + a_src->meta.ri;
37958 }
37959 if (status.repr) {
37960 goto suspend;
37961 }
37962 self->private_impl.f_seen_chrm = true;
37963 }
37964 } else if (self->private_impl.f_chunk_type == 1280598886) {
37965 if (self->private_impl.f_seen_fctl) {
37966 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
37967 goto exit;
37968 }
37969 if (a_src) {
37970 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37971 }
37972 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
37973 status = wuffs_png__decoder__decode_fctl(self, a_src);
37974 if (a_src) {
37975 iop_a_src = a_src->data.ptr + a_src->meta.ri;
37976 }
37977 if (status.repr) {
37978 goto suspend;
37979 }
37980 self->private_impl.f_seen_fctl = true;
37981 } else if (self->private_impl.f_chunk_type == 1095582055) {
37982 if (self->private_impl.f_report_metadata_gama) {
37983 if (self->private_impl.f_seen_gama) {
37984 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
37985 goto exit;
37986 }
37987 if (a_src) {
37988 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37989 }
37990 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
37991 status = wuffs_png__decoder__decode_gama(self, a_src);
37992 if (a_src) {
37993 iop_a_src = a_src->data.ptr + a_src->meta.ri;
37994 }
37995 if (status.repr) {
37996 goto suspend;
37997 }
37998 self->private_impl.f_seen_gama = true;
37999 }
38000 } else if (self->private_impl.f_chunk_type == 1346585449) {
38001 if (self->private_impl.f_report_metadata_iccp) {
38002 if (self->private_impl.f_seen_iccp) {
38003 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38004 goto exit;
38005 }
38006 if (a_src) {
38007 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
38008 }
38009 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
38010 status = wuffs_png__decoder__decode_iccp(self, a_src);
38011 if (a_src) {
38012 iop_a_src = a_src->data.ptr + a_src->meta.ri;
38013 }
38014 if (status.repr) {
38015 goto suspend;
38016 }
38017 self->private_impl.f_seen_iccp = true;
38018 }
38019 } else if (self->private_impl.f_chunk_type == 1111970419) {
38020 if (self->private_impl.f_report_metadata_srgb) {
38021 if (self->private_impl.f_seen_srgb) {
38022 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38023 goto exit;
38024 }
38025 if (a_src) {
38026 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
38027 }
38028 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
38029 status = wuffs_png__decoder__decode_srgb(self, a_src);
38030 if (a_src) {
38031 iop_a_src = a_src->data.ptr + a_src->meta.ri;
38032 }
38033 if (status.repr) {
38034 goto suspend;
38035 }
38036 self->private_impl.f_seen_srgb = true;
38037 }
Nigel Taoe360a532021-04-05 22:47:03 +100038038 } else if (self->private_impl.f_chunk_type == 1397641844) {
38039 if (self->private_impl.f_seen_trns || (self->private_impl.f_color_type > 3) || ((self->private_impl.f_color_type == 3) && ! self->private_impl.f_seen_plte)) {
38040 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38041 goto exit;
38042 }
38043 if (a_src) {
38044 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
38045 }
Nigel Taobf9dab32021-11-18 19:19:55 +110038046 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
Nigel Taoe360a532021-04-05 22:47:03 +100038047 status = wuffs_png__decoder__decode_trns(self, a_src);
38048 if (a_src) {
38049 iop_a_src = a_src->data.ptr + a_src->meta.ri;
38050 }
38051 if (status.repr) {
38052 goto suspend;
38053 }
38054 self->private_impl.f_seen_trns = true;
Nigel Taobf9dab32021-11-18 19:19:55 +110038055 } else if ((self->private_impl.f_chunk_type == 1951945833) || (self->private_impl.f_chunk_type == 1951942004) || (self->private_impl.f_chunk_type == 1951945850)) {
38056 if (self->private_impl.f_report_metadata_kvp) {
38057 self->private_impl.f_metadata_flavor = 4;
38058 self->private_impl.f_metadata_fourcc = 1263947851;
38059 self->private_impl.f_metadata_x = 0;
38060 self->private_impl.f_metadata_y = 0;
38061 self->private_impl.f_metadata_z = 0;
38062 }
38063 }
38064 if (self->private_impl.f_metadata_fourcc == 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100038065 self->private_data.s_decode_other_chunk[0].scratch = self->private_impl.f_chunk_length;
Nigel Taobf9dab32021-11-18 19:19:55 +110038066 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
Nigel Taoe360a532021-04-05 22:47:03 +100038067 if (self->private_data.s_decode_other_chunk[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
38068 self->private_data.s_decode_other_chunk[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
38069 iop_a_src = io2_a_src;
38070 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38071 goto suspend;
38072 }
38073 iop_a_src += self->private_data.s_decode_other_chunk[0].scratch;
38074 }
38075
38076 goto ok;
38077 ok:
38078 self->private_impl.p_decode_other_chunk[0] = 0;
38079 goto exit;
38080 }
38081
38082 goto suspend;
38083 suspend:
38084 self->private_impl.p_decode_other_chunk[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
38085
38086 goto exit;
38087 exit:
38088 if (a_src) {
38089 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
38090 }
38091
38092 return status;
38093}
38094
Nigel Taobf9dab32021-11-18 19:19:55 +110038095// -------- func png.decoder.decode_actl
38096
38097static wuffs_base__status
38098wuffs_png__decoder__decode_actl(
38099 wuffs_png__decoder* self,
38100 wuffs_base__io_buffer* a_src) {
38101 wuffs_base__status status = wuffs_base__make_status(NULL);
38102
38103 const uint8_t* iop_a_src = NULL;
38104 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38105 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38106 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38107 if (a_src) {
38108 io0_a_src = a_src->data.ptr;
38109 io1_a_src = io0_a_src + a_src->meta.ri;
38110 iop_a_src = io1_a_src;
38111 io2_a_src = io0_a_src + a_src->meta.wi;
38112 }
38113
38114 uint32_t coro_susp_point = self->private_impl.p_decode_actl[0];
38115 switch (coro_susp_point) {
38116 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
38117
38118 if (self->private_impl.f_chunk_length != 8) {
38119 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38120 goto exit;
38121 } else if (self->private_impl.f_interlace_pass > 0) {
38122 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
38123 goto exit;
38124 }
38125 self->private_impl.f_chunk_length = 0;
38126 {
38127 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
38128 uint32_t t_0;
38129 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38130 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
38131 iop_a_src += 4;
38132 } else {
38133 self->private_data.s_decode_actl[0].scratch = 0;
38134 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
38135 while (true) {
38136 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38137 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38138 goto suspend;
38139 }
38140 uint64_t* scratch = &self->private_data.s_decode_actl[0].scratch;
38141 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
38142 *scratch >>= 8;
38143 *scratch <<= 8;
38144 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
38145 if (num_bits_0 == 24) {
38146 t_0 = ((uint32_t)(*scratch >> 32));
38147 break;
38148 }
38149 num_bits_0 += 8;
38150 *scratch |= ((uint64_t)(num_bits_0));
38151 }
38152 }
38153 self->private_impl.f_num_animation_frames_value = t_0;
38154 }
38155 if (self->private_impl.f_num_animation_frames_value == 0) {
38156 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38157 goto exit;
38158 }
38159 {
38160 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
38161 uint32_t t_1;
38162 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38163 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
38164 iop_a_src += 4;
38165 } else {
38166 self->private_data.s_decode_actl[0].scratch = 0;
38167 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
38168 while (true) {
38169 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38170 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38171 goto suspend;
38172 }
38173 uint64_t* scratch = &self->private_data.s_decode_actl[0].scratch;
38174 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
38175 *scratch >>= 8;
38176 *scratch <<= 8;
38177 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
38178 if (num_bits_1 == 24) {
38179 t_1 = ((uint32_t)(*scratch >> 32));
38180 break;
38181 }
38182 num_bits_1 += 8;
38183 *scratch |= ((uint64_t)(num_bits_1));
38184 }
38185 }
38186 self->private_impl.f_num_animation_loops_value = t_1;
38187 }
38188
38189 goto ok;
38190 ok:
38191 self->private_impl.p_decode_actl[0] = 0;
38192 goto exit;
38193 }
38194
38195 goto suspend;
38196 suspend:
38197 self->private_impl.p_decode_actl[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
38198
38199 goto exit;
38200 exit:
38201 if (a_src) {
38202 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
38203 }
38204
38205 return status;
38206}
38207
38208// -------- func png.decoder.decode_chrm
38209
38210static wuffs_base__status
38211wuffs_png__decoder__decode_chrm(
38212 wuffs_png__decoder* self,
38213 wuffs_base__io_buffer* a_src) {
38214 wuffs_base__status status = wuffs_base__make_status(NULL);
38215
38216 uint64_t v_u = 0;
38217
38218 const uint8_t* iop_a_src = NULL;
38219 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38220 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38221 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38222 if (a_src) {
38223 io0_a_src = a_src->data.ptr;
38224 io1_a_src = io0_a_src + a_src->meta.ri;
38225 iop_a_src = io1_a_src;
38226 io2_a_src = io0_a_src + a_src->meta.wi;
38227 }
38228
38229 uint32_t coro_susp_point = self->private_impl.p_decode_chrm[0];
38230 switch (coro_susp_point) {
38231 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
38232
38233 if (self->private_impl.f_chunk_length != 32) {
38234 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38235 goto exit;
38236 }
38237 self->private_impl.f_chunk_length = 0;
38238 self->private_impl.f_metadata_flavor = 5;
38239 self->private_impl.f_metadata_fourcc = 1128813133;
38240 self->private_impl.f_metadata_x = 0;
38241 self->private_impl.f_metadata_y = 0;
38242 self->private_impl.f_metadata_z = 0;
38243 {
38244 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
38245 uint64_t t_0;
38246 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38247 t_0 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38248 iop_a_src += 4;
38249 } else {
38250 self->private_data.s_decode_chrm[0].scratch = 0;
38251 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
38252 while (true) {
38253 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38254 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38255 goto suspend;
38256 }
38257 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
38258 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
38259 *scratch >>= 8;
38260 *scratch <<= 8;
38261 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
38262 if (num_bits_0 == 24) {
38263 t_0 = ((uint64_t)(*scratch >> 32));
38264 break;
38265 }
38266 num_bits_0 += 8;
38267 *scratch |= ((uint64_t)(num_bits_0));
38268 }
38269 }
38270 v_u = t_0;
38271 }
38272 self->private_impl.f_metadata_x |= ((16777215 & v_u) << 0);
38273 {
38274 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
38275 uint64_t t_1;
38276 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38277 t_1 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38278 iop_a_src += 4;
38279 } else {
38280 self->private_data.s_decode_chrm[0].scratch = 0;
38281 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
38282 while (true) {
38283 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38284 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38285 goto suspend;
38286 }
38287 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
38288 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
38289 *scratch >>= 8;
38290 *scratch <<= 8;
38291 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
38292 if (num_bits_1 == 24) {
38293 t_1 = ((uint64_t)(*scratch >> 32));
38294 break;
38295 }
38296 num_bits_1 += 8;
38297 *scratch |= ((uint64_t)(num_bits_1));
38298 }
38299 }
38300 v_u = t_1;
38301 }
38302 self->private_impl.f_metadata_x |= ((16777215 & v_u) << 24);
38303 {
38304 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
38305 uint64_t t_2;
38306 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38307 t_2 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38308 iop_a_src += 4;
38309 } else {
38310 self->private_data.s_decode_chrm[0].scratch = 0;
38311 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
38312 while (true) {
38313 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38314 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38315 goto suspend;
38316 }
38317 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
38318 uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFF));
38319 *scratch >>= 8;
38320 *scratch <<= 8;
38321 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2);
38322 if (num_bits_2 == 24) {
38323 t_2 = ((uint64_t)(*scratch >> 32));
38324 break;
38325 }
38326 num_bits_2 += 8;
38327 *scratch |= ((uint64_t)(num_bits_2));
38328 }
38329 }
38330 v_u = t_2;
38331 }
38332 self->private_impl.f_metadata_x |= ((uint64_t)((16777215 & v_u) << 48));
38333 self->private_impl.f_metadata_y |= ((16777215 & v_u) >> 16);
38334 {
38335 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
38336 uint64_t t_3;
38337 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38338 t_3 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38339 iop_a_src += 4;
38340 } else {
38341 self->private_data.s_decode_chrm[0].scratch = 0;
38342 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
38343 while (true) {
38344 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38345 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38346 goto suspend;
38347 }
38348 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
38349 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
38350 *scratch >>= 8;
38351 *scratch <<= 8;
38352 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
38353 if (num_bits_3 == 24) {
38354 t_3 = ((uint64_t)(*scratch >> 32));
38355 break;
38356 }
38357 num_bits_3 += 8;
38358 *scratch |= ((uint64_t)(num_bits_3));
38359 }
38360 }
38361 v_u = t_3;
38362 }
38363 self->private_impl.f_metadata_y |= ((16777215 & v_u) << 8);
38364 {
38365 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
38366 uint64_t t_4;
38367 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38368 t_4 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38369 iop_a_src += 4;
38370 } else {
38371 self->private_data.s_decode_chrm[0].scratch = 0;
38372 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
38373 while (true) {
38374 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38375 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38376 goto suspend;
38377 }
38378 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
38379 uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFF));
38380 *scratch >>= 8;
38381 *scratch <<= 8;
38382 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4);
38383 if (num_bits_4 == 24) {
38384 t_4 = ((uint64_t)(*scratch >> 32));
38385 break;
38386 }
38387 num_bits_4 += 8;
38388 *scratch |= ((uint64_t)(num_bits_4));
38389 }
38390 }
38391 v_u = t_4;
38392 }
38393 self->private_impl.f_metadata_y |= ((16777215 & v_u) << 32);
38394 {
38395 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
38396 uint64_t t_5;
38397 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38398 t_5 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38399 iop_a_src += 4;
38400 } else {
38401 self->private_data.s_decode_chrm[0].scratch = 0;
38402 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
38403 while (true) {
38404 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38405 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38406 goto suspend;
38407 }
38408 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
38409 uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFF));
38410 *scratch >>= 8;
38411 *scratch <<= 8;
38412 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5);
38413 if (num_bits_5 == 24) {
38414 t_5 = ((uint64_t)(*scratch >> 32));
38415 break;
38416 }
38417 num_bits_5 += 8;
38418 *scratch |= ((uint64_t)(num_bits_5));
38419 }
38420 }
38421 v_u = t_5;
38422 }
38423 self->private_impl.f_metadata_y |= ((uint64_t)((16777215 & v_u) << 56));
38424 self->private_impl.f_metadata_z |= ((16777215 & v_u) >> 8);
38425 {
38426 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
38427 uint64_t t_6;
38428 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38429 t_6 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38430 iop_a_src += 4;
38431 } else {
38432 self->private_data.s_decode_chrm[0].scratch = 0;
38433 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
38434 while (true) {
38435 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38436 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38437 goto suspend;
38438 }
38439 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
38440 uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFF));
38441 *scratch >>= 8;
38442 *scratch <<= 8;
38443 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6);
38444 if (num_bits_6 == 24) {
38445 t_6 = ((uint64_t)(*scratch >> 32));
38446 break;
38447 }
38448 num_bits_6 += 8;
38449 *scratch |= ((uint64_t)(num_bits_6));
38450 }
38451 }
38452 v_u = t_6;
38453 }
38454 self->private_impl.f_metadata_z |= ((16777215 & v_u) << 16);
38455 {
38456 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
38457 uint64_t t_7;
38458 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38459 t_7 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38460 iop_a_src += 4;
38461 } else {
38462 self->private_data.s_decode_chrm[0].scratch = 0;
38463 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
38464 while (true) {
38465 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38466 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38467 goto suspend;
38468 }
38469 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
38470 uint32_t num_bits_7 = ((uint32_t)(*scratch & 0xFF));
38471 *scratch >>= 8;
38472 *scratch <<= 8;
38473 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_7);
38474 if (num_bits_7 == 24) {
38475 t_7 = ((uint64_t)(*scratch >> 32));
38476 break;
38477 }
38478 num_bits_7 += 8;
38479 *scratch |= ((uint64_t)(num_bits_7));
38480 }
38481 }
38482 v_u = t_7;
38483 }
38484 self->private_impl.f_metadata_z |= ((16777215 & v_u) << 40);
38485
38486 goto ok;
38487 ok:
38488 self->private_impl.p_decode_chrm[0] = 0;
38489 goto exit;
38490 }
38491
38492 goto suspend;
38493 suspend:
38494 self->private_impl.p_decode_chrm[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
38495
38496 goto exit;
38497 exit:
38498 if (a_src) {
38499 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
38500 }
38501
38502 return status;
38503}
38504
38505// -------- func png.decoder.decode_fctl
38506
38507static wuffs_base__status
38508wuffs_png__decoder__decode_fctl(
38509 wuffs_png__decoder* self,
38510 wuffs_base__io_buffer* a_src) {
38511 wuffs_base__status status = wuffs_base__make_status(NULL);
38512
38513 uint32_t v_x0 = 0;
38514 uint32_t v_y0 = 0;
38515 uint32_t v_x1 = 0;
38516 uint32_t v_y1 = 0;
38517
38518 const uint8_t* iop_a_src = NULL;
38519 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38520 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38521 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38522 if (a_src) {
38523 io0_a_src = a_src->data.ptr;
38524 io1_a_src = io0_a_src + a_src->meta.ri;
38525 iop_a_src = io1_a_src;
38526 io2_a_src = io0_a_src + a_src->meta.wi;
38527 }
38528
38529 uint32_t coro_susp_point = self->private_impl.p_decode_fctl[0];
38530 if (coro_susp_point) {
38531 v_x0 = self->private_data.s_decode_fctl[0].v_x0;
38532 v_x1 = self->private_data.s_decode_fctl[0].v_x1;
38533 v_y1 = self->private_data.s_decode_fctl[0].v_y1;
38534 }
38535 switch (coro_susp_point) {
38536 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
38537
38538 if (self->private_impl.f_chunk_length != 26) {
38539 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38540 goto exit;
38541 }
38542 self->private_impl.f_chunk_length = 0;
38543 {
38544 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
38545 uint32_t t_0;
38546 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38547 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
38548 iop_a_src += 4;
38549 } else {
38550 self->private_data.s_decode_fctl[0].scratch = 0;
38551 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
38552 while (true) {
38553 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38554 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38555 goto suspend;
38556 }
38557 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
38558 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
38559 *scratch >>= 8;
38560 *scratch <<= 8;
38561 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
38562 if (num_bits_0 == 24) {
38563 t_0 = ((uint32_t)(*scratch >> 32));
38564 break;
38565 }
38566 num_bits_0 += 8;
38567 *scratch |= ((uint64_t)(num_bits_0));
38568 }
38569 }
38570 v_x0 = t_0;
38571 }
38572 if (v_x0 != self->private_impl.f_next_animation_seq_num) {
38573 status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number);
38574 goto exit;
38575 } else if (self->private_impl.f_next_animation_seq_num >= 4294967295) {
38576 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
38577 goto exit;
38578 }
38579 self->private_impl.f_next_animation_seq_num += 1;
38580 {
38581 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
38582 uint32_t t_1;
38583 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38584 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
38585 iop_a_src += 4;
38586 } else {
38587 self->private_data.s_decode_fctl[0].scratch = 0;
38588 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
38589 while (true) {
38590 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38591 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38592 goto suspend;
38593 }
38594 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
38595 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
38596 *scratch >>= 8;
38597 *scratch <<= 8;
38598 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
38599 if (num_bits_1 == 24) {
38600 t_1 = ((uint32_t)(*scratch >> 32));
38601 break;
38602 }
38603 num_bits_1 += 8;
38604 *scratch |= ((uint64_t)(num_bits_1));
38605 }
38606 }
38607 v_x1 = t_1;
38608 }
38609 {
38610 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
38611 uint32_t t_2;
38612 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38613 t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
38614 iop_a_src += 4;
38615 } else {
38616 self->private_data.s_decode_fctl[0].scratch = 0;
38617 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
38618 while (true) {
38619 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38620 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38621 goto suspend;
38622 }
38623 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
38624 uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFF));
38625 *scratch >>= 8;
38626 *scratch <<= 8;
38627 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2);
38628 if (num_bits_2 == 24) {
38629 t_2 = ((uint32_t)(*scratch >> 32));
38630 break;
38631 }
38632 num_bits_2 += 8;
38633 *scratch |= ((uint64_t)(num_bits_2));
38634 }
38635 }
38636 v_y1 = t_2;
38637 }
38638 {
38639 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
38640 uint32_t t_3;
38641 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38642 t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
38643 iop_a_src += 4;
38644 } else {
38645 self->private_data.s_decode_fctl[0].scratch = 0;
38646 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
38647 while (true) {
38648 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38649 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38650 goto suspend;
38651 }
38652 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
38653 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
38654 *scratch >>= 8;
38655 *scratch <<= 8;
38656 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
38657 if (num_bits_3 == 24) {
38658 t_3 = ((uint32_t)(*scratch >> 32));
38659 break;
38660 }
38661 num_bits_3 += 8;
38662 *scratch |= ((uint64_t)(num_bits_3));
38663 }
38664 }
38665 v_x0 = t_3;
38666 }
38667 {
38668 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
38669 uint32_t t_4;
38670 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38671 t_4 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
38672 iop_a_src += 4;
38673 } else {
38674 self->private_data.s_decode_fctl[0].scratch = 0;
38675 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
38676 while (true) {
38677 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38678 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38679 goto suspend;
38680 }
38681 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
38682 uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFF));
38683 *scratch >>= 8;
38684 *scratch <<= 8;
38685 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4);
38686 if (num_bits_4 == 24) {
38687 t_4 = ((uint32_t)(*scratch >> 32));
38688 break;
38689 }
38690 num_bits_4 += 8;
38691 *scratch |= ((uint64_t)(num_bits_4));
38692 }
38693 }
38694 v_y0 = t_4;
38695 }
38696 v_x1 += v_x0;
38697 v_y1 += v_y0;
38698 if ((v_x0 >= v_x1) ||
38699 (v_x0 > self->private_impl.f_width) ||
38700 (v_x1 > self->private_impl.f_width) ||
38701 (v_y0 >= v_y1) ||
38702 (v_y0 > self->private_impl.f_height) ||
38703 (v_y1 > self->private_impl.f_height)) {
38704 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38705 goto exit;
38706 }
38707 self->private_impl.f_frame_rect_x0 = v_x0;
38708 self->private_impl.f_frame_rect_y0 = v_y0;
38709 self->private_impl.f_frame_rect_x1 = v_x1;
38710 self->private_impl.f_frame_rect_y1 = v_y1;
38711 {
38712 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
38713 uint32_t t_5;
38714 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
38715 t_5 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
38716 iop_a_src += 2;
38717 } else {
38718 self->private_data.s_decode_fctl[0].scratch = 0;
38719 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
38720 while (true) {
38721 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38722 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38723 goto suspend;
38724 }
38725 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
38726 uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFF));
38727 *scratch >>= 8;
38728 *scratch <<= 8;
38729 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5);
38730 if (num_bits_5 == 8) {
38731 t_5 = ((uint32_t)(*scratch >> 48));
38732 break;
38733 }
38734 num_bits_5 += 8;
38735 *scratch |= ((uint64_t)(num_bits_5));
38736 }
38737 }
38738 v_x0 = t_5;
38739 }
38740 {
38741 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
38742 uint32_t t_6;
38743 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
38744 t_6 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
38745 iop_a_src += 2;
38746 } else {
38747 self->private_data.s_decode_fctl[0].scratch = 0;
38748 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
38749 while (true) {
38750 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38751 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38752 goto suspend;
38753 }
38754 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
38755 uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFF));
38756 *scratch >>= 8;
38757 *scratch <<= 8;
38758 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6);
38759 if (num_bits_6 == 8) {
38760 t_6 = ((uint32_t)(*scratch >> 48));
38761 break;
38762 }
38763 num_bits_6 += 8;
38764 *scratch |= ((uint64_t)(num_bits_6));
38765 }
38766 }
38767 v_x1 = t_6;
38768 }
38769 if (v_x1 <= 0) {
38770 self->private_impl.f_frame_duration = (((uint64_t)(v_x0)) * 7056000);
38771 } else {
38772 self->private_impl.f_frame_duration = ((((uint64_t)(v_x0)) * 705600000) / ((uint64_t)(v_x1)));
38773 }
38774 {
38775 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
38776 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38777 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38778 goto suspend;
38779 }
38780 uint32_t t_7 = *iop_a_src++;
38781 v_x0 = t_7;
38782 }
38783 if (v_x0 == 0) {
38784 self->private_impl.f_frame_disposal = 0;
38785 } else if (v_x0 == 1) {
38786 self->private_impl.f_frame_disposal = 1;
38787 } else if (v_x0 == 2) {
38788 self->private_impl.f_frame_disposal = 2;
38789 } else {
38790 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38791 goto exit;
38792 }
38793 {
38794 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
38795 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38796 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38797 goto suspend;
38798 }
38799 uint32_t t_8 = *iop_a_src++;
38800 v_x0 = t_8;
38801 }
38802 if (v_x0 == 0) {
38803 self->private_impl.f_frame_overwrite_instead_of_blend = true;
38804 } else if (v_x0 == 1) {
38805 self->private_impl.f_frame_overwrite_instead_of_blend = false;
38806 } else {
38807 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38808 goto exit;
38809 }
38810 if (self->private_impl.f_num_decoded_frame_configs_value == 0) {
38811 self->private_impl.f_first_rect_x0 = self->private_impl.f_frame_rect_x0;
38812 self->private_impl.f_first_rect_y0 = self->private_impl.f_frame_rect_y0;
38813 self->private_impl.f_first_rect_x1 = self->private_impl.f_frame_rect_x1;
38814 self->private_impl.f_first_rect_y1 = self->private_impl.f_frame_rect_y1;
38815 self->private_impl.f_first_duration = self->private_impl.f_frame_duration;
38816 self->private_impl.f_first_disposal = self->private_impl.f_frame_disposal;
38817 self->private_impl.f_first_overwrite_instead_of_blend = self->private_impl.f_frame_overwrite_instead_of_blend;
38818 }
38819
38820 goto ok;
38821 ok:
38822 self->private_impl.p_decode_fctl[0] = 0;
38823 goto exit;
38824 }
38825
38826 goto suspend;
38827 suspend:
38828 self->private_impl.p_decode_fctl[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
38829 self->private_data.s_decode_fctl[0].v_x0 = v_x0;
38830 self->private_data.s_decode_fctl[0].v_x1 = v_x1;
38831 self->private_data.s_decode_fctl[0].v_y1 = v_y1;
38832
38833 goto exit;
38834 exit:
38835 if (a_src) {
38836 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
38837 }
38838
38839 return status;
38840}
38841
38842// -------- func png.decoder.decode_gama
38843
38844static wuffs_base__status
38845wuffs_png__decoder__decode_gama(
38846 wuffs_png__decoder* self,
38847 wuffs_base__io_buffer* a_src) {
38848 wuffs_base__status status = wuffs_base__make_status(NULL);
38849
38850 const uint8_t* iop_a_src = NULL;
38851 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38852 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38853 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38854 if (a_src) {
38855 io0_a_src = a_src->data.ptr;
38856 io1_a_src = io0_a_src + a_src->meta.ri;
38857 iop_a_src = io1_a_src;
38858 io2_a_src = io0_a_src + a_src->meta.wi;
38859 }
38860
38861 uint32_t coro_susp_point = self->private_impl.p_decode_gama[0];
38862 switch (coro_susp_point) {
38863 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
38864
38865 if (self->private_impl.f_chunk_length != 4) {
38866 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38867 goto exit;
38868 }
38869 self->private_impl.f_chunk_length = 0;
38870 self->private_impl.f_metadata_flavor = 5;
38871 self->private_impl.f_metadata_fourcc = 1195461953;
38872 {
38873 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
38874 uint64_t t_0;
38875 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
38876 t_0 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
38877 iop_a_src += 4;
38878 } else {
38879 self->private_data.s_decode_gama[0].scratch = 0;
38880 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
38881 while (true) {
38882 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38883 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38884 goto suspend;
38885 }
38886 uint64_t* scratch = &self->private_data.s_decode_gama[0].scratch;
38887 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
38888 *scratch >>= 8;
38889 *scratch <<= 8;
38890 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
38891 if (num_bits_0 == 24) {
38892 t_0 = ((uint64_t)(*scratch >> 32));
38893 break;
38894 }
38895 num_bits_0 += 8;
38896 *scratch |= ((uint64_t)(num_bits_0));
38897 }
38898 }
38899 self->private_impl.f_metadata_x = t_0;
38900 }
38901 self->private_impl.f_metadata_y = 0;
38902 self->private_impl.f_metadata_z = 0;
38903
38904 goto ok;
38905 ok:
38906 self->private_impl.p_decode_gama[0] = 0;
38907 goto exit;
38908 }
38909
38910 goto suspend;
38911 suspend:
38912 self->private_impl.p_decode_gama[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
38913
38914 goto exit;
38915 exit:
38916 if (a_src) {
38917 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
38918 }
38919
38920 return status;
38921}
38922
38923// -------- func png.decoder.decode_iccp
38924
38925static wuffs_base__status
38926wuffs_png__decoder__decode_iccp(
38927 wuffs_png__decoder* self,
38928 wuffs_base__io_buffer* a_src) {
38929 wuffs_base__status status = wuffs_base__make_status(NULL);
38930
38931 uint8_t v_c = 0;
38932
38933 const uint8_t* iop_a_src = NULL;
38934 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38935 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38936 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
38937 if (a_src) {
38938 io0_a_src = a_src->data.ptr;
38939 io1_a_src = io0_a_src + a_src->meta.ri;
38940 iop_a_src = io1_a_src;
38941 io2_a_src = io0_a_src + a_src->meta.wi;
38942 }
38943
38944 uint32_t coro_susp_point = self->private_impl.p_decode_iccp[0];
38945 switch (coro_susp_point) {
38946 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
38947
38948 while (true) {
38949 if (self->private_impl.f_chunk_length <= 0) {
38950 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38951 goto exit;
38952 }
38953 self->private_impl.f_chunk_length -= 1;
38954 {
38955 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
38956 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38957 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38958 goto suspend;
38959 }
38960 uint8_t t_0 = *iop_a_src++;
38961 v_c = t_0;
38962 }
38963 if (v_c == 0) {
38964 goto label__0__break;
38965 }
38966 }
38967 label__0__break:;
38968 if (self->private_impl.f_chunk_length <= 0) {
38969 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
38970 goto exit;
38971 }
38972 self->private_impl.f_chunk_length -= 1;
38973 {
38974 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
38975 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
38976 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
38977 goto suspend;
38978 }
38979 uint8_t t_1 = *iop_a_src++;
38980 v_c = t_1;
38981 }
38982 if (v_c != 0) {
38983 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method);
38984 goto exit;
38985 }
38986 self->private_impl.f_metadata_is_zlib_compressed = true;
38987 self->private_impl.f_metadata_flavor = 4;
38988 self->private_impl.f_metadata_fourcc = 1229144912;
38989 self->private_impl.f_metadata_x = 0;
38990 self->private_impl.f_metadata_y = 0;
38991 self->private_impl.f_metadata_z = 0;
38992
38993 goto ok;
38994 ok:
38995 self->private_impl.p_decode_iccp[0] = 0;
38996 goto exit;
38997 }
38998
38999 goto suspend;
39000 suspend:
39001 self->private_impl.p_decode_iccp[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
39002
39003 goto exit;
39004 exit:
39005 if (a_src) {
39006 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39007 }
39008
39009 return status;
39010}
39011
Nigel Taoe360a532021-04-05 22:47:03 +100039012// -------- func png.decoder.decode_plte
39013
39014static wuffs_base__status
39015wuffs_png__decoder__decode_plte(
39016 wuffs_png__decoder* self,
39017 wuffs_base__io_buffer* a_src) {
39018 wuffs_base__status status = wuffs_base__make_status(NULL);
39019
39020 uint32_t v_num_entries = 0;
39021 uint32_t v_i = 0;
39022 uint32_t v_argb = 0;
39023
39024 const uint8_t* iop_a_src = NULL;
39025 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39026 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39027 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39028 if (a_src) {
39029 io0_a_src = a_src->data.ptr;
39030 io1_a_src = io0_a_src + a_src->meta.ri;
39031 iop_a_src = io1_a_src;
39032 io2_a_src = io0_a_src + a_src->meta.wi;
39033 }
39034
39035 uint32_t coro_susp_point = self->private_impl.p_decode_plte[0];
39036 if (coro_susp_point) {
39037 v_num_entries = self->private_data.s_decode_plte[0].v_num_entries;
39038 v_i = self->private_data.s_decode_plte[0].v_i;
39039 }
39040 switch (coro_susp_point) {
39041 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
39042
39043 if ((self->private_impl.f_chunk_length > 768) || ((self->private_impl.f_chunk_length % 3) != 0)) {
39044 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39045 goto exit;
39046 }
39047 v_num_entries = (((uint32_t)(self->private_impl.f_chunk_length)) / 3);
Nigel Taobf9dab32021-11-18 19:19:55 +110039048 self->private_impl.f_chunk_length = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100039049 while (v_i < v_num_entries) {
39050 {
39051 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
39052 uint32_t t_0;
39053 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
39054 t_0 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src)));
39055 iop_a_src += 3;
39056 } else {
39057 self->private_data.s_decode_plte[0].scratch = 0;
39058 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
39059 while (true) {
39060 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39061 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39062 goto suspend;
39063 }
39064 uint64_t* scratch = &self->private_data.s_decode_plte[0].scratch;
39065 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
39066 *scratch >>= 8;
39067 *scratch <<= 8;
39068 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
39069 if (num_bits_0 == 16) {
39070 t_0 = ((uint32_t)(*scratch >> 40));
39071 break;
39072 }
39073 num_bits_0 += 8;
39074 *scratch |= ((uint64_t)(num_bits_0));
39075 }
39076 }
39077 v_argb = t_0;
39078 }
39079 v_argb |= 4278190080;
39080 self->private_data.f_src_palette[((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
39081 self->private_data.f_src_palette[((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
39082 self->private_data.f_src_palette[((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
39083 self->private_data.f_src_palette[((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
39084 v_i += 1;
39085 }
39086 while (v_i < 256) {
39087 self->private_data.f_src_palette[((4 * v_i) + 0)] = 0;
39088 self->private_data.f_src_palette[((4 * v_i) + 1)] = 0;
39089 self->private_data.f_src_palette[((4 * v_i) + 2)] = 0;
39090 self->private_data.f_src_palette[((4 * v_i) + 3)] = 255;
39091 v_i += 1;
39092 }
39093
39094 goto ok;
39095 ok:
39096 self->private_impl.p_decode_plte[0] = 0;
39097 goto exit;
39098 }
39099
39100 goto suspend;
39101 suspend:
39102 self->private_impl.p_decode_plte[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
39103 self->private_data.s_decode_plte[0].v_num_entries = v_num_entries;
39104 self->private_data.s_decode_plte[0].v_i = v_i;
39105
39106 goto exit;
39107 exit:
39108 if (a_src) {
39109 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39110 }
39111
39112 return status;
39113}
39114
Nigel Taobf9dab32021-11-18 19:19:55 +110039115// -------- func png.decoder.decode_srgb
39116
39117static wuffs_base__status
39118wuffs_png__decoder__decode_srgb(
39119 wuffs_png__decoder* self,
39120 wuffs_base__io_buffer* a_src) {
39121 wuffs_base__status status = wuffs_base__make_status(NULL);
39122
39123 const uint8_t* iop_a_src = NULL;
39124 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39125 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39126 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39127 if (a_src) {
39128 io0_a_src = a_src->data.ptr;
39129 io1_a_src = io0_a_src + a_src->meta.ri;
39130 iop_a_src = io1_a_src;
39131 io2_a_src = io0_a_src + a_src->meta.wi;
39132 }
39133
39134 uint32_t coro_susp_point = self->private_impl.p_decode_srgb[0];
39135 switch (coro_susp_point) {
39136 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
39137
39138 if (self->private_impl.f_chunk_length != 1) {
39139 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39140 goto exit;
39141 }
39142 self->private_impl.f_chunk_length = 0;
39143 self->private_impl.f_metadata_flavor = 5;
39144 self->private_impl.f_metadata_fourcc = 1397901122;
39145 {
39146 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
39147 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39148 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39149 goto suspend;
39150 }
39151 uint64_t t_0 = *iop_a_src++;
39152 self->private_impl.f_metadata_x = t_0;
39153 }
39154 self->private_impl.f_metadata_y = 0;
39155 self->private_impl.f_metadata_z = 0;
39156
39157 goto ok;
39158 ok:
39159 self->private_impl.p_decode_srgb[0] = 0;
39160 goto exit;
39161 }
39162
39163 goto suspend;
39164 suspend:
39165 self->private_impl.p_decode_srgb[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
39166
39167 goto exit;
39168 exit:
39169 if (a_src) {
39170 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39171 }
39172
39173 return status;
39174}
39175
Nigel Taoe360a532021-04-05 22:47:03 +100039176// -------- func png.decoder.decode_trns
39177
39178static wuffs_base__status
39179wuffs_png__decoder__decode_trns(
39180 wuffs_png__decoder* self,
39181 wuffs_base__io_buffer* a_src) {
39182 wuffs_base__status status = wuffs_base__make_status(NULL);
39183
Nigel Taoe360a532021-04-05 22:47:03 +100039184 uint32_t v_i = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110039185 uint32_t v_n = 0;
39186 uint64_t v_u = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100039187
39188 const uint8_t* iop_a_src = NULL;
39189 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39190 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39191 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39192 if (a_src) {
39193 io0_a_src = a_src->data.ptr;
39194 io1_a_src = io0_a_src + a_src->meta.ri;
39195 iop_a_src = io1_a_src;
39196 io2_a_src = io0_a_src + a_src->meta.wi;
39197 }
39198
39199 uint32_t coro_susp_point = self->private_impl.p_decode_trns[0];
39200 if (coro_susp_point) {
Nigel Taoe360a532021-04-05 22:47:03 +100039201 v_i = self->private_data.s_decode_trns[0].v_i;
Nigel Taobf9dab32021-11-18 19:19:55 +110039202 v_n = self->private_data.s_decode_trns[0].v_n;
Nigel Taoe360a532021-04-05 22:47:03 +100039203 }
39204 switch (coro_susp_point) {
39205 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
39206
Nigel Taobf9dab32021-11-18 19:19:55 +110039207 if (self->private_impl.f_color_type == 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100039208 self->private_impl.choosy_filter_and_swizzle = (
39209 &wuffs_png__decoder__filter_and_swizzle_tricky);
Nigel Taobf9dab32021-11-18 19:19:55 +110039210 if (self->private_impl.f_depth <= 8) {
Nigel Taoe360a532021-04-05 22:47:03 +100039211 self->private_impl.f_dst_pixfmt = 2164295816;
Nigel Taobf9dab32021-11-18 19:19:55 +110039212 self->private_impl.f_src_pixfmt = 2164295816;
39213 } else {
39214 self->private_impl.f_dst_pixfmt = 2164308923;
Nigel Taoe360a532021-04-05 22:47:03 +100039215 self->private_impl.f_src_pixfmt = 2164308923;
39216 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039217 if (self->private_impl.f_chunk_length != 2) {
39218 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39219 goto exit;
39220 }
39221 self->private_impl.f_chunk_length = 0;
39222 {
39223 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
39224 uint64_t t_0;
39225 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
39226 t_0 = ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
39227 iop_a_src += 2;
39228 } else {
39229 self->private_data.s_decode_trns[0].scratch = 0;
39230 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
39231 while (true) {
39232 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39233 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39234 goto suspend;
39235 }
39236 uint64_t* scratch = &self->private_data.s_decode_trns[0].scratch;
39237 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
39238 *scratch >>= 8;
39239 *scratch <<= 8;
39240 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
39241 if (num_bits_0 == 8) {
39242 t_0 = ((uint64_t)(*scratch >> 48));
39243 break;
39244 }
39245 num_bits_0 += 8;
39246 *scratch |= ((uint64_t)(num_bits_0));
39247 }
39248 }
39249 v_u = t_0;
39250 }
39251 if (self->private_impl.f_depth <= 1) {
39252 self->private_impl.f_remap_transparency = (((v_u & 1) * 16777215) | 4278190080);
39253 } else if (self->private_impl.f_depth <= 2) {
39254 self->private_impl.f_remap_transparency = (((v_u & 3) * 5592405) | 4278190080);
39255 } else if (self->private_impl.f_depth <= 4) {
39256 self->private_impl.f_remap_transparency = (((v_u & 15) * 1118481) | 4278190080);
39257 } else if (self->private_impl.f_depth <= 8) {
39258 self->private_impl.f_remap_transparency = (((v_u & 255) * 65793) | 4278190080);
39259 } else {
39260 self->private_impl.f_remap_transparency = ((v_u * 4295032833) | 18446462598732840960u);
39261 }
39262 } else if (self->private_impl.f_color_type == 2) {
39263 self->private_impl.choosy_filter_and_swizzle = (
39264 &wuffs_png__decoder__filter_and_swizzle_tricky);
39265 if (self->private_impl.f_depth <= 8) {
39266 self->private_impl.f_dst_pixfmt = 2164295816;
39267 self->private_impl.f_src_pixfmt = 2164295816;
39268 } else {
39269 self->private_impl.f_dst_pixfmt = 2164308923;
39270 self->private_impl.f_src_pixfmt = 2164308923;
39271 }
39272 if (self->private_impl.f_chunk_length != 6) {
39273 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39274 goto exit;
39275 }
39276 self->private_impl.f_chunk_length = 0;
39277 {
39278 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
39279 uint64_t t_1;
39280 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 6)) {
39281 t_1 = ((uint64_t)(wuffs_base__peek_u48be__no_bounds_check(iop_a_src)));
39282 iop_a_src += 6;
39283 } else {
39284 self->private_data.s_decode_trns[0].scratch = 0;
39285 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
39286 while (true) {
39287 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39288 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39289 goto suspend;
39290 }
39291 uint64_t* scratch = &self->private_data.s_decode_trns[0].scratch;
39292 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
39293 *scratch >>= 8;
39294 *scratch <<= 8;
39295 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
39296 if (num_bits_1 == 40) {
39297 t_1 = ((uint64_t)(*scratch >> 16));
39298 break;
39299 }
39300 num_bits_1 += 8;
39301 *scratch |= ((uint64_t)(num_bits_1));
39302 }
39303 }
39304 v_u = t_1;
39305 }
39306 if (self->private_impl.f_depth <= 8) {
39307 self->private_impl.f_remap_transparency = ((255 & (v_u >> 0)) |
39308 (65280 & (v_u >> 8)) |
39309 (16711680 & (v_u >> 16)) |
39310 4278190080);
39311 } else {
39312 self->private_impl.f_remap_transparency = (v_u | 18446462598732840960u);
39313 }
39314 } else if (self->private_impl.f_color_type == 3) {
39315 self->private_impl.f_dst_pixfmt = 2164523016;
39316 self->private_impl.f_src_pixfmt = 2164523016;
39317 if (self->private_impl.f_chunk_length > 256) {
39318 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39319 goto exit;
39320 }
39321 v_n = ((uint32_t)(self->private_impl.f_chunk_length));
39322 self->private_impl.f_chunk_length = 0;
39323 while (v_i < v_n) {
39324 {
39325 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
39326 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39327 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39328 goto suspend;
39329 }
39330 uint8_t t_2 = *iop_a_src++;
39331 self->private_data.f_src_palette[((4 * v_i) + 3)] = t_2;
39332 }
39333 v_i += 1;
39334 }
39335 } else {
39336 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39337 goto exit;
Nigel Taoe360a532021-04-05 22:47:03 +100039338 }
39339
39340 goto ok;
39341 ok:
39342 self->private_impl.p_decode_trns[0] = 0;
39343 goto exit;
39344 }
39345
39346 goto suspend;
39347 suspend:
39348 self->private_impl.p_decode_trns[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
Nigel Taoe360a532021-04-05 22:47:03 +100039349 self->private_data.s_decode_trns[0].v_i = v_i;
Nigel Taobf9dab32021-11-18 19:19:55 +110039350 self->private_data.s_decode_trns[0].v_n = v_n;
Nigel Taoe360a532021-04-05 22:47:03 +100039351
39352 goto exit;
39353 exit:
39354 if (a_src) {
39355 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39356 }
39357
39358 return status;
39359}
39360
39361// -------- func png.decoder.decode_frame_config
39362
39363WUFFS_BASE__MAYBE_STATIC wuffs_base__status
39364wuffs_png__decoder__decode_frame_config(
39365 wuffs_png__decoder* self,
39366 wuffs_base__frame_config* a_dst,
39367 wuffs_base__io_buffer* a_src) {
39368 if (!self) {
39369 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
39370 }
39371 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
39372 return wuffs_base__make_status(
39373 (self->private_impl.magic == WUFFS_BASE__DISABLED)
39374 ? wuffs_base__error__disabled_by_previous_error
39375 : wuffs_base__error__initialize_not_called);
39376 }
39377 if (!a_src) {
39378 self->private_impl.magic = WUFFS_BASE__DISABLED;
39379 return wuffs_base__make_status(wuffs_base__error__bad_argument);
39380 }
39381 if ((self->private_impl.active_coroutine != 0) &&
39382 (self->private_impl.active_coroutine != 2)) {
39383 self->private_impl.magic = WUFFS_BASE__DISABLED;
39384 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
39385 }
39386 self->private_impl.active_coroutine = 0;
39387 wuffs_base__status status = wuffs_base__make_status(NULL);
39388
39389 const uint8_t* iop_a_src = NULL;
39390 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39391 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39392 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39393 if (a_src) {
39394 io0_a_src = a_src->data.ptr;
39395 io1_a_src = io0_a_src + a_src->meta.ri;
39396 iop_a_src = io1_a_src;
39397 io2_a_src = io0_a_src + a_src->meta.wi;
39398 }
39399
39400 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
39401 switch (coro_susp_point) {
39402 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
39403
Nigel Taobf9dab32021-11-18 19:19:55 +110039404 if (self->private_impl.f_call_sequence == 255) {
39405 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
39406 goto ok;
39407 } else if (self->private_impl.f_call_sequence < 3) {
Nigel Taoe360a532021-04-05 22:47:03 +100039408 if (a_src) {
39409 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39410 }
39411 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
39412 status = wuffs_png__decoder__decode_image_config(self, NULL, a_src);
39413 if (a_src) {
39414 iop_a_src = a_src->data.ptr + a_src->meta.ri;
39415 }
39416 if (status.repr) {
39417 goto suspend;
39418 }
39419 } else if (self->private_impl.f_call_sequence == 3) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100039420 if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) {
Nigel Taoe360a532021-04-05 22:47:03 +100039421 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
39422 goto exit;
39423 }
39424 } else if (self->private_impl.f_call_sequence == 4) {
Nigel Taobf9dab32021-11-18 19:19:55 +110039425 if (a_src) {
39426 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39427 }
39428 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
39429 status = wuffs_png__decoder__skip_frame(self, a_src);
39430 if (a_src) {
39431 iop_a_src = a_src->data.ptr + a_src->meta.ri;
39432 }
39433 if (status.repr) {
39434 goto suspend;
39435 }
39436 if (self->private_impl.f_call_sequence == 255) {
39437 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
39438 goto ok;
39439 }
39440 }
39441 if (self->private_impl.f_num_decoded_frame_configs_value == 0) {
39442 self->private_impl.f_frame_rect_x0 = self->private_impl.f_first_rect_x0;
39443 self->private_impl.f_frame_rect_y0 = self->private_impl.f_first_rect_y0;
39444 self->private_impl.f_frame_rect_x1 = self->private_impl.f_first_rect_x1;
39445 self->private_impl.f_frame_rect_y1 = self->private_impl.f_first_rect_y1;
39446 self->private_impl.f_frame_config_io_position = self->private_impl.f_first_config_io_position;
39447 self->private_impl.f_frame_duration = self->private_impl.f_first_duration;
39448 self->private_impl.f_frame_disposal = self->private_impl.f_first_disposal;
39449 self->private_impl.f_frame_overwrite_instead_of_blend = self->private_impl.f_first_overwrite_instead_of_blend;
Nigel Taoe360a532021-04-05 22:47:03 +100039450 } else {
Nigel Taobf9dab32021-11-18 19:19:55 +110039451 while (true) {
39452 {
39453 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
39454 uint32_t t_0;
39455 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
39456 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
39457 iop_a_src += 4;
39458 } else {
39459 self->private_data.s_decode_frame_config[0].scratch = 0;
39460 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
39461 while (true) {
39462 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39463 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39464 goto suspend;
39465 }
39466 uint64_t* scratch = &self->private_data.s_decode_frame_config[0].scratch;
39467 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
39468 *scratch >>= 8;
39469 *scratch <<= 8;
39470 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
39471 if (num_bits_0 == 24) {
39472 t_0 = ((uint32_t)(*scratch >> 32));
39473 break;
39474 }
39475 num_bits_0 += 8;
39476 *scratch |= ((uint64_t)(num_bits_0));
39477 }
39478 }
39479 self->private_impl.f_chunk_length = t_0;
39480 }
39481 {
39482 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
39483 uint32_t t_1;
39484 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
39485 t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
39486 iop_a_src += 4;
39487 } else {
39488 self->private_data.s_decode_frame_config[0].scratch = 0;
39489 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
39490 while (true) {
39491 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39492 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39493 goto suspend;
39494 }
39495 uint64_t* scratch = &self->private_data.s_decode_frame_config[0].scratch;
39496 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
39497 *scratch <<= 8;
39498 *scratch >>= 8;
39499 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
39500 if (num_bits_1 == 24) {
39501 t_1 = ((uint32_t)(*scratch));
39502 break;
39503 }
39504 num_bits_1 += 8;
39505 *scratch |= ((uint64_t)(num_bits_1)) << 56;
39506 }
39507 }
39508 self->private_impl.f_chunk_type = t_1;
39509 }
39510 if (self->private_impl.f_chunk_type == 1413571686) {
39511 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39512 goto exit;
39513 } else if (self->private_impl.f_chunk_type == 1280598886) {
39514 self->private_impl.f_frame_config_io_position = ((uint64_t)(wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) - 8));
39515 if (a_src) {
39516 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39517 }
39518 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
39519 status = wuffs_png__decoder__decode_fctl(self, a_src);
39520 if (a_src) {
39521 iop_a_src = a_src->data.ptr + a_src->meta.ri;
39522 }
39523 if (status.repr) {
39524 goto suspend;
39525 }
39526 self->private_data.s_decode_frame_config[0].scratch = 4;
39527 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
39528 if (self->private_data.s_decode_frame_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
39529 self->private_data.s_decode_frame_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
39530 iop_a_src = io2_a_src;
39531 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39532 goto suspend;
39533 }
39534 iop_a_src += self->private_data.s_decode_frame_config[0].scratch;
39535 goto label__0__break;
39536 }
39537 self->private_data.s_decode_frame_config[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 4);
39538 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
39539 if (self->private_data.s_decode_frame_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
39540 self->private_data.s_decode_frame_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
39541 iop_a_src = io2_a_src;
39542 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39543 goto suspend;
39544 }
39545 iop_a_src += self->private_data.s_decode_frame_config[0].scratch;
39546 self->private_impl.f_chunk_length = 0;
39547 }
39548 label__0__break:;
Nigel Taoe360a532021-04-05 22:47:03 +100039549 }
39550 if (a_dst != NULL) {
39551 wuffs_base__frame_config__set(
39552 a_dst,
39553 wuffs_base__utility__make_rect_ie_u32(
Nigel Taobf9dab32021-11-18 19:19:55 +110039554 self->private_impl.f_frame_rect_x0,
39555 self->private_impl.f_frame_rect_y0,
39556 self->private_impl.f_frame_rect_x1,
39557 self->private_impl.f_frame_rect_y1),
39558 ((wuffs_base__flicks)(self->private_impl.f_frame_duration)),
39559 ((uint64_t)(self->private_impl.f_num_decoded_frame_configs_value)),
Nigel Taoe360a532021-04-05 22:47:03 +100039560 self->private_impl.f_frame_config_io_position,
Nigel Taobf9dab32021-11-18 19:19:55 +110039561 self->private_impl.f_frame_disposal,
39562 ((self->private_impl.f_color_type <= 3) && ! self->private_impl.f_seen_trns),
39563 self->private_impl.f_frame_overwrite_instead_of_blend,
Nigel Taoe360a532021-04-05 22:47:03 +100039564 0);
39565 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039566 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frame_configs_value, 1);
Nigel Taoe360a532021-04-05 22:47:03 +100039567 self->private_impl.f_call_sequence = 4;
39568
Nigel Taoe360a532021-04-05 22:47:03 +100039569 ok:
39570 self->private_impl.p_decode_frame_config[0] = 0;
39571 goto exit;
39572 }
39573
39574 goto suspend;
39575 suspend:
39576 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
39577 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
39578
39579 goto exit;
39580 exit:
39581 if (a_src) {
39582 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39583 }
39584
39585 if (wuffs_base__status__is_error(&status)) {
39586 self->private_impl.magic = WUFFS_BASE__DISABLED;
39587 }
39588 return status;
39589}
39590
Nigel Taobf9dab32021-11-18 19:19:55 +110039591// -------- func png.decoder.skip_frame
39592
39593static wuffs_base__status
39594wuffs_png__decoder__skip_frame(
39595 wuffs_png__decoder* self,
39596 wuffs_base__io_buffer* a_src) {
39597 wuffs_base__status status = wuffs_base__make_status(NULL);
39598
39599 uint32_t v_seq_num = 0;
39600
39601 const uint8_t* iop_a_src = NULL;
39602 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39603 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39604 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39605 if (a_src) {
39606 io0_a_src = a_src->data.ptr;
39607 io1_a_src = io0_a_src + a_src->meta.ri;
39608 iop_a_src = io1_a_src;
39609 io2_a_src = io0_a_src + a_src->meta.wi;
39610 }
39611
39612 uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
39613 switch (coro_susp_point) {
39614 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
39615
39616 self->private_impl.f_chunk_type_array[0] = 0;
39617 self->private_impl.f_chunk_type_array[1] = 0;
39618 self->private_impl.f_chunk_type_array[2] = 0;
39619 self->private_impl.f_chunk_type_array[3] = 0;
39620 label__0__continue:;
39621 while (true) {
39622 while (((uint64_t)(io2_a_src - iop_a_src)) < 8) {
39623 if (a_src && a_src->meta.closed) {
39624 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39625 goto exit;
39626 }
39627 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39628 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
39629 }
39630 self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
39631 self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32)));
39632 if (self->private_impl.f_chunk_type == 1413563465) {
39633 if (self->private_impl.f_chunk_type_array[0] == 102) {
39634 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39635 goto exit;
39636 }
39637 self->private_impl.f_chunk_type_array[0] = 73;
39638 self->private_impl.f_chunk_type_array[1] = 68;
39639 self->private_impl.f_chunk_type_array[2] = 65;
39640 self->private_impl.f_chunk_type_array[3] = 84;
39641 } else if (self->private_impl.f_chunk_type == 1413571686) {
39642 if (self->private_impl.f_chunk_type_array[0] == 73) {
39643 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39644 goto exit;
39645 }
39646 self->private_impl.f_chunk_type_array[0] = 102;
39647 self->private_impl.f_chunk_type_array[1] = 100;
39648 self->private_impl.f_chunk_type_array[2] = 65;
39649 self->private_impl.f_chunk_type_array[3] = 84;
39650 if (self->private_impl.f_chunk_length < 4) {
39651 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39652 goto exit;
39653 }
39654 self->private_impl.f_chunk_length -= 4;
39655 iop_a_src += 8;
39656 {
39657 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
39658 uint32_t t_0;
39659 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
39660 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
39661 iop_a_src += 4;
39662 } else {
39663 self->private_data.s_skip_frame[0].scratch = 0;
39664 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
39665 while (true) {
39666 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39667 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39668 goto suspend;
39669 }
39670 uint64_t* scratch = &self->private_data.s_skip_frame[0].scratch;
39671 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
39672 *scratch >>= 8;
39673 *scratch <<= 8;
39674 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
39675 if (num_bits_0 == 24) {
39676 t_0 = ((uint32_t)(*scratch >> 32));
39677 break;
39678 }
39679 num_bits_0 += 8;
39680 *scratch |= ((uint64_t)(num_bits_0));
39681 }
39682 }
39683 v_seq_num = t_0;
39684 }
39685 if (v_seq_num != self->private_impl.f_next_animation_seq_num) {
39686 status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number);
39687 goto exit;
39688 } else if (self->private_impl.f_next_animation_seq_num >= 4294967295) {
39689 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
39690 goto exit;
39691 }
39692 self->private_impl.f_next_animation_seq_num += 1;
39693 self->private_data.s_skip_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 4);
39694 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
39695 if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
39696 self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
39697 iop_a_src = io2_a_src;
39698 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39699 goto suspend;
39700 }
39701 iop_a_src += self->private_data.s_skip_frame[0].scratch;
39702 self->private_impl.f_chunk_length = 0;
39703 goto label__0__continue;
39704 } else if (self->private_impl.f_chunk_type_array[0] != 0) {
39705 goto label__0__break;
39706 } else if (self->private_impl.f_chunk_type == 1280598886) {
39707 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39708 goto exit;
39709 }
39710 self->private_data.s_skip_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 12);
39711 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
39712 if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
39713 self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
39714 iop_a_src = io2_a_src;
39715 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39716 goto suspend;
39717 }
39718 iop_a_src += self->private_data.s_skip_frame[0].scratch;
39719 self->private_impl.f_chunk_length = 0;
39720 }
39721 label__0__break:;
39722 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
39723 if (self->private_impl.f_num_decoded_frames_value < self->private_impl.f_num_animation_frames_value) {
39724 self->private_impl.f_call_sequence = 5;
39725 } else {
39726 self->private_impl.f_call_sequence = 255;
39727 }
39728
39729 ok:
39730 self->private_impl.p_skip_frame[0] = 0;
39731 goto exit;
39732 }
39733
39734 goto suspend;
39735 suspend:
39736 self->private_impl.p_skip_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
39737
39738 goto exit;
39739 exit:
39740 if (a_src) {
39741 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39742 }
39743
39744 return status;
39745}
39746
Nigel Taoe360a532021-04-05 22:47:03 +100039747// -------- func png.decoder.decode_frame
39748
39749WUFFS_BASE__MAYBE_STATIC wuffs_base__status
39750wuffs_png__decoder__decode_frame(
39751 wuffs_png__decoder* self,
39752 wuffs_base__pixel_buffer* a_dst,
39753 wuffs_base__io_buffer* a_src,
39754 wuffs_base__pixel_blend a_blend,
39755 wuffs_base__slice_u8 a_workbuf,
39756 wuffs_base__decode_frame_options* a_opts) {
39757 if (!self) {
39758 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
39759 }
39760 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
39761 return wuffs_base__make_status(
39762 (self->private_impl.magic == WUFFS_BASE__DISABLED)
39763 ? wuffs_base__error__disabled_by_previous_error
39764 : wuffs_base__error__initialize_not_called);
39765 }
39766 if (!a_dst || !a_src) {
39767 self->private_impl.magic = WUFFS_BASE__DISABLED;
39768 return wuffs_base__make_status(wuffs_base__error__bad_argument);
39769 }
39770 if ((self->private_impl.active_coroutine != 0) &&
39771 (self->private_impl.active_coroutine != 3)) {
39772 self->private_impl.magic = WUFFS_BASE__DISABLED;
39773 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
39774 }
39775 self->private_impl.active_coroutine = 0;
39776 wuffs_base__status status = wuffs_base__make_status(NULL);
39777
Nigel Taobf9dab32021-11-18 19:19:55 +110039778 uint32_t v_seq_num = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100039779 wuffs_base__status v_status = wuffs_base__make_status(NULL);
39780 uint32_t v_pass_width = 0;
39781 uint32_t v_pass_height = 0;
39782
Nigel Taobf9dab32021-11-18 19:19:55 +110039783 const uint8_t* iop_a_src = NULL;
39784 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39785 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39786 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39787 if (a_src) {
39788 io0_a_src = a_src->data.ptr;
39789 io1_a_src = io0_a_src + a_src->meta.ri;
39790 iop_a_src = io1_a_src;
39791 io2_a_src = io0_a_src + a_src->meta.wi;
39792 }
39793
Nigel Taoe360a532021-04-05 22:47:03 +100039794 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
39795 switch (coro_susp_point) {
39796 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
39797
Nigel Taobf9dab32021-11-18 19:19:55 +110039798 if (self->private_impl.f_call_sequence == 255) {
39799 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
39800 goto ok;
39801 } else if (self->private_impl.f_call_sequence != 4) {
39802 if (a_src) {
39803 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39804 }
Nigel Taoe360a532021-04-05 22:47:03 +100039805 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
39806 status = wuffs_png__decoder__decode_frame_config(self, NULL, a_src);
Nigel Taobf9dab32021-11-18 19:19:55 +110039807 if (a_src) {
39808 iop_a_src = a_src->data.ptr + a_src->meta.ri;
39809 }
Nigel Taoe360a532021-04-05 22:47:03 +100039810 if (status.repr) {
39811 goto suspend;
39812 }
Nigel Taoe360a532021-04-05 22:47:03 +100039813 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039814 while (true) {
39815 while (((uint64_t)(io2_a_src - iop_a_src)) < 8) {
39816 if (a_src && a_src->meta.closed) {
39817 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39818 goto exit;
39819 }
39820 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39821 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
39822 }
39823 self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
39824 self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32)));
39825 if (self->private_impl.f_chunk_type == 1413563465) {
39826 self->private_impl.f_chunk_type_array[0] = 73;
39827 self->private_impl.f_chunk_type_array[1] = 68;
39828 self->private_impl.f_chunk_type_array[2] = 65;
39829 self->private_impl.f_chunk_type_array[3] = 84;
39830 iop_a_src += 8;
39831 if ( ! self->private_impl.f_ignore_checksum) {
39832 wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32,
39833 sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
39834 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4));
39835 }
39836 goto label__0__break;
39837 } else if (self->private_impl.f_chunk_type == 1413571686) {
39838 self->private_impl.f_chunk_type_array[0] = 102;
39839 self->private_impl.f_chunk_type_array[1] = 100;
39840 self->private_impl.f_chunk_type_array[2] = 65;
39841 self->private_impl.f_chunk_type_array[3] = 84;
39842 if (self->private_impl.f_chunk_length < 4) {
39843 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39844 goto exit;
39845 }
39846 self->private_impl.f_chunk_length -= 4;
39847 iop_a_src += 8;
39848 {
39849 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
39850 uint32_t t_0;
39851 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
39852 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
39853 iop_a_src += 4;
39854 } else {
39855 self->private_data.s_decode_frame[0].scratch = 0;
39856 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
39857 while (true) {
39858 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39859 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39860 goto suspend;
39861 }
39862 uint64_t* scratch = &self->private_data.s_decode_frame[0].scratch;
39863 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
39864 *scratch >>= 8;
39865 *scratch <<= 8;
39866 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
39867 if (num_bits_0 == 24) {
39868 t_0 = ((uint32_t)(*scratch >> 32));
39869 break;
39870 }
39871 num_bits_0 += 8;
39872 *scratch |= ((uint64_t)(num_bits_0));
39873 }
39874 }
39875 v_seq_num = t_0;
39876 }
39877 if (v_seq_num != self->private_impl.f_next_animation_seq_num) {
39878 status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number);
39879 goto exit;
39880 } else if (self->private_impl.f_next_animation_seq_num >= 4294967295) {
39881 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
39882 goto exit;
39883 }
39884 self->private_impl.f_next_animation_seq_num += 1;
39885 goto label__0__break;
39886 } else if (self->private_impl.f_chunk_type == 1280598886) {
39887 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39888 goto exit;
39889 }
39890 self->private_data.s_decode_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 12);
39891 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
39892 if (self->private_data.s_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
39893 self->private_data.s_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
39894 iop_a_src = io2_a_src;
39895 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39896 goto suspend;
39897 }
39898 iop_a_src += self->private_data.s_decode_frame[0].scratch;
39899 self->private_impl.f_chunk_length = 0;
39900 }
39901 label__0__break:;
39902 if (self->private_impl.f_zlib_is_dirty) {
39903 wuffs_base__ignore_status(wuffs_zlib__decoder__initialize(&self->private_data.f_zlib,
39904 sizeof (wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
39905 if (self->private_impl.f_ignore_checksum) {
39906 wuffs_zlib__decoder__set_quirk_enabled(&self->private_data.f_zlib, 1, true);
39907 }
39908 }
39909 self->private_impl.f_zlib_is_dirty = true;
Nigel Taoe360a532021-04-05 22:47:03 +100039910 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
39911 wuffs_base__pixel_buffer__pixel_format(a_dst),
39912 wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)),
39913 wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt),
39914 wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024),
39915 a_blend);
39916 if ( ! wuffs_base__status__is_ok(&v_status)) {
39917 status = v_status;
39918 if (wuffs_base__status__is_error(&status)) {
39919 goto exit;
39920 } else if (wuffs_base__status__is_suspension(&status)) {
39921 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
39922 goto exit;
39923 }
39924 goto ok;
39925 }
Nigel Tao7804ffe2021-10-07 21:58:26 +110039926 self->private_impl.f_workbuf_hist_pos_base = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100039927 while (true) {
Nigel Taobf9dab32021-11-18 19:19:55 +110039928 if (self->private_impl.f_chunk_type_array[0] == 73) {
39929 v_pass_width = (16777215 & ((((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][1])) + self->private_impl.f_width) >> WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0]));
39930 v_pass_height = (16777215 & ((((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][4])) + self->private_impl.f_height) >> WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][3]));
39931 } else {
39932 v_pass_width = (16777215 & ((uint32_t)(self->private_impl.f_frame_rect_x1 - self->private_impl.f_frame_rect_x0)));
39933 v_pass_height = (16777215 & ((uint32_t)(self->private_impl.f_frame_rect_y1 - self->private_impl.f_frame_rect_y0)));
39934 }
Nigel Taoe360a532021-04-05 22:47:03 +100039935 if ((v_pass_width > 0) && (v_pass_height > 0)) {
39936 self->private_impl.f_pass_bytes_per_row = wuffs_png__decoder__calculate_bytes_per_row(self, v_pass_width);
39937 self->private_impl.f_pass_workbuf_length = (((uint64_t)(v_pass_height)) * (1 + self->private_impl.f_pass_bytes_per_row));
Nigel Taobf9dab32021-11-18 19:19:55 +110039938 if (a_src) {
39939 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39940 }
39941 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
Nigel Taoe360a532021-04-05 22:47:03 +100039942 status = wuffs_png__decoder__decode_pass(self, a_src, a_workbuf);
Nigel Taobf9dab32021-11-18 19:19:55 +110039943 if (a_src) {
39944 iop_a_src = a_src->data.ptr + a_src->meta.ri;
39945 }
Nigel Taoe360a532021-04-05 22:47:03 +100039946 if (status.repr) {
39947 goto suspend;
39948 }
39949 v_status = wuffs_png__decoder__filter_and_swizzle(self, a_dst, a_workbuf);
39950 if ( ! wuffs_base__status__is_ok(&v_status)) {
39951 status = v_status;
39952 if (wuffs_base__status__is_error(&status)) {
39953 goto exit;
39954 } else if (wuffs_base__status__is_suspension(&status)) {
39955 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
39956 goto exit;
39957 }
39958 goto ok;
39959 }
Nigel Tao7804ffe2021-10-07 21:58:26 +110039960 self->private_impl.f_workbuf_hist_pos_base += self->private_impl.f_pass_workbuf_length;
Nigel Taoe360a532021-04-05 22:47:03 +100039961 }
39962 if ((self->private_impl.f_interlace_pass == 0) || (self->private_impl.f_interlace_pass >= 7)) {
Nigel Taobf9dab32021-11-18 19:19:55 +110039963 goto label__1__break;
Nigel Taoe360a532021-04-05 22:47:03 +100039964 }
39965#if defined(__GNUC__)
39966#pragma GCC diagnostic push
39967#pragma GCC diagnostic ignored "-Wconversion"
39968#endif
39969 self->private_impl.f_interlace_pass += 1;
39970#if defined(__GNUC__)
39971#pragma GCC diagnostic pop
39972#endif
39973 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039974 label__1__break:;
39975 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
39976 if (self->private_impl.f_num_decoded_frames_value < self->private_impl.f_num_animation_frames_value) {
39977 self->private_impl.f_call_sequence = 5;
39978 } else {
39979 self->private_impl.f_call_sequence = 255;
39980 }
Nigel Taoe360a532021-04-05 22:47:03 +100039981
Nigel Taoe360a532021-04-05 22:47:03 +100039982 ok:
39983 self->private_impl.p_decode_frame[0] = 0;
39984 goto exit;
39985 }
39986
39987 goto suspend;
39988 suspend:
39989 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
39990 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
39991
39992 goto exit;
39993 exit:
Nigel Taobf9dab32021-11-18 19:19:55 +110039994 if (a_src) {
39995 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39996 }
39997
Nigel Taoe360a532021-04-05 22:47:03 +100039998 if (wuffs_base__status__is_error(&status)) {
39999 self->private_impl.magic = WUFFS_BASE__DISABLED;
40000 }
40001 return status;
40002}
40003
40004// -------- func png.decoder.decode_pass
40005
40006static wuffs_base__status
40007wuffs_png__decoder__decode_pass(
40008 wuffs_png__decoder* self,
40009 wuffs_base__io_buffer* a_src,
40010 wuffs_base__slice_u8 a_workbuf) {
40011 wuffs_base__status status = wuffs_base__make_status(NULL);
40012
40013 wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer();
40014 wuffs_base__io_buffer* v_w = &u_w;
40015 uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40016 uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40017 uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40018 uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40019 uint64_t v_w_mark = 0;
40020 uint64_t v_r_mark = 0;
40021 wuffs_base__status v_zlib_status = wuffs_base__make_status(NULL);
40022 uint32_t v_checksum_have = 0;
40023 uint32_t v_checksum_want = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110040024 uint32_t v_seq_num = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100040025
40026 const uint8_t* iop_a_src = NULL;
40027 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40028 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40029 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40030 if (a_src) {
40031 io0_a_src = a_src->data.ptr;
40032 io1_a_src = io0_a_src + a_src->meta.ri;
40033 iop_a_src = io1_a_src;
40034 io2_a_src = io0_a_src + a_src->meta.wi;
40035 }
40036
40037 uint32_t coro_susp_point = self->private_impl.p_decode_pass[0];
Nigel Taoe360a532021-04-05 22:47:03 +100040038 switch (coro_susp_point) {
40039 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
40040
40041 self->private_impl.f_workbuf_wi = 0;
40042 label__0__continue:;
40043 while (true) {
40044 if ((self->private_impl.f_workbuf_wi > self->private_impl.f_pass_workbuf_length) || (self->private_impl.f_pass_workbuf_length > ((uint64_t)(a_workbuf.len)))) {
40045 status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length);
40046 goto exit;
40047 }
40048 {
40049 wuffs_base__io_buffer* o_0_v_w = v_w;
40050 uint8_t *o_0_iop_v_w = iop_v_w;
40051 uint8_t *o_0_io0_v_w = io0_v_w;
40052 uint8_t *o_0_io1_v_w = io1_v_w;
40053 uint8_t *o_0_io2_v_w = io2_v_w;
40054 v_w = wuffs_base__io_writer__set(
40055 &u_w,
40056 &iop_v_w,
40057 &io0_v_w,
40058 &io1_v_w,
40059 &io2_v_w,
40060 wuffs_base__slice_u8__subslice_ij(a_workbuf,
40061 self->private_impl.f_workbuf_wi,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100040062 self->private_impl.f_pass_workbuf_length),
Nigel Tao7804ffe2021-10-07 21:58:26 +110040063 ((uint64_t)(self->private_impl.f_workbuf_hist_pos_base + self->private_impl.f_workbuf_wi)));
Nigel Taoe360a532021-04-05 22:47:03 +100040064 {
40065 const uint8_t *o_1_io2_a_src = io2_a_src;
40066 wuffs_base__io_reader__limit(&io2_a_src, iop_a_src,
Nigel Taobf9dab32021-11-18 19:19:55 +110040067 ((uint64_t)(self->private_impl.f_chunk_length)));
Nigel Taoe360a532021-04-05 22:47:03 +100040068 if (a_src) {
40069 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
40070 }
40071 v_w_mark = ((uint64_t)(iop_v_w - io0_v_w));
40072 v_r_mark = ((uint64_t)(iop_a_src - io0_a_src));
40073 {
40074 u_w.meta.wi = ((size_t)(iop_v_w - u_w.data.ptr));
40075 if (a_src) {
40076 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40077 }
40078 wuffs_base__status t_0 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, v_w, a_src, wuffs_base__utility__empty_slice_u8());
40079 v_zlib_status = t_0;
40080 iop_v_w = u_w.data.ptr + u_w.meta.wi;
40081 if (a_src) {
40082 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40083 }
40084 }
40085 if ( ! self->private_impl.f_ignore_checksum) {
40086 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__io__since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src));
40087 }
Nigel Taobf9dab32021-11-18 19:19:55 +110040088 wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)((wuffs_base__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src))) & 4294967295))));
Nigel Taoe360a532021-04-05 22:47:03 +100040089 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_workbuf_wi, wuffs_base__io__count_since(v_w_mark, ((uint64_t)(iop_v_w - io0_v_w))));
40090 io2_a_src = o_1_io2_a_src;
40091 if (a_src) {
40092 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
40093 }
40094 }
40095 v_w = o_0_v_w;
40096 iop_v_w = o_0_iop_v_w;
40097 io0_v_w = o_0_io0_v_w;
40098 io1_v_w = o_0_io1_v_w;
40099 io2_v_w = o_0_io2_v_w;
40100 }
40101 if (wuffs_base__status__is_ok(&v_zlib_status)) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040102 if (self->private_impl.f_chunk_length > 0) {
40103 status = wuffs_base__make_status(wuffs_base__error__too_much_data);
40104 goto exit;
40105 }
40106 {
40107 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
40108 uint32_t t_1;
40109 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40110 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
40111 iop_a_src += 4;
40112 } else {
40113 self->private_data.s_decode_pass[0].scratch = 0;
40114 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
40115 while (true) {
40116 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40117 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40118 goto suspend;
Nigel Taoe360a532021-04-05 22:47:03 +100040119 }
Nigel Taobf9dab32021-11-18 19:19:55 +110040120 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
40121 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
40122 *scratch >>= 8;
40123 *scratch <<= 8;
40124 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
40125 if (num_bits_1 == 24) {
40126 t_1 = ((uint32_t)(*scratch >> 32));
40127 break;
40128 }
40129 num_bits_1 += 8;
40130 *scratch |= ((uint64_t)(num_bits_1));
Nigel Taoe360a532021-04-05 22:47:03 +100040131 }
Nigel Taoe360a532021-04-05 22:47:03 +100040132 }
Nigel Taobf9dab32021-11-18 19:19:55 +110040133 v_checksum_want = t_1;
40134 }
40135 if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_chunk_type_array[0] == 73)) {
40136 v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__utility__empty_slice_u8());
Nigel Taoe360a532021-04-05 22:47:03 +100040137 if (v_checksum_have != v_checksum_want) {
40138 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
40139 goto exit;
40140 }
40141 }
40142 goto label__0__break;
40143 } else if (v_zlib_status.repr == wuffs_base__suspension__short_write) {
40144 if ((1 <= self->private_impl.f_interlace_pass) && (self->private_impl.f_interlace_pass <= 6)) {
40145 goto label__0__break;
40146 }
40147 status = wuffs_base__make_status(wuffs_base__error__too_much_data);
40148 goto exit;
40149 } else if (v_zlib_status.repr != wuffs_base__suspension__short_read) {
40150 status = v_zlib_status;
40151 if (wuffs_base__status__is_error(&status)) {
40152 goto exit;
40153 } else if (wuffs_base__status__is_suspension(&status)) {
40154 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
40155 goto exit;
40156 }
40157 goto ok;
40158 } else if (self->private_impl.f_chunk_length == 0) {
40159 {
40160 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
40161 uint32_t t_2;
40162 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40163 t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
40164 iop_a_src += 4;
40165 } else {
40166 self->private_data.s_decode_pass[0].scratch = 0;
40167 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
40168 while (true) {
40169 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40170 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40171 goto suspend;
40172 }
40173 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
40174 uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFF));
40175 *scratch >>= 8;
40176 *scratch <<= 8;
40177 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2);
40178 if (num_bits_2 == 24) {
40179 t_2 = ((uint32_t)(*scratch >> 32));
40180 break;
40181 }
40182 num_bits_2 += 8;
40183 *scratch |= ((uint64_t)(num_bits_2));
40184 }
40185 }
40186 v_checksum_want = t_2;
40187 }
Nigel Taobf9dab32021-11-18 19:19:55 +110040188 if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_chunk_type_array[0] == 73)) {
Nigel Taoe360a532021-04-05 22:47:03 +100040189 v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__utility__empty_slice_u8());
40190 if (v_checksum_have != v_checksum_want) {
40191 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
40192 goto exit;
40193 }
40194 }
40195 {
40196 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
Nigel Taobf9dab32021-11-18 19:19:55 +110040197 uint32_t t_3;
Nigel Taoe360a532021-04-05 22:47:03 +100040198 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040199 t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
Nigel Taoe360a532021-04-05 22:47:03 +100040200 iop_a_src += 4;
40201 } else {
40202 self->private_data.s_decode_pass[0].scratch = 0;
40203 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
40204 while (true) {
40205 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40206 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40207 goto suspend;
40208 }
40209 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
40210 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
40211 *scratch >>= 8;
40212 *scratch <<= 8;
40213 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
40214 if (num_bits_3 == 24) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040215 t_3 = ((uint32_t)(*scratch >> 32));
Nigel Taoe360a532021-04-05 22:47:03 +100040216 break;
40217 }
40218 num_bits_3 += 8;
40219 *scratch |= ((uint64_t)(num_bits_3));
40220 }
40221 }
40222 self->private_impl.f_chunk_length = t_3;
40223 }
40224 {
40225 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
40226 uint32_t t_4;
40227 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40228 t_4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
40229 iop_a_src += 4;
40230 } else {
40231 self->private_data.s_decode_pass[0].scratch = 0;
40232 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
40233 while (true) {
40234 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40235 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40236 goto suspend;
40237 }
40238 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
40239 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
40240 *scratch <<= 8;
40241 *scratch >>= 8;
40242 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
40243 if (num_bits_4 == 24) {
40244 t_4 = ((uint32_t)(*scratch));
40245 break;
40246 }
40247 num_bits_4 += 8;
40248 *scratch |= ((uint64_t)(num_bits_4)) << 56;
40249 }
40250 }
40251 self->private_impl.f_chunk_type = t_4;
40252 }
Nigel Taobf9dab32021-11-18 19:19:55 +110040253 if (self->private_impl.f_chunk_type_array[0] == 73) {
40254 if (self->private_impl.f_chunk_type != 1413563465) {
40255 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40256 goto exit;
40257 }
40258 if ( ! self->private_impl.f_ignore_checksum) {
40259 wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32,
40260 sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
40261 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4));
40262 }
40263 } else {
40264 if ((self->private_impl.f_chunk_type != 1413571686) || (self->private_impl.f_chunk_length < 4)) {
40265 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40266 goto exit;
40267 }
40268 self->private_impl.f_chunk_length -= 4;
40269 {
40270 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
40271 uint32_t t_5;
40272 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40273 t_5 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
40274 iop_a_src += 4;
40275 } else {
40276 self->private_data.s_decode_pass[0].scratch = 0;
40277 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
40278 while (true) {
40279 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40280 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40281 goto suspend;
40282 }
40283 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
40284 uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFF));
40285 *scratch >>= 8;
40286 *scratch <<= 8;
40287 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5);
40288 if (num_bits_5 == 24) {
40289 t_5 = ((uint32_t)(*scratch >> 32));
40290 break;
40291 }
40292 num_bits_5 += 8;
40293 *scratch |= ((uint64_t)(num_bits_5));
40294 }
40295 }
40296 v_seq_num = t_5;
40297 }
40298 if (v_seq_num != self->private_impl.f_next_animation_seq_num) {
40299 status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number);
40300 goto exit;
40301 } else if (self->private_impl.f_next_animation_seq_num >= 4294967295) {
40302 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
40303 goto exit;
40304 }
40305 self->private_impl.f_next_animation_seq_num += 1;
Nigel Taoe360a532021-04-05 22:47:03 +100040306 }
40307 goto label__0__continue;
40308 } else if (((uint64_t)(io2_a_src - iop_a_src)) > 0) {
40309 status = wuffs_base__make_status(wuffs_png__error__internal_error_zlib_decoder_did_not_exhaust_its_input);
40310 goto exit;
40311 }
40312 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
Nigel Taobf9dab32021-11-18 19:19:55 +110040313 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
Nigel Taoe360a532021-04-05 22:47:03 +100040314 }
40315 label__0__break:;
40316 if (self->private_impl.f_workbuf_wi != self->private_impl.f_pass_workbuf_length) {
40317 status = wuffs_base__make_status(wuffs_base__error__not_enough_data);
40318 goto exit;
40319 } else if (0 < ((uint64_t)(a_workbuf.len))) {
40320 if (a_workbuf.ptr[0] == 4) {
40321 a_workbuf.ptr[0] = 1;
40322 }
40323 }
40324
Nigel Taoe360a532021-04-05 22:47:03 +100040325 ok:
40326 self->private_impl.p_decode_pass[0] = 0;
40327 goto exit;
40328 }
40329
40330 goto suspend;
40331 suspend:
40332 self->private_impl.p_decode_pass[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
Nigel Taoe360a532021-04-05 22:47:03 +100040333
40334 goto exit;
40335 exit:
40336 if (a_src) {
40337 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40338 }
40339
40340 return status;
40341}
40342
40343// -------- func png.decoder.frame_dirty_rect
40344
40345WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
40346wuffs_png__decoder__frame_dirty_rect(
40347 const wuffs_png__decoder* self) {
40348 if (!self) {
40349 return wuffs_base__utility__empty_rect_ie_u32();
40350 }
40351 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
40352 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
40353 return wuffs_base__utility__empty_rect_ie_u32();
40354 }
40355
40356 return wuffs_base__utility__make_rect_ie_u32(
Nigel Taobf9dab32021-11-18 19:19:55 +110040357 self->private_impl.f_frame_rect_x0,
40358 self->private_impl.f_frame_rect_y0,
40359 self->private_impl.f_frame_rect_x1,
40360 self->private_impl.f_frame_rect_y1);
Nigel Taoe360a532021-04-05 22:47:03 +100040361}
40362
40363// -------- func png.decoder.num_animation_loops
40364
40365WUFFS_BASE__MAYBE_STATIC uint32_t
40366wuffs_png__decoder__num_animation_loops(
40367 const wuffs_png__decoder* self) {
40368 if (!self) {
40369 return 0;
40370 }
40371 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
40372 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
40373 return 0;
40374 }
40375
Nigel Taobf9dab32021-11-18 19:19:55 +110040376 return self->private_impl.f_num_animation_loops_value;
Nigel Taoe360a532021-04-05 22:47:03 +100040377}
40378
40379// -------- func png.decoder.num_decoded_frame_configs
40380
40381WUFFS_BASE__MAYBE_STATIC uint64_t
40382wuffs_png__decoder__num_decoded_frame_configs(
40383 const wuffs_png__decoder* self) {
40384 if (!self) {
40385 return 0;
40386 }
40387 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
40388 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
40389 return 0;
40390 }
40391
Nigel Taobf9dab32021-11-18 19:19:55 +110040392 return ((uint64_t)(self->private_impl.f_num_decoded_frame_configs_value));
Nigel Taoe360a532021-04-05 22:47:03 +100040393}
40394
40395// -------- func png.decoder.num_decoded_frames
40396
40397WUFFS_BASE__MAYBE_STATIC uint64_t
40398wuffs_png__decoder__num_decoded_frames(
40399 const wuffs_png__decoder* self) {
40400 if (!self) {
40401 return 0;
40402 }
40403 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
40404 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
40405 return 0;
40406 }
40407
Nigel Taobf9dab32021-11-18 19:19:55 +110040408 return ((uint64_t)(self->private_impl.f_num_decoded_frames_value));
Nigel Taoe360a532021-04-05 22:47:03 +100040409}
40410
40411// -------- func png.decoder.restart_frame
40412
40413WUFFS_BASE__MAYBE_STATIC wuffs_base__status
40414wuffs_png__decoder__restart_frame(
40415 wuffs_png__decoder* self,
40416 uint64_t a_index,
40417 uint64_t a_io_position) {
40418 if (!self) {
40419 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
40420 }
40421 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
40422 return wuffs_base__make_status(
40423 (self->private_impl.magic == WUFFS_BASE__DISABLED)
40424 ? wuffs_base__error__disabled_by_previous_error
40425 : wuffs_base__error__initialize_not_called);
40426 }
40427
40428 if (self->private_impl.f_call_sequence < 3) {
40429 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
Nigel Taobf9dab32021-11-18 19:19:55 +110040430 } else if ((a_index >= ((uint64_t)(self->private_impl.f_num_animation_frames_value))) || ((a_index == 0) && (a_io_position != self->private_impl.f_first_config_io_position))) {
Nigel Taoe360a532021-04-05 22:47:03 +100040431 return wuffs_base__make_status(wuffs_base__error__bad_argument);
40432 }
40433 self->private_impl.f_call_sequence = 3;
40434 if (self->private_impl.f_interlace_pass >= 1) {
40435 self->private_impl.f_interlace_pass = 1;
40436 }
40437 self->private_impl.f_frame_config_io_position = a_io_position;
Nigel Taobf9dab32021-11-18 19:19:55 +110040438 self->private_impl.f_num_decoded_frame_configs_value = ((uint32_t)((a_index & 4294967295)));
40439 self->private_impl.f_num_decoded_frames_value = self->private_impl.f_num_decoded_frame_configs_value;
Nigel Taoe360a532021-04-05 22:47:03 +100040440 return wuffs_base__make_status(NULL);
40441}
40442
40443// -------- func png.decoder.set_report_metadata
40444
40445WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
40446wuffs_png__decoder__set_report_metadata(
40447 wuffs_png__decoder* self,
40448 uint32_t a_fourcc,
40449 bool a_report) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040450 if (!self) {
40451 return wuffs_base__make_empty_struct();
40452 }
40453 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
40454 return wuffs_base__make_empty_struct();
40455 }
40456
40457 if (a_fourcc == 1128813133) {
40458 self->private_impl.f_report_metadata_chrm = a_report;
40459 } else if (a_fourcc == 1195461953) {
40460 self->private_impl.f_report_metadata_gama = a_report;
40461 } else if (a_fourcc == 1229144912) {
40462 self->private_impl.f_report_metadata_iccp = a_report;
40463 } else if (a_fourcc == 1263947808) {
40464 self->private_impl.f_report_metadata_kvp = a_report;
40465 } else if (a_fourcc == 1397901122) {
40466 self->private_impl.f_report_metadata_srgb = a_report;
40467 }
Nigel Taoe360a532021-04-05 22:47:03 +100040468 return wuffs_base__make_empty_struct();
40469}
40470
40471// -------- func png.decoder.tell_me_more
40472
40473WUFFS_BASE__MAYBE_STATIC wuffs_base__status
40474wuffs_png__decoder__tell_me_more(
40475 wuffs_png__decoder* self,
40476 wuffs_base__io_buffer* a_dst,
40477 wuffs_base__more_information* a_minfo,
40478 wuffs_base__io_buffer* a_src) {
40479 if (!self) {
40480 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
40481 }
40482 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
40483 return wuffs_base__make_status(
40484 (self->private_impl.magic == WUFFS_BASE__DISABLED)
40485 ? wuffs_base__error__disabled_by_previous_error
40486 : wuffs_base__error__initialize_not_called);
40487 }
40488 if (!a_dst || !a_src) {
40489 self->private_impl.magic = WUFFS_BASE__DISABLED;
40490 return wuffs_base__make_status(wuffs_base__error__bad_argument);
40491 }
40492 if ((self->private_impl.active_coroutine != 0) &&
40493 (self->private_impl.active_coroutine != 4)) {
40494 self->private_impl.magic = WUFFS_BASE__DISABLED;
40495 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
40496 }
40497 self->private_impl.active_coroutine = 0;
40498 wuffs_base__status status = wuffs_base__make_status(NULL);
40499
Nigel Taobf9dab32021-11-18 19:19:55 +110040500 uint8_t v_c = 0;
40501 uint16_t v_c2 = 0;
40502 wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer();
40503 wuffs_base__io_buffer* v_w = &u_w;
40504 uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40505 uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40506 uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40507 uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40508 uint64_t v_num_written = 0;
40509 uint64_t v_w_mark = 0;
40510 uint64_t v_r_mark = 0;
40511 wuffs_base__status v_zlib_status = wuffs_base__make_status(NULL);
Nigel Taoe360a532021-04-05 22:47:03 +100040512
Nigel Taobf9dab32021-11-18 19:19:55 +110040513 uint8_t* iop_a_dst = NULL;
40514 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40515 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40516 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40517 if (a_dst) {
40518 io0_a_dst = a_dst->data.ptr;
40519 io1_a_dst = io0_a_dst + a_dst->meta.wi;
40520 iop_a_dst = io1_a_dst;
40521 io2_a_dst = io0_a_dst + a_dst->data.len;
40522 if (a_dst->meta.closed) {
40523 io2_a_dst = iop_a_dst;
40524 }
40525 }
40526 const uint8_t* iop_a_src = NULL;
40527 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40528 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40529 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40530 if (a_src) {
40531 io0_a_src = a_src->data.ptr;
40532 io1_a_src = io0_a_src + a_src->meta.ri;
40533 iop_a_src = io1_a_src;
40534 io2_a_src = io0_a_src + a_src->meta.wi;
40535 }
40536
40537 uint32_t coro_susp_point = self->private_impl.p_tell_me_more[0];
40538 if (coro_susp_point) {
40539 v_zlib_status = self->private_data.s_tell_me_more[0].v_zlib_status;
40540 }
40541 switch (coro_susp_point) {
40542 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
40543
40544 if (self->private_impl.f_call_sequence != 1) {
40545 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
40546 goto exit;
40547 }
40548 if (self->private_impl.f_metadata_fourcc == 0) {
40549 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
40550 goto exit;
40551 }
40552 if (self->private_impl.f_metadata_is_zlib_compressed) {
40553 if (self->private_impl.f_zlib_is_dirty) {
40554 wuffs_base__ignore_status(wuffs_zlib__decoder__initialize(&self->private_data.f_zlib,
40555 sizeof (wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
40556 if (self->private_impl.f_ignore_checksum) {
40557 wuffs_zlib__decoder__set_quirk_enabled(&self->private_data.f_zlib, 1, true);
40558 }
40559 }
40560 self->private_impl.f_zlib_is_dirty = true;
40561 self->private_impl.f_ztxt_hist_pos = 0;
40562 }
40563 label__loop__continue:;
40564 while (true) {
40565 if (a_minfo != NULL) {
40566 wuffs_base__more_information__set(a_minfo,
40567 self->private_impl.f_metadata_flavor,
40568 self->private_impl.f_metadata_fourcc,
40569 self->private_impl.f_metadata_x,
40570 self->private_impl.f_metadata_y,
40571 self->private_impl.f_metadata_z);
40572 }
40573 if (self->private_impl.f_metadata_flavor != 4) {
40574 goto label__loop__break;
40575 }
40576 if (self->private_impl.f_metadata_is_zlib_compressed) {
40577 if (self->private_impl.f_chunk_type == 1346585449) {
40578 {
40579 const uint8_t *o_0_io2_a_src = io2_a_src;
40580 wuffs_base__io_reader__limit(&io2_a_src, iop_a_src,
40581 ((uint64_t)(self->private_impl.f_chunk_length)));
40582 if (a_src) {
40583 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
40584 }
40585 v_r_mark = ((uint64_t)(iop_a_src - io0_a_src));
40586 {
40587 if (a_dst) {
40588 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
40589 }
40590 if (a_src) {
40591 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40592 }
40593 wuffs_base__status t_0 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, a_dst, a_src, wuffs_base__utility__empty_slice_u8());
40594 v_zlib_status = t_0;
40595 if (a_dst) {
40596 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
40597 }
40598 if (a_src) {
40599 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40600 }
40601 }
40602 wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)((wuffs_base__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src))) & 4294967295))));
40603 io2_a_src = o_0_io2_a_src;
40604 if (a_src) {
40605 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
40606 }
40607 }
40608 if (wuffs_base__status__is_ok(&v_zlib_status)) {
40609 self->private_impl.f_metadata_is_zlib_compressed = false;
40610 goto label__loop__break;
40611 } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) {
40612 status = v_zlib_status;
40613 if (wuffs_base__status__is_error(&status)) {
40614 goto exit;
40615 } else if (wuffs_base__status__is_suspension(&status)) {
40616 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
40617 goto exit;
40618 }
40619 goto ok;
40620 }
40621 status = v_zlib_status;
40622 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
40623 } else if (self->private_impl.f_chunk_type == 1951945833) {
40624 {
40625 const uint8_t *o_1_io2_a_src = io2_a_src;
40626 wuffs_base__io_reader__limit(&io2_a_src, iop_a_src,
40627 ((uint64_t)(self->private_impl.f_chunk_length)));
40628 if (a_src) {
40629 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
40630 }
40631 v_r_mark = ((uint64_t)(iop_a_src - io0_a_src));
40632 {
40633 if (a_dst) {
40634 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
40635 }
40636 if (a_src) {
40637 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40638 }
40639 wuffs_base__status t_1 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, a_dst, a_src, wuffs_base__utility__empty_slice_u8());
40640 v_zlib_status = t_1;
40641 if (a_dst) {
40642 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
40643 }
40644 if (a_src) {
40645 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40646 }
40647 }
40648 wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)((wuffs_base__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src))) & 4294967295))));
40649 io2_a_src = o_1_io2_a_src;
40650 if (a_src) {
40651 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
40652 }
40653 }
40654 if (wuffs_base__status__is_ok(&v_zlib_status)) {
40655 self->private_impl.f_metadata_is_zlib_compressed = false;
40656 goto label__loop__break;
40657 } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) {
40658 status = v_zlib_status;
40659 if (wuffs_base__status__is_error(&status)) {
40660 goto exit;
40661 } else if (wuffs_base__status__is_suspension(&status)) {
40662 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
40663 goto exit;
40664 }
40665 goto ok;
40666 }
40667 status = v_zlib_status;
40668 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
40669 } else if (self->private_impl.f_chunk_type == 1951945850) {
40670 if (self->private_impl.f_ztxt_ri == self->private_impl.f_ztxt_wi) {
40671 {
40672 wuffs_base__io_buffer* o_2_v_w = v_w;
40673 uint8_t *o_2_iop_v_w = iop_v_w;
40674 uint8_t *o_2_io0_v_w = io0_v_w;
40675 uint8_t *o_2_io1_v_w = io1_v_w;
40676 uint8_t *o_2_io2_v_w = io2_v_w;
40677 v_w = wuffs_base__io_writer__set(
40678 &u_w,
40679 &iop_v_w,
40680 &io0_v_w,
40681 &io1_v_w,
40682 &io2_v_w,
40683 wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024),
40684 self->private_impl.f_ztxt_hist_pos);
40685 {
40686 const uint8_t *o_3_io2_a_src = io2_a_src;
40687 wuffs_base__io_reader__limit(&io2_a_src, iop_a_src,
40688 ((uint64_t)(self->private_impl.f_chunk_length)));
40689 if (a_src) {
40690 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
40691 }
40692 v_w_mark = ((uint64_t)(iop_v_w - io0_v_w));
40693 v_r_mark = ((uint64_t)(iop_a_src - io0_a_src));
40694 {
40695 u_w.meta.wi = ((size_t)(iop_v_w - u_w.data.ptr));
40696 if (a_src) {
40697 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40698 }
40699 wuffs_base__status t_2 = wuffs_zlib__decoder__transform_io(&self->private_data.f_zlib, v_w, a_src, wuffs_base__utility__empty_slice_u8());
40700 v_zlib_status = t_2;
40701 iop_v_w = u_w.data.ptr + u_w.meta.wi;
40702 if (a_src) {
40703 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40704 }
40705 }
40706 wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_chunk_length, ((uint32_t)((wuffs_base__io__count_since(v_r_mark, ((uint64_t)(iop_a_src - io0_a_src))) & 4294967295))));
40707 v_num_written = wuffs_base__io__count_since(v_w_mark, ((uint64_t)(iop_v_w - io0_v_w)));
40708 io2_a_src = o_3_io2_a_src;
40709 if (a_src) {
40710 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
40711 }
40712 }
40713 v_w = o_2_v_w;
40714 iop_v_w = o_2_iop_v_w;
40715 io0_v_w = o_2_io0_v_w;
40716 io1_v_w = o_2_io1_v_w;
40717 io2_v_w = o_2_io2_v_w;
40718 }
40719 if (v_num_written > 1024) {
40720 status = wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_i_o);
40721 goto exit;
40722 }
40723 self->private_impl.f_ztxt_ri = 0;
40724 self->private_impl.f_ztxt_wi = ((uint32_t)(v_num_written));
40725 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_ztxt_hist_pos, v_num_written);
40726 }
40727 while (self->private_impl.f_ztxt_ri < self->private_impl.f_ztxt_wi) {
40728 v_c2 = WUFFS_PNG__LATIN_1[self->private_data.f_dst_palette[self->private_impl.f_ztxt_ri]];
40729 if (v_c2 == 0) {
40730 status = wuffs_base__make_status(wuffs_png__error__bad_text_chunk_not_latin_1);
40731 goto exit;
40732 } else if (v_c2 <= 127) {
40733 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
40734 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
40735 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
40736 v_c2 = 0;
40737 goto label__loop__continue;
40738 }
40739 self->private_impl.f_ztxt_ri += 1;
40740 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(v_c2))), iop_a_dst += 1);
40741 } else {
40742 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1) {
40743 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
40744 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
40745 v_c2 = 0;
40746 goto label__loop__continue;
40747 }
40748 self->private_impl.f_ztxt_ri += 1;
40749 (wuffs_base__poke_u16le__no_bounds_check(iop_a_dst, v_c2), iop_a_dst += 2);
40750 }
40751 }
40752 if (wuffs_base__status__is_ok(&v_zlib_status)) {
40753 self->private_impl.f_metadata_is_zlib_compressed = false;
40754 goto label__loop__break;
40755 } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) {
40756 status = v_zlib_status;
40757 if (wuffs_base__status__is_error(&status)) {
40758 goto exit;
40759 } else if (wuffs_base__status__is_suspension(&status)) {
40760 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
40761 goto exit;
40762 }
40763 goto ok;
40764 } else if (v_zlib_status.repr != wuffs_base__suspension__short_write) {
40765 status = v_zlib_status;
40766 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
40767 }
40768 } else {
40769 status = wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_chunk_type);
40770 goto exit;
40771 }
40772 } else if ((self->private_impl.f_chunk_type == 1951945833) && (self->private_impl.f_metadata_fourcc == 1263947862)) {
40773 while (true) {
40774 if (self->private_impl.f_chunk_length <= 0) {
40775 goto label__loop__break;
40776 } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
40777 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40778 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
40779 goto label__loop__continue;
40780 } else if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
40781 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
40782 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
40783 goto label__loop__continue;
40784 }
40785 self->private_impl.f_chunk_length -= 1;
40786 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
40787 iop_a_src += 1;
40788 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_c), iop_a_dst += 1);
40789 }
40790 } else {
40791 while (true) {
40792 if (self->private_impl.f_chunk_length <= 0) {
40793 if (self->private_impl.f_metadata_fourcc == 1263947851) {
40794 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40795 goto exit;
40796 }
40797 goto label__loop__break;
40798 } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
40799 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40800 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
40801 goto label__loop__continue;
40802 }
40803 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
40804 if (v_c == 0) {
40805 self->private_impl.f_chunk_length -= 1;
40806 iop_a_src += 1;
40807 goto label__loop__break;
40808 }
40809 v_c2 = WUFFS_PNG__LATIN_1[v_c];
40810 if (v_c2 == 0) {
40811 status = wuffs_base__make_status(wuffs_png__error__bad_text_chunk_not_latin_1);
40812 goto exit;
40813 } else if (v_c2 <= 127) {
40814 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
40815 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
40816 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
40817 v_c2 = 0;
40818 goto label__loop__continue;
40819 }
40820 self->private_impl.f_chunk_length -= 1;
40821 iop_a_src += 1;
40822 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(v_c2))), iop_a_dst += 1);
40823 } else {
40824 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1) {
40825 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
40826 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
40827 v_c2 = 0;
40828 goto label__loop__continue;
40829 }
40830 self->private_impl.f_chunk_length -= 1;
40831 iop_a_src += 1;
40832 (wuffs_base__poke_u16le__no_bounds_check(iop_a_dst, v_c2), iop_a_dst += 2);
40833 }
40834 }
40835 }
40836 }
40837 label__loop__break:;
40838 if (self->private_impl.f_metadata_fourcc == 1263947851) {
40839 self->private_impl.f_metadata_fourcc = 1263947862;
40840 if (self->private_impl.f_chunk_type == 1951945833) {
40841 if (self->private_impl.f_chunk_length <= 1) {
40842 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40843 goto exit;
40844 }
40845 self->private_impl.f_chunk_length -= 2;
40846 {
40847 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
40848 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40849 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40850 goto suspend;
40851 }
40852 uint8_t t_3 = *iop_a_src++;
40853 v_c = t_3;
40854 }
40855 if (v_c == 0) {
40856 self->private_impl.f_metadata_is_zlib_compressed = false;
40857 } else if (v_c == 1) {
40858 self->private_impl.f_metadata_is_zlib_compressed = true;
40859 } else {
40860 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40861 goto exit;
40862 }
40863 {
40864 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
40865 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40866 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40867 goto suspend;
40868 }
40869 uint8_t t_4 = *iop_a_src++;
40870 v_c = t_4;
40871 }
40872 if ((v_c != 0) && self->private_impl.f_metadata_is_zlib_compressed) {
40873 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method);
40874 goto exit;
40875 }
40876 self->private_impl.f_metadata_fourcc -= 2;
40877 while (self->private_impl.f_metadata_fourcc != 1263947862) {
40878 self->private_impl.f_metadata_fourcc += 1;
40879 while (true) {
40880 if (self->private_impl.f_chunk_length <= 0) {
40881 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40882 goto exit;
40883 }
40884 self->private_impl.f_chunk_length -= 1;
40885 {
40886 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
40887 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40888 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40889 goto suspend;
40890 }
40891 uint8_t t_5 = *iop_a_src++;
40892 v_c = t_5;
40893 }
40894 if (v_c == 0) {
40895 goto label__0__break;
40896 }
40897 }
40898 label__0__break:;
40899 }
40900 } else if (self->private_impl.f_chunk_type == 1951945850) {
40901 if (self->private_impl.f_chunk_length <= 0) {
40902 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40903 goto exit;
40904 }
40905 self->private_impl.f_chunk_length -= 1;
40906 {
40907 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
40908 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40909 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40910 goto suspend;
40911 }
40912 uint8_t t_6 = *iop_a_src++;
40913 v_c = t_6;
40914 }
40915 if (v_c != 0) {
40916 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method);
40917 goto exit;
40918 }
40919 self->private_impl.f_metadata_is_zlib_compressed = true;
40920 }
40921 } else {
40922 if (self->private_impl.f_chunk_length != 0) {
40923 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40924 goto exit;
40925 }
40926 self->private_data.s_tell_me_more[0].scratch = 4;
40927 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
40928 if (self->private_data.s_tell_me_more[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
40929 self->private_data.s_tell_me_more[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
40930 iop_a_src = io2_a_src;
40931 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40932 goto suspend;
40933 }
40934 iop_a_src += self->private_data.s_tell_me_more[0].scratch;
40935 self->private_impl.f_metadata_flavor = 0;
40936 self->private_impl.f_metadata_fourcc = 0;
40937 self->private_impl.f_metadata_x = 0;
40938 self->private_impl.f_metadata_y = 0;
40939 self->private_impl.f_metadata_z = 0;
40940 }
40941 self->private_impl.f_call_sequence = 2;
40942 status = wuffs_base__make_status(NULL);
40943 goto ok;
40944
40945 ok:
40946 self->private_impl.p_tell_me_more[0] = 0;
40947 goto exit;
40948 }
40949
40950 goto suspend;
40951 suspend:
40952 self->private_impl.p_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
40953 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0;
40954 self->private_data.s_tell_me_more[0].v_zlib_status = v_zlib_status;
40955
Nigel Taoe360a532021-04-05 22:47:03 +100040956 goto exit;
40957 exit:
Nigel Taobf9dab32021-11-18 19:19:55 +110040958 if (a_dst) {
40959 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
40960 }
40961 if (a_src) {
40962 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40963 }
40964
Nigel Taoe360a532021-04-05 22:47:03 +100040965 if (wuffs_base__status__is_error(&status)) {
40966 self->private_impl.magic = WUFFS_BASE__DISABLED;
40967 }
40968 return status;
40969}
40970
40971// -------- func png.decoder.workbuf_len
40972
40973WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
40974wuffs_png__decoder__workbuf_len(
40975 const wuffs_png__decoder* self) {
40976 if (!self) {
40977 return wuffs_base__utility__empty_range_ii_u64();
40978 }
40979 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
40980 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
40981 return wuffs_base__utility__empty_range_ii_u64();
40982 }
40983
40984 return wuffs_base__utility__make_range_ii_u64(self->private_impl.f_overall_workbuf_length, self->private_impl.f_overall_workbuf_length);
40985}
40986
40987// -------- func png.decoder.filter_and_swizzle
40988
40989static wuffs_base__status
40990wuffs_png__decoder__filter_and_swizzle(
40991 wuffs_png__decoder* self,
40992 wuffs_base__pixel_buffer* a_dst,
40993 wuffs_base__slice_u8 a_workbuf) {
40994 return (*self->private_impl.choosy_filter_and_swizzle)(self, a_dst, a_workbuf);
40995}
40996
40997static wuffs_base__status
40998wuffs_png__decoder__filter_and_swizzle__choosy_default(
40999 wuffs_png__decoder* self,
41000 wuffs_base__pixel_buffer* a_dst,
41001 wuffs_base__slice_u8 a_workbuf) {
41002 wuffs_base__pixel_format v_dst_pixfmt = {0};
41003 uint32_t v_dst_bits_per_pixel = 0;
41004 uint64_t v_dst_bytes_per_pixel = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110041005 uint64_t v_dst_bytes_per_row0 = 0;
41006 uint64_t v_dst_bytes_per_row1 = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100041007 wuffs_base__slice_u8 v_dst_palette = {0};
41008 wuffs_base__table_u8 v_tab = {0};
41009 uint32_t v_y = 0;
41010 wuffs_base__slice_u8 v_dst = {0};
41011 uint8_t v_filter = 0;
41012 wuffs_base__slice_u8 v_curr_row = {0};
41013 wuffs_base__slice_u8 v_prev_row = {0};
41014
41015 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
41016 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
41017 if ((v_dst_bits_per_pixel & 7) != 0) {
41018 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
41019 }
41020 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
Nigel Taobf9dab32021-11-18 19:19:55 +110041021 v_dst_bytes_per_row0 = (((uint64_t)(self->private_impl.f_frame_rect_x0)) * v_dst_bytes_per_pixel);
41022 v_dst_bytes_per_row1 = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * v_dst_bytes_per_pixel);
Nigel Taoe360a532021-04-05 22:47:03 +100041023 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024));
41024 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
Nigel Taobf9dab32021-11-18 19:19:55 +110041025 if (v_dst_bytes_per_row1 < ((uint64_t)(v_tab.width))) {
41026 v_tab = wuffs_base__table_u8__subtable_ij(v_tab,
41027 0,
41028 0,
41029 v_dst_bytes_per_row1,
41030 ((uint64_t)(v_tab.height)));
41031 }
41032 if (v_dst_bytes_per_row0 < ((uint64_t)(v_tab.width))) {
41033 v_tab = wuffs_base__table_u8__subtable_ij(v_tab,
41034 v_dst_bytes_per_row0,
41035 0,
41036 ((uint64_t)(v_tab.width)),
41037 ((uint64_t)(v_tab.height)));
41038 } else {
41039 v_tab = wuffs_base__table_u8__subtable_ij(v_tab,
41040 0,
41041 0,
41042 0,
41043 0);
41044 }
41045 v_y = self->private_impl.f_frame_rect_y0;
41046 while (v_y < self->private_impl.f_frame_rect_y1) {
41047 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_y);
Nigel Taoe360a532021-04-05 22:47:03 +100041048 if (1 > ((uint64_t)(a_workbuf.len))) {
41049 return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length);
41050 }
41051 v_filter = a_workbuf.ptr[0];
41052 a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, 1);
41053 if (self->private_impl.f_pass_bytes_per_row > ((uint64_t)(a_workbuf.len))) {
41054 return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length);
41055 }
41056 v_curr_row = wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_pass_bytes_per_row);
41057 a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, self->private_impl.f_pass_bytes_per_row);
41058 if (v_filter == 0) {
41059 } else if (v_filter == 1) {
41060 wuffs_png__decoder__filter_1(self, v_curr_row);
41061 } else if (v_filter == 2) {
41062 wuffs_png__decoder__filter_2(self, v_curr_row, v_prev_row);
41063 } else if (v_filter == 3) {
41064 wuffs_png__decoder__filter_3(self, v_curr_row, v_prev_row);
41065 } else if (v_filter == 4) {
41066 wuffs_png__decoder__filter_4(self, v_curr_row, v_prev_row);
41067 } else {
41068 return wuffs_base__make_status(wuffs_png__error__bad_filter);
41069 }
41070 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, v_curr_row);
41071 v_prev_row = v_curr_row;
41072 v_y += 1;
41073 }
41074 return wuffs_base__make_status(NULL);
41075}
41076
41077// -------- func png.decoder.filter_and_swizzle_tricky
41078
41079static wuffs_base__status
41080wuffs_png__decoder__filter_and_swizzle_tricky(
41081 wuffs_png__decoder* self,
41082 wuffs_base__pixel_buffer* a_dst,
41083 wuffs_base__slice_u8 a_workbuf) {
41084 wuffs_base__pixel_format v_dst_pixfmt = {0};
41085 uint32_t v_dst_bits_per_pixel = 0;
41086 uint64_t v_dst_bytes_per_pixel = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110041087 uint64_t v_dst_bytes_per_row1 = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100041088 wuffs_base__slice_u8 v_dst_palette = {0};
41089 wuffs_base__table_u8 v_tab = {0};
41090 uint64_t v_src_bytes_per_pixel = 0;
41091 uint32_t v_x = 0;
41092 uint32_t v_y = 0;
41093 uint64_t v_i = 0;
41094 wuffs_base__slice_u8 v_dst = {0};
41095 uint8_t v_filter = 0;
41096 wuffs_base__slice_u8 v_s = {0};
41097 wuffs_base__slice_u8 v_curr_row = {0};
41098 wuffs_base__slice_u8 v_prev_row = {0};
41099 uint8_t v_bits_unpacked[8] = {0};
41100 uint8_t v_bits_packed = 0;
41101 uint8_t v_packs_remaining = 0;
41102 uint8_t v_multiplier = 0;
41103 uint8_t v_shift = 0;
41104
41105 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
41106 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
41107 if ((v_dst_bits_per_pixel & 7) != 0) {
41108 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
41109 }
41110 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
Nigel Taobf9dab32021-11-18 19:19:55 +110041111 v_dst_bytes_per_row1 = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * v_dst_bytes_per_pixel);
Nigel Taoe360a532021-04-05 22:47:03 +100041112 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024));
41113 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
41114 v_src_bytes_per_pixel = 1;
41115 if (self->private_impl.f_depth >= 8) {
41116 v_src_bytes_per_pixel = (((uint64_t)(WUFFS_PNG__NUM_CHANNELS[self->private_impl.f_color_type])) * ((uint64_t)((self->private_impl.f_depth >> 3))));
41117 }
Nigel Taobf9dab32021-11-18 19:19:55 +110041118 if (self->private_impl.f_chunk_type_array[0] == 73) {
41119 v_y = ((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][5]));
41120 } else {
41121 v_y = self->private_impl.f_frame_rect_y0;
41122 }
41123 while (v_y < self->private_impl.f_frame_rect_y1) {
41124 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_y);
41125 if (v_dst_bytes_per_row1 < ((uint64_t)(v_dst.len))) {
41126 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row1);
Nigel Taoe360a532021-04-05 22:47:03 +100041127 }
41128 if (1 > ((uint64_t)(a_workbuf.len))) {
41129 return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length);
41130 }
41131 v_filter = a_workbuf.ptr[0];
41132 a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, 1);
41133 if (self->private_impl.f_pass_bytes_per_row > ((uint64_t)(a_workbuf.len))) {
41134 return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length);
41135 }
41136 v_curr_row = wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_pass_bytes_per_row);
41137 a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, self->private_impl.f_pass_bytes_per_row);
41138 if (v_filter == 0) {
41139 } else if (v_filter == 1) {
41140 wuffs_png__decoder__filter_1(self, v_curr_row);
41141 } else if (v_filter == 2) {
41142 wuffs_png__decoder__filter_2(self, v_curr_row, v_prev_row);
41143 } else if (v_filter == 3) {
41144 wuffs_png__decoder__filter_3(self, v_curr_row, v_prev_row);
41145 } else if (v_filter == 4) {
41146 wuffs_png__decoder__filter_4(self, v_curr_row, v_prev_row);
41147 } else {
41148 return wuffs_base__make_status(wuffs_png__error__bad_filter);
41149 }
41150 v_s = v_curr_row;
Nigel Taobf9dab32021-11-18 19:19:55 +110041151 if (self->private_impl.f_chunk_type_array[0] == 73) {
41152 v_x = ((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][2]));
41153 } else {
41154 v_x = self->private_impl.f_frame_rect_x0;
41155 }
Nigel Taoe360a532021-04-05 22:47:03 +100041156 if (self->private_impl.f_depth == 8) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041157 while (v_x < self->private_impl.f_frame_rect_x1) {
Nigel Taoe360a532021-04-05 22:47:03 +100041158 v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel);
41159 if (v_i <= ((uint64_t)(v_dst.len))) {
41160 if (self->private_impl.f_color_type == 4) {
41161 if (2 <= ((uint64_t)(v_s.len))) {
41162 v_bits_unpacked[0] = v_s.ptr[0];
41163 v_bits_unpacked[1] = v_s.ptr[0];
41164 v_bits_unpacked[2] = v_s.ptr[0];
41165 v_bits_unpacked[3] = v_s.ptr[1];
41166 v_s = wuffs_base__slice_u8__subslice_i(v_s, 2);
41167 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4));
41168 }
Nigel Taobf9dab32021-11-18 19:19:55 +110041169 } else if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) != 0) {
41170 if (self->private_impl.f_color_type == 0) {
41171 if (1 <= ((uint64_t)(v_s.len))) {
41172 v_bits_unpacked[0] = v_s.ptr[0];
41173 v_bits_unpacked[1] = v_s.ptr[0];
41174 v_bits_unpacked[2] = v_s.ptr[0];
41175 v_bits_unpacked[3] = 255;
41176 v_s = wuffs_base__slice_u8__subslice_i(v_s, 1);
41177 if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) == ((((uint32_t)(v_bits_unpacked[0])) << 0) |
41178 (((uint32_t)(v_bits_unpacked[1])) << 8) |
41179 (((uint32_t)(v_bits_unpacked[2])) << 16) |
41180 (((uint32_t)(v_bits_unpacked[3])) << 24))) {
41181 v_bits_unpacked[0] = 0;
41182 v_bits_unpacked[1] = 0;
41183 v_bits_unpacked[2] = 0;
41184 v_bits_unpacked[3] = 0;
41185 }
41186 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4));
41187 }
41188 } else {
41189 if (3 <= ((uint64_t)(v_s.len))) {
41190 v_bits_unpacked[0] = v_s.ptr[2];
41191 v_bits_unpacked[1] = v_s.ptr[1];
41192 v_bits_unpacked[2] = v_s.ptr[0];
41193 v_bits_unpacked[3] = 255;
41194 v_s = wuffs_base__slice_u8__subslice_i(v_s, 3);
41195 if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) == ((((uint32_t)(v_bits_unpacked[0])) << 0) |
41196 (((uint32_t)(v_bits_unpacked[1])) << 8) |
41197 (((uint32_t)(v_bits_unpacked[2])) << 16) |
41198 (((uint32_t)(v_bits_unpacked[3])) << 24))) {
41199 v_bits_unpacked[0] = 0;
41200 v_bits_unpacked[1] = 0;
41201 v_bits_unpacked[2] = 0;
41202 v_bits_unpacked[3] = 0;
41203 }
41204 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4));
41205 }
41206 }
Nigel Taoe360a532021-04-05 22:47:03 +100041207 } else if (v_src_bytes_per_pixel <= ((uint64_t)(v_s.len))) {
41208 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__slice_u8__subslice_j(v_s, v_src_bytes_per_pixel));
41209 v_s = wuffs_base__slice_u8__subslice_i(v_s, v_src_bytes_per_pixel);
41210 }
41211 }
41212 v_x += (((uint32_t)(1)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0]);
41213 }
41214 } else if (self->private_impl.f_depth < 8) {
41215 v_multiplier = 1;
41216 if (self->private_impl.f_color_type == 0) {
41217 v_multiplier = WUFFS_PNG__LOW_BIT_DEPTH_MULTIPLIERS[self->private_impl.f_depth];
41218 }
41219 v_shift = ((8 - self->private_impl.f_depth) & 7);
41220 v_packs_remaining = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110041221 while (v_x < self->private_impl.f_frame_rect_x1) {
Nigel Taoe360a532021-04-05 22:47:03 +100041222 v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel);
41223 if (v_i <= ((uint64_t)(v_dst.len))) {
41224 if ((v_packs_remaining == 0) && (1 <= ((uint64_t)(v_s.len)))) {
41225 v_packs_remaining = WUFFS_PNG__LOW_BIT_DEPTH_NUM_PACKS[self->private_impl.f_depth];
41226 v_bits_packed = v_s.ptr[0];
41227 v_s = wuffs_base__slice_u8__subslice_i(v_s, 1);
41228 }
41229 v_bits_unpacked[0] = ((uint8_t)((v_bits_packed >> v_shift) * v_multiplier));
41230 v_bits_packed = ((uint8_t)(v_bits_packed << self->private_impl.f_depth));
41231 v_packs_remaining = ((uint8_t)(v_packs_remaining - 1));
Nigel Taobf9dab32021-11-18 19:19:55 +110041232 if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) != 0) {
41233 v_bits_unpacked[1] = v_bits_unpacked[0];
41234 v_bits_unpacked[2] = v_bits_unpacked[0];
41235 v_bits_unpacked[3] = 255;
41236 if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) == ((((uint32_t)(v_bits_unpacked[0])) << 0) |
41237 (((uint32_t)(v_bits_unpacked[1])) << 8) |
41238 (((uint32_t)(v_bits_unpacked[2])) << 16) |
41239 (((uint32_t)(v_bits_unpacked[3])) << 24))) {
41240 v_bits_unpacked[0] = 0;
41241 v_bits_unpacked[1] = 0;
41242 v_bits_unpacked[2] = 0;
41243 v_bits_unpacked[3] = 0;
41244 }
41245 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 4));
41246 } else {
41247 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 1));
41248 }
Nigel Taoe360a532021-04-05 22:47:03 +100041249 }
41250 v_x += (((uint32_t)(1)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0]);
41251 }
41252 } else {
Nigel Taobf9dab32021-11-18 19:19:55 +110041253 while (v_x < self->private_impl.f_frame_rect_x1) {
Nigel Taoe360a532021-04-05 22:47:03 +100041254 v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel);
41255 if (v_i <= ((uint64_t)(v_dst.len))) {
41256 if (self->private_impl.f_color_type == 0) {
41257 if (2 <= ((uint64_t)(v_s.len))) {
41258 v_bits_unpacked[0] = v_s.ptr[1];
41259 v_bits_unpacked[1] = v_s.ptr[0];
41260 v_bits_unpacked[2] = v_s.ptr[1];
41261 v_bits_unpacked[3] = v_s.ptr[0];
41262 v_bits_unpacked[4] = v_s.ptr[1];
41263 v_bits_unpacked[5] = v_s.ptr[0];
Nigel Taobf9dab32021-11-18 19:19:55 +110041264 v_bits_unpacked[6] = 255;
41265 v_bits_unpacked[7] = 255;
Nigel Taoe360a532021-04-05 22:47:03 +100041266 v_s = wuffs_base__slice_u8__subslice_i(v_s, 2);
Nigel Taobf9dab32021-11-18 19:19:55 +110041267 if (self->private_impl.f_remap_transparency == ((((uint64_t)(v_bits_unpacked[0])) << 0) |
41268 (((uint64_t)(v_bits_unpacked[1])) << 8) |
41269 (((uint64_t)(v_bits_unpacked[2])) << 16) |
41270 (((uint64_t)(v_bits_unpacked[3])) << 24) |
41271 (((uint64_t)(v_bits_unpacked[4])) << 32) |
41272 (((uint64_t)(v_bits_unpacked[5])) << 40) |
41273 (((uint64_t)(v_bits_unpacked[6])) << 48) |
41274 (((uint64_t)(v_bits_unpacked[7])) << 56))) {
41275 v_bits_unpacked[0] = 0;
41276 v_bits_unpacked[1] = 0;
41277 v_bits_unpacked[2] = 0;
41278 v_bits_unpacked[3] = 0;
41279 v_bits_unpacked[4] = 0;
41280 v_bits_unpacked[5] = 0;
41281 v_bits_unpacked[6] = 0;
41282 v_bits_unpacked[7] = 0;
41283 }
Nigel Taoe360a532021-04-05 22:47:03 +100041284 }
41285 } else if (self->private_impl.f_color_type == 2) {
41286 if (6 <= ((uint64_t)(v_s.len))) {
41287 v_bits_unpacked[0] = v_s.ptr[5];
41288 v_bits_unpacked[1] = v_s.ptr[4];
41289 v_bits_unpacked[2] = v_s.ptr[3];
41290 v_bits_unpacked[3] = v_s.ptr[2];
41291 v_bits_unpacked[4] = v_s.ptr[1];
41292 v_bits_unpacked[5] = v_s.ptr[0];
Nigel Taobf9dab32021-11-18 19:19:55 +110041293 v_bits_unpacked[6] = 255;
41294 v_bits_unpacked[7] = 255;
Nigel Taoe360a532021-04-05 22:47:03 +100041295 v_s = wuffs_base__slice_u8__subslice_i(v_s, 6);
Nigel Taobf9dab32021-11-18 19:19:55 +110041296 if (self->private_impl.f_remap_transparency == ((((uint64_t)(v_bits_unpacked[0])) << 0) |
41297 (((uint64_t)(v_bits_unpacked[1])) << 8) |
41298 (((uint64_t)(v_bits_unpacked[2])) << 16) |
41299 (((uint64_t)(v_bits_unpacked[3])) << 24) |
41300 (((uint64_t)(v_bits_unpacked[4])) << 32) |
41301 (((uint64_t)(v_bits_unpacked[5])) << 40) |
41302 (((uint64_t)(v_bits_unpacked[6])) << 48) |
41303 (((uint64_t)(v_bits_unpacked[7])) << 56))) {
41304 v_bits_unpacked[0] = 0;
41305 v_bits_unpacked[1] = 0;
41306 v_bits_unpacked[2] = 0;
41307 v_bits_unpacked[3] = 0;
41308 v_bits_unpacked[4] = 0;
41309 v_bits_unpacked[5] = 0;
41310 v_bits_unpacked[6] = 0;
41311 v_bits_unpacked[7] = 0;
41312 }
Nigel Taoe360a532021-04-05 22:47:03 +100041313 }
41314 } else if (self->private_impl.f_color_type == 4) {
41315 if (4 <= ((uint64_t)(v_s.len))) {
41316 v_bits_unpacked[0] = v_s.ptr[1];
41317 v_bits_unpacked[1] = v_s.ptr[0];
41318 v_bits_unpacked[2] = v_s.ptr[1];
41319 v_bits_unpacked[3] = v_s.ptr[0];
41320 v_bits_unpacked[4] = v_s.ptr[1];
41321 v_bits_unpacked[5] = v_s.ptr[0];
41322 v_bits_unpacked[6] = v_s.ptr[3];
41323 v_bits_unpacked[7] = v_s.ptr[2];
41324 v_s = wuffs_base__slice_u8__subslice_i(v_s, 4);
41325 }
41326 } else {
41327 if (8 <= ((uint64_t)(v_s.len))) {
41328 v_bits_unpacked[0] = v_s.ptr[5];
41329 v_bits_unpacked[1] = v_s.ptr[4];
41330 v_bits_unpacked[2] = v_s.ptr[3];
41331 v_bits_unpacked[3] = v_s.ptr[2];
41332 v_bits_unpacked[4] = v_s.ptr[1];
41333 v_bits_unpacked[5] = v_s.ptr[0];
41334 v_bits_unpacked[6] = v_s.ptr[7];
41335 v_bits_unpacked[7] = v_s.ptr[6];
41336 v_s = wuffs_base__slice_u8__subslice_i(v_s, 8);
41337 }
41338 }
41339 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(v_bits_unpacked, 8));
41340 }
41341 v_x += (((uint32_t)(1)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0]);
41342 }
41343 }
41344 v_prev_row = v_curr_row;
41345 v_y += (((uint32_t)(1)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][3]);
41346 }
41347 return wuffs_base__make_status(NULL);
41348}
41349
41350#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG)
41351
41352#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP)
41353
41354// ---------------- Status Codes Implementations
41355
41356const char wuffs_wbmp__error__bad_header[] = "#wbmp: bad header";
41357
41358// ---------------- Private Consts
41359
41360// ---------------- Private Initializer Prototypes
41361
41362// ---------------- Private Function Prototypes
41363
41364// ---------------- VTables
41365
41366const wuffs_base__image_decoder__func_ptrs
41367wuffs_wbmp__decoder__func_ptrs_for__wuffs_base__image_decoder = {
41368 (wuffs_base__status(*)(void*,
41369 wuffs_base__pixel_buffer*,
41370 wuffs_base__io_buffer*,
41371 wuffs_base__pixel_blend,
41372 wuffs_base__slice_u8,
41373 wuffs_base__decode_frame_options*))(&wuffs_wbmp__decoder__decode_frame),
41374 (wuffs_base__status(*)(void*,
41375 wuffs_base__frame_config*,
41376 wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__decode_frame_config),
41377 (wuffs_base__status(*)(void*,
41378 wuffs_base__image_config*,
41379 wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__decode_image_config),
41380 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_wbmp__decoder__frame_dirty_rect),
41381 (uint32_t(*)(const void*))(&wuffs_wbmp__decoder__num_animation_loops),
41382 (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__num_decoded_frame_configs),
41383 (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__num_decoded_frames),
41384 (wuffs_base__status(*)(void*,
41385 uint64_t,
41386 uint64_t))(&wuffs_wbmp__decoder__restart_frame),
41387 (wuffs_base__empty_struct(*)(void*,
41388 uint32_t,
41389 bool))(&wuffs_wbmp__decoder__set_quirk_enabled),
41390 (wuffs_base__empty_struct(*)(void*,
41391 uint32_t,
41392 bool))(&wuffs_wbmp__decoder__set_report_metadata),
41393 (wuffs_base__status(*)(void*,
41394 wuffs_base__io_buffer*,
41395 wuffs_base__more_information*,
41396 wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__tell_me_more),
41397 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_wbmp__decoder__workbuf_len),
41398};
41399
41400// ---------------- Initializer Implementations
41401
41402wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
41403wuffs_wbmp__decoder__initialize(
41404 wuffs_wbmp__decoder* self,
41405 size_t sizeof_star_self,
41406 uint64_t wuffs_version,
41407 uint32_t options){
41408 if (!self) {
41409 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
41410 }
41411 if (sizeof(*self) != sizeof_star_self) {
41412 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
41413 }
41414 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
41415 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
41416 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
41417 }
41418
41419 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
41420 // The whole point of this if-check is to detect an uninitialized *self.
41421 // We disable the warning on GCC. Clang-5.0 does not have this warning.
41422#if !defined(__clang__) && defined(__GNUC__)
41423#pragma GCC diagnostic push
41424#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
41425#endif
41426 if (self->private_impl.magic != 0) {
41427 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
41428 }
41429#if !defined(__clang__) && defined(__GNUC__)
41430#pragma GCC diagnostic pop
41431#endif
41432 } else {
41433 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
41434 memset(self, 0, sizeof(*self));
41435 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
41436 } else {
41437 memset(&(self->private_impl), 0, sizeof(self->private_impl));
41438 }
41439 }
41440
41441 self->private_impl.magic = WUFFS_BASE__MAGIC;
41442 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
41443 wuffs_base__image_decoder__vtable_name;
41444 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
41445 (const void*)(&wuffs_wbmp__decoder__func_ptrs_for__wuffs_base__image_decoder);
41446 return wuffs_base__make_status(NULL);
41447}
41448
41449wuffs_wbmp__decoder*
41450wuffs_wbmp__decoder__alloc() {
41451 wuffs_wbmp__decoder* x =
41452 (wuffs_wbmp__decoder*)(calloc(sizeof(wuffs_wbmp__decoder), 1));
41453 if (!x) {
41454 return NULL;
41455 }
41456 if (wuffs_wbmp__decoder__initialize(
41457 x, sizeof(wuffs_wbmp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
41458 free(x);
41459 return NULL;
41460 }
41461 return x;
41462}
41463
41464size_t
41465sizeof__wuffs_wbmp__decoder() {
41466 return sizeof(wuffs_wbmp__decoder);
41467}
41468
41469// ---------------- Function Implementations
41470
41471// -------- func wbmp.decoder.set_quirk_enabled
41472
41473WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
41474wuffs_wbmp__decoder__set_quirk_enabled(
41475 wuffs_wbmp__decoder* self,
41476 uint32_t a_quirk,
41477 bool a_enabled) {
41478 return wuffs_base__make_empty_struct();
41479}
41480
41481// -------- func wbmp.decoder.decode_image_config
41482
41483WUFFS_BASE__MAYBE_STATIC wuffs_base__status
41484wuffs_wbmp__decoder__decode_image_config(
41485 wuffs_wbmp__decoder* self,
41486 wuffs_base__image_config* a_dst,
41487 wuffs_base__io_buffer* a_src) {
41488 if (!self) {
41489 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
41490 }
41491 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
41492 return wuffs_base__make_status(
41493 (self->private_impl.magic == WUFFS_BASE__DISABLED)
41494 ? wuffs_base__error__disabled_by_previous_error
41495 : wuffs_base__error__initialize_not_called);
41496 }
41497 if (!a_src) {
41498 self->private_impl.magic = WUFFS_BASE__DISABLED;
41499 return wuffs_base__make_status(wuffs_base__error__bad_argument);
41500 }
41501 if ((self->private_impl.active_coroutine != 0) &&
41502 (self->private_impl.active_coroutine != 1)) {
41503 self->private_impl.magic = WUFFS_BASE__DISABLED;
41504 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
41505 }
41506 self->private_impl.active_coroutine = 0;
41507 wuffs_base__status status = wuffs_base__make_status(NULL);
41508
41509 uint8_t v_c = 0;
41510 uint32_t v_i = 0;
41511 uint32_t v_x32 = 0;
41512 uint64_t v_x64 = 0;
41513
41514 const uint8_t* iop_a_src = NULL;
41515 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41516 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41517 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41518 if (a_src) {
41519 io0_a_src = a_src->data.ptr;
41520 io1_a_src = io0_a_src + a_src->meta.ri;
41521 iop_a_src = io1_a_src;
41522 io2_a_src = io0_a_src + a_src->meta.wi;
41523 }
41524
41525 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
41526 if (coro_susp_point) {
41527 v_i = self->private_data.s_decode_image_config[0].v_i;
41528 v_x32 = self->private_data.s_decode_image_config[0].v_x32;
41529 }
41530 switch (coro_susp_point) {
41531 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41532
41533 if (self->private_impl.f_call_sequence != 0) {
41534 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
41535 goto exit;
41536 }
41537 v_i = 0;
41538 while (v_i < 2) {
41539 {
41540 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41541 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41542 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41543 goto suspend;
41544 }
41545 uint8_t t_0 = *iop_a_src++;
41546 v_c = t_0;
41547 }
41548 if (v_c != 0) {
41549 status = wuffs_base__make_status(wuffs_wbmp__error__bad_header);
41550 goto exit;
41551 }
41552 v_i += 1;
41553 }
41554 v_i = 0;
41555 while (v_i < 2) {
41556 v_x32 = 0;
41557 while (true) {
41558 {
41559 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
41560 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41561 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41562 goto suspend;
41563 }
41564 uint8_t t_1 = *iop_a_src++;
41565 v_c = t_1;
41566 }
41567 v_x32 |= ((uint32_t)((v_c & 127)));
41568 if ((v_c >> 7) == 0) {
41569 goto label__0__break;
41570 }
41571 v_x64 = (((uint64_t)(v_x32)) << 7);
41572 if (v_x64 > 4294967295) {
41573 status = wuffs_base__make_status(wuffs_wbmp__error__bad_header);
41574 goto exit;
41575 }
41576 v_x32 = ((uint32_t)(v_x64));
41577 }
41578 label__0__break:;
41579 if (v_i == 0) {
41580 self->private_impl.f_width = v_x32;
41581 } else {
41582 self->private_impl.f_height = v_x32;
41583 }
41584 v_i += 1;
41585 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100041586 self->private_impl.f_frame_config_io_position = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)));
Nigel Taoe360a532021-04-05 22:47:03 +100041587 if (a_dst != NULL) {
41588 wuffs_base__image_config__set(
41589 a_dst,
41590 2198077448,
41591 0,
41592 self->private_impl.f_width,
41593 self->private_impl.f_height,
41594 self->private_impl.f_frame_config_io_position,
41595 true);
41596 }
41597 self->private_impl.f_call_sequence = 3;
41598
41599 goto ok;
41600 ok:
41601 self->private_impl.p_decode_image_config[0] = 0;
41602 goto exit;
41603 }
41604
41605 goto suspend;
41606 suspend:
41607 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
41608 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
41609 self->private_data.s_decode_image_config[0].v_i = v_i;
41610 self->private_data.s_decode_image_config[0].v_x32 = v_x32;
41611
41612 goto exit;
41613 exit:
41614 if (a_src) {
41615 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41616 }
41617
41618 if (wuffs_base__status__is_error(&status)) {
41619 self->private_impl.magic = WUFFS_BASE__DISABLED;
41620 }
41621 return status;
41622}
41623
41624// -------- func wbmp.decoder.decode_frame_config
41625
41626WUFFS_BASE__MAYBE_STATIC wuffs_base__status
41627wuffs_wbmp__decoder__decode_frame_config(
41628 wuffs_wbmp__decoder* self,
41629 wuffs_base__frame_config* a_dst,
41630 wuffs_base__io_buffer* a_src) {
41631 if (!self) {
41632 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
41633 }
41634 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
41635 return wuffs_base__make_status(
41636 (self->private_impl.magic == WUFFS_BASE__DISABLED)
41637 ? wuffs_base__error__disabled_by_previous_error
41638 : wuffs_base__error__initialize_not_called);
41639 }
41640 if (!a_src) {
41641 self->private_impl.magic = WUFFS_BASE__DISABLED;
41642 return wuffs_base__make_status(wuffs_base__error__bad_argument);
41643 }
41644 if ((self->private_impl.active_coroutine != 0) &&
41645 (self->private_impl.active_coroutine != 2)) {
41646 self->private_impl.magic = WUFFS_BASE__DISABLED;
41647 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
41648 }
41649 self->private_impl.active_coroutine = 0;
41650 wuffs_base__status status = wuffs_base__make_status(NULL);
41651
41652 const uint8_t* iop_a_src = NULL;
41653 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41654 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41655 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41656 if (a_src) {
41657 io0_a_src = a_src->data.ptr;
41658 io1_a_src = io0_a_src + a_src->meta.ri;
41659 iop_a_src = io1_a_src;
41660 io2_a_src = io0_a_src + a_src->meta.wi;
41661 }
41662
41663 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
41664 switch (coro_susp_point) {
41665 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41666
41667 if (self->private_impl.f_call_sequence < 3) {
41668 if (a_src) {
41669 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41670 }
41671 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41672 status = wuffs_wbmp__decoder__decode_image_config(self, NULL, a_src);
41673 if (a_src) {
41674 iop_a_src = a_src->data.ptr + a_src->meta.ri;
41675 }
41676 if (status.repr) {
41677 goto suspend;
41678 }
41679 } else if (self->private_impl.f_call_sequence == 3) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100041680 if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)))) {
Nigel Taoe360a532021-04-05 22:47:03 +100041681 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
41682 goto exit;
41683 }
41684 } else if (self->private_impl.f_call_sequence == 4) {
41685 self->private_impl.f_call_sequence = 255;
41686 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
41687 goto ok;
41688 } else {
41689 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
41690 goto ok;
41691 }
41692 if (a_dst != NULL) {
41693 wuffs_base__frame_config__set(
41694 a_dst,
41695 wuffs_base__utility__make_rect_ie_u32(
41696 0,
41697 0,
41698 self->private_impl.f_width,
41699 self->private_impl.f_height),
41700 ((wuffs_base__flicks)(0)),
41701 0,
41702 self->private_impl.f_frame_config_io_position,
41703 0,
41704 true,
41705 false,
41706 4278190080);
41707 }
41708 self->private_impl.f_call_sequence = 4;
41709
Nigel Taoe360a532021-04-05 22:47:03 +100041710 ok:
41711 self->private_impl.p_decode_frame_config[0] = 0;
41712 goto exit;
41713 }
41714
41715 goto suspend;
41716 suspend:
41717 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
41718 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
41719
41720 goto exit;
41721 exit:
41722 if (a_src) {
41723 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41724 }
41725
41726 if (wuffs_base__status__is_error(&status)) {
41727 self->private_impl.magic = WUFFS_BASE__DISABLED;
41728 }
41729 return status;
41730}
41731
41732// -------- func wbmp.decoder.decode_frame
41733
41734WUFFS_BASE__MAYBE_STATIC wuffs_base__status
41735wuffs_wbmp__decoder__decode_frame(
41736 wuffs_wbmp__decoder* self,
41737 wuffs_base__pixel_buffer* a_dst,
41738 wuffs_base__io_buffer* a_src,
41739 wuffs_base__pixel_blend a_blend,
41740 wuffs_base__slice_u8 a_workbuf,
41741 wuffs_base__decode_frame_options* a_opts) {
41742 if (!self) {
41743 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
41744 }
41745 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
41746 return wuffs_base__make_status(
41747 (self->private_impl.magic == WUFFS_BASE__DISABLED)
41748 ? wuffs_base__error__disabled_by_previous_error
41749 : wuffs_base__error__initialize_not_called);
41750 }
41751 if (!a_dst || !a_src) {
41752 self->private_impl.magic = WUFFS_BASE__DISABLED;
41753 return wuffs_base__make_status(wuffs_base__error__bad_argument);
41754 }
41755 if ((self->private_impl.active_coroutine != 0) &&
41756 (self->private_impl.active_coroutine != 3)) {
41757 self->private_impl.magic = WUFFS_BASE__DISABLED;
41758 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
41759 }
41760 self->private_impl.active_coroutine = 0;
41761 wuffs_base__status status = wuffs_base__make_status(NULL);
41762
41763 wuffs_base__status v_status = wuffs_base__make_status(NULL);
41764 wuffs_base__pixel_format v_dst_pixfmt = {0};
41765 uint32_t v_dst_bits_per_pixel = 0;
41766 uint64_t v_dst_bytes_per_pixel = 0;
41767 uint64_t v_dst_x_in_bytes = 0;
41768 uint32_t v_dst_x = 0;
41769 uint32_t v_dst_y = 0;
41770 wuffs_base__table_u8 v_tab = {0};
41771 wuffs_base__slice_u8 v_dst = {0};
41772 uint8_t v_src[1] = {0};
41773 uint8_t v_c = 0;
41774
41775 const uint8_t* iop_a_src = NULL;
41776 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41777 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41778 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41779 if (a_src) {
41780 io0_a_src = a_src->data.ptr;
41781 io1_a_src = io0_a_src + a_src->meta.ri;
41782 iop_a_src = io1_a_src;
41783 io2_a_src = io0_a_src + a_src->meta.wi;
41784 }
41785
41786 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
41787 if (coro_susp_point) {
41788 v_dst_bytes_per_pixel = self->private_data.s_decode_frame[0].v_dst_bytes_per_pixel;
41789 v_dst_x = self->private_data.s_decode_frame[0].v_dst_x;
41790 v_dst_y = self->private_data.s_decode_frame[0].v_dst_y;
41791 memcpy(v_src, self->private_data.s_decode_frame[0].v_src, sizeof(v_src));
41792 v_c = self->private_data.s_decode_frame[0].v_c;
41793 }
41794 switch (coro_susp_point) {
41795 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41796
41797 if (self->private_impl.f_call_sequence < 4) {
41798 if (a_src) {
41799 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41800 }
41801 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41802 status = wuffs_wbmp__decoder__decode_frame_config(self, NULL, a_src);
41803 if (a_src) {
41804 iop_a_src = a_src->data.ptr + a_src->meta.ri;
41805 }
41806 if (status.repr) {
41807 goto suspend;
41808 }
41809 } else if (self->private_impl.f_call_sequence == 4) {
41810 } else {
41811 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
41812 goto ok;
41813 }
41814 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
41815 wuffs_base__pixel_buffer__pixel_format(a_dst),
41816 wuffs_base__pixel_buffer__palette(a_dst),
41817 wuffs_base__utility__make_pixel_format(536870920),
41818 wuffs_base__utility__empty_slice_u8(),
41819 a_blend);
41820 if ( ! wuffs_base__status__is_ok(&v_status)) {
41821 status = v_status;
41822 if (wuffs_base__status__is_error(&status)) {
41823 goto exit;
41824 } else if (wuffs_base__status__is_suspension(&status)) {
41825 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
41826 goto exit;
41827 }
41828 goto ok;
41829 }
41830 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
41831 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
41832 if ((v_dst_bits_per_pixel & 7) != 0) {
41833 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
41834 goto exit;
41835 }
41836 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
41837 if (self->private_impl.f_width > 0) {
41838 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
41839 while (v_dst_y < self->private_impl.f_height) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041840 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100041841 v_dst_x = 0;
41842 while (v_dst_x < self->private_impl.f_width) {
41843 if ((v_dst_x & 7) == 0) {
41844 while (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
41845 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41846 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
41847 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
Nigel Taobf9dab32021-11-18 19:19:55 +110041848 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100041849 v_dst_x_in_bytes = (((uint64_t)(v_dst_x)) * v_dst_bytes_per_pixel);
41850 if (v_dst_x_in_bytes <= ((uint64_t)(v_dst.len))) {
41851 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_x_in_bytes);
41852 }
41853 }
41854 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
41855 iop_a_src += 1;
41856 }
41857 if ((v_c & 128) == 0) {
41858 v_src[0] = 0;
41859 } else {
41860 v_src[0] = 255;
41861 }
41862 v_c = ((uint8_t)(((((uint32_t)(v_c)) << 1) & 255)));
41863 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, wuffs_base__utility__empty_slice_u8(), wuffs_base__make_slice_u8(v_src, 1));
41864 if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) {
41865 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel);
41866 }
41867 v_dst_x += 1;
41868 }
41869 v_dst_y += 1;
41870 }
41871 }
41872 self->private_impl.f_call_sequence = 255;
41873
Nigel Taoe360a532021-04-05 22:47:03 +100041874 ok:
41875 self->private_impl.p_decode_frame[0] = 0;
41876 goto exit;
41877 }
41878
41879 goto suspend;
41880 suspend:
41881 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
41882 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
41883 self->private_data.s_decode_frame[0].v_dst_bytes_per_pixel = v_dst_bytes_per_pixel;
41884 self->private_data.s_decode_frame[0].v_dst_x = v_dst_x;
41885 self->private_data.s_decode_frame[0].v_dst_y = v_dst_y;
41886 memcpy(self->private_data.s_decode_frame[0].v_src, v_src, sizeof(v_src));
41887 self->private_data.s_decode_frame[0].v_c = v_c;
41888
41889 goto exit;
41890 exit:
41891 if (a_src) {
41892 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41893 }
41894
41895 if (wuffs_base__status__is_error(&status)) {
41896 self->private_impl.magic = WUFFS_BASE__DISABLED;
41897 }
41898 return status;
41899}
41900
41901// -------- func wbmp.decoder.frame_dirty_rect
41902
41903WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
41904wuffs_wbmp__decoder__frame_dirty_rect(
41905 const wuffs_wbmp__decoder* self) {
41906 if (!self) {
41907 return wuffs_base__utility__empty_rect_ie_u32();
41908 }
41909 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
41910 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
41911 return wuffs_base__utility__empty_rect_ie_u32();
41912 }
41913
41914 return wuffs_base__utility__make_rect_ie_u32(
41915 0,
41916 0,
41917 self->private_impl.f_width,
41918 self->private_impl.f_height);
41919}
41920
41921// -------- func wbmp.decoder.num_animation_loops
41922
41923WUFFS_BASE__MAYBE_STATIC uint32_t
41924wuffs_wbmp__decoder__num_animation_loops(
41925 const wuffs_wbmp__decoder* self) {
41926 if (!self) {
41927 return 0;
41928 }
41929 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
41930 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
41931 return 0;
41932 }
41933
41934 return 0;
41935}
41936
41937// -------- func wbmp.decoder.num_decoded_frame_configs
41938
41939WUFFS_BASE__MAYBE_STATIC uint64_t
41940wuffs_wbmp__decoder__num_decoded_frame_configs(
41941 const wuffs_wbmp__decoder* self) {
41942 if (!self) {
41943 return 0;
41944 }
41945 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
41946 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
41947 return 0;
41948 }
41949
41950 if (self->private_impl.f_call_sequence > 3) {
41951 return 1;
41952 }
41953 return 0;
41954}
41955
41956// -------- func wbmp.decoder.num_decoded_frames
41957
41958WUFFS_BASE__MAYBE_STATIC uint64_t
41959wuffs_wbmp__decoder__num_decoded_frames(
41960 const wuffs_wbmp__decoder* self) {
41961 if (!self) {
41962 return 0;
41963 }
41964 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
41965 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
41966 return 0;
41967 }
41968
41969 if (self->private_impl.f_call_sequence > 4) {
41970 return 1;
41971 }
41972 return 0;
41973}
41974
41975// -------- func wbmp.decoder.restart_frame
41976
41977WUFFS_BASE__MAYBE_STATIC wuffs_base__status
41978wuffs_wbmp__decoder__restart_frame(
41979 wuffs_wbmp__decoder* self,
41980 uint64_t a_index,
41981 uint64_t a_io_position) {
41982 if (!self) {
41983 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
41984 }
41985 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
41986 return wuffs_base__make_status(
41987 (self->private_impl.magic == WUFFS_BASE__DISABLED)
41988 ? wuffs_base__error__disabled_by_previous_error
41989 : wuffs_base__error__initialize_not_called);
41990 }
41991
41992 if (self->private_impl.f_call_sequence < 3) {
41993 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
41994 }
41995 if (a_index != 0) {
41996 return wuffs_base__make_status(wuffs_base__error__bad_argument);
41997 }
41998 self->private_impl.f_call_sequence = 3;
41999 self->private_impl.f_frame_config_io_position = a_io_position;
42000 return wuffs_base__make_status(NULL);
42001}
42002
42003// -------- func wbmp.decoder.set_report_metadata
42004
42005WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
42006wuffs_wbmp__decoder__set_report_metadata(
42007 wuffs_wbmp__decoder* self,
42008 uint32_t a_fourcc,
42009 bool a_report) {
42010 return wuffs_base__make_empty_struct();
42011}
42012
42013// -------- func wbmp.decoder.tell_me_more
42014
42015WUFFS_BASE__MAYBE_STATIC wuffs_base__status
42016wuffs_wbmp__decoder__tell_me_more(
42017 wuffs_wbmp__decoder* self,
42018 wuffs_base__io_buffer* a_dst,
42019 wuffs_base__more_information* a_minfo,
42020 wuffs_base__io_buffer* a_src) {
42021 if (!self) {
42022 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
42023 }
42024 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
42025 return wuffs_base__make_status(
42026 (self->private_impl.magic == WUFFS_BASE__DISABLED)
42027 ? wuffs_base__error__disabled_by_previous_error
42028 : wuffs_base__error__initialize_not_called);
42029 }
42030 if (!a_dst || !a_src) {
42031 self->private_impl.magic = WUFFS_BASE__DISABLED;
42032 return wuffs_base__make_status(wuffs_base__error__bad_argument);
42033 }
42034 if ((self->private_impl.active_coroutine != 0) &&
42035 (self->private_impl.active_coroutine != 4)) {
42036 self->private_impl.magic = WUFFS_BASE__DISABLED;
42037 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
42038 }
42039 self->private_impl.active_coroutine = 0;
42040 wuffs_base__status status = wuffs_base__make_status(NULL);
42041
42042 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
42043 goto exit;
42044
42045 goto ok;
42046 ok:
42047 goto exit;
42048 exit:
42049 if (wuffs_base__status__is_error(&status)) {
42050 self->private_impl.magic = WUFFS_BASE__DISABLED;
42051 }
42052 return status;
42053}
42054
42055// -------- func wbmp.decoder.workbuf_len
42056
42057WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
42058wuffs_wbmp__decoder__workbuf_len(
42059 const wuffs_wbmp__decoder* self) {
42060 if (!self) {
42061 return wuffs_base__utility__empty_range_ii_u64();
42062 }
42063 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
42064 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
42065 return wuffs_base__utility__empty_range_ii_u64();
42066 }
42067
42068 return wuffs_base__utility__make_range_ii_u64(0, 0);
42069}
42070
42071#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP)
42072
42073#if defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
42074
42075// ---------------- Auxiliary - Base
42076
42077// Auxiliary code is discussed at
42078// https://github.com/google/wuffs/blob/main/doc/note/auxiliary-code.md
42079
42080#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__BASE)
42081
42082namespace wuffs_aux {
42083
42084namespace sync_io {
42085
42086// --------
42087
Nigel Taobf9dab32021-11-18 19:19:55 +110042088DynIOBuffer::DynIOBuffer(uint64_t max_incl)
42089 : m_buf(wuffs_base__empty_io_buffer()), m_max_incl(max_incl) {}
42090
42091DynIOBuffer::~DynIOBuffer() {
42092 if (m_buf.data.ptr) {
42093 free(m_buf.data.ptr);
42094 }
42095}
42096
42097void //
42098DynIOBuffer::drop() {
42099 if (m_buf.data.ptr) {
42100 free(m_buf.data.ptr);
42101 }
42102 m_buf = wuffs_base__empty_io_buffer();
42103}
42104
42105DynIOBuffer::GrowResult //
42106DynIOBuffer::grow(uint64_t min_incl) {
42107 uint64_t n = round_up(min_incl, m_max_incl);
42108 if (n == 0) {
42109 return ((min_incl == 0) && (m_max_incl == 0))
42110 ? DynIOBuffer::GrowResult::OK
42111 : DynIOBuffer::GrowResult::FailedMaxInclExceeded;
42112 } else if (n > m_buf.data.len) {
42113 uint8_t* ptr = static_cast<uint8_t*>(realloc(m_buf.data.ptr, n));
42114 if (!ptr) {
42115 return DynIOBuffer::GrowResult::FailedOutOfMemory;
42116 }
42117 m_buf.data.ptr = ptr;
42118 m_buf.data.len = n;
42119 }
42120 return DynIOBuffer::GrowResult::OK;
42121}
42122
42123// round_up rounds min_incl up, returning the smallest value x satisfying
42124// (min_incl <= x) and (x <= max_incl) and some other constraints. It returns 0
42125// if there is no such x.
42126//
42127// When max_incl <= 4096, the other constraints are:
42128// - (x == max_incl)
42129//
42130// When max_incl > 4096, the other constraints are:
42131// - (x == max_incl) or (x is a power of 2)
42132// - (x >= 4096)
42133uint64_t //
42134DynIOBuffer::round_up(uint64_t min_incl, uint64_t max_incl) {
42135 if (min_incl > max_incl) {
42136 return 0;
42137 }
42138 uint64_t n = 4096;
42139 if (n >= max_incl) {
42140 return max_incl;
42141 }
42142 while (n < min_incl) {
42143 if (n >= (max_incl / 2)) {
42144 return max_incl;
42145 }
42146 n *= 2;
42147 }
42148 return n;
42149}
42150
42151// --------
42152
Nigel Taoe360a532021-04-05 22:47:03 +100042153Input::~Input() {}
42154
42155IOBuffer* //
42156Input::BringsItsOwnIOBuffer() {
42157 return nullptr;
42158}
42159
42160// --------
42161
42162FileInput::FileInput(FILE* f) : m_f(f) {}
42163
42164std::string //
42165FileInput::CopyIn(IOBuffer* dst) {
42166 if (!m_f) {
42167 return "wuffs_aux::sync_io::FileInput: nullptr file";
42168 } else if (!dst) {
42169 return "wuffs_aux::sync_io::FileInput: nullptr IOBuffer";
42170 } else if (dst->meta.closed) {
42171 return "wuffs_aux::sync_io::FileInput: end of file";
42172 } else {
42173 dst->compact();
42174 size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);
42175 dst->meta.wi += n;
42176 dst->meta.closed = feof(m_f);
42177 if (ferror(m_f)) {
42178 return "wuffs_aux::sync_io::FileInput: error reading file";
42179 }
42180 }
42181 return "";
42182}
42183
42184// --------
42185
42186MemoryInput::MemoryInput(const char* ptr, size_t len)
42187 : m_io(wuffs_base__ptr_u8__reader(
42188 static_cast<uint8_t*>(static_cast<void*>(const_cast<char*>(ptr))),
42189 len,
42190 true)) {}
42191
42192MemoryInput::MemoryInput(const uint8_t* ptr, size_t len)
42193 : m_io(wuffs_base__ptr_u8__reader(const_cast<uint8_t*>(ptr), len, true)) {}
42194
42195IOBuffer* //
42196MemoryInput::BringsItsOwnIOBuffer() {
42197 return &m_io;
42198}
42199
42200std::string //
42201MemoryInput::CopyIn(IOBuffer* dst) {
42202 if (!dst) {
42203 return "wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer";
42204 } else if (dst->meta.closed) {
42205 return "wuffs_aux::sync_io::MemoryInput: end of file";
42206 } else if (wuffs_base__slice_u8__overlaps(dst->data, m_io.data)) {
42207 // Treat m_io's data as immutable, so don't compact dst or otherwise write
42208 // to it.
42209 return "wuffs_aux::sync_io::MemoryInput: overlapping buffers";
42210 } else {
42211 dst->compact();
42212 size_t nd = dst->writer_length();
42213 size_t ns = m_io.reader_length();
42214 size_t n = (nd < ns) ? nd : ns;
42215 memcpy(dst->writer_pointer(), m_io.reader_pointer(), n);
42216 m_io.meta.ri += n;
42217 dst->meta.wi += n;
42218 dst->meta.closed = m_io.reader_length() == 0;
42219 }
42220 return "";
42221}
42222
42223// --------
42224
42225} // namespace sync_io
42226
Nigel Taobf9dab32021-11-18 19:19:55 +110042227namespace private_impl {
42228
42229struct ErrorMessages {
42230 const char* max_incl_metadata_length_exceeded;
42231 const char* out_of_memory;
42232 const char* unexpected_end_of_file;
42233 const char* unsupported_metadata;
42234 const char* unsupported_negative_advance;
42235
42236 // If adding new "const char*" typed fields to this struct, either add them
42237 // after existing fields or, if re-ordering fields, make sure that you update
42238 // all of the "const private_impl::ErrorMessages FooBarErrorMessages" values
42239 // in all of the sibling *.cc files.
42240
42241 static inline const char* resolve(const char* s) {
42242 return s ? s : "wuffs_aux::private_impl: unknown error";
42243 };
42244};
42245
42246std::string //
42247AdvanceIOBufferTo(const ErrorMessages& error_messages,
42248 sync_io::Input& input,
42249 IOBuffer& io_buf,
42250 uint64_t absolute_position) {
42251 if (absolute_position < io_buf.reader_position()) {
42252 return error_messages.resolve(error_messages.unsupported_negative_advance);
42253 }
42254 while (true) {
42255 uint64_t relative_position = absolute_position - io_buf.reader_position();
42256 if (relative_position <= io_buf.reader_length()) {
42257 io_buf.meta.ri += (size_t)relative_position;
42258 break;
42259 } else if (io_buf.meta.closed) {
42260 return error_messages.resolve(error_messages.unexpected_end_of_file);
42261 }
42262 io_buf.meta.ri = io_buf.meta.wi;
42263 if (!input.BringsItsOwnIOBuffer()) {
42264 io_buf.compact();
42265 }
42266 std::string error_message = input.CopyIn(&io_buf);
42267 if (!error_message.empty()) {
42268 return error_message;
42269 }
42270 }
42271 return "";
42272}
42273
42274std::string //
42275HandleMetadata(
42276 const ErrorMessages& error_messages,
42277 sync_io::Input& input,
42278 wuffs_base__io_buffer& io_buf,
42279 sync_io::DynIOBuffer& raw,
42280 wuffs_base__status (*tell_me_more_func)(void*,
42281 wuffs_base__io_buffer*,
42282 wuffs_base__more_information*,
42283 wuffs_base__io_buffer*),
42284 void* tell_me_more_receiver,
42285 std::string (*handle_metadata_func)(void*,
42286 const wuffs_base__more_information*,
42287 wuffs_base__slice_u8),
42288 void* handle_metadata_receiver) {
42289 wuffs_base__more_information minfo = wuffs_base__empty_more_information();
42290 // Reset raw but keep its backing array (the raw.m_buf.data slice).
42291 raw.m_buf.meta = wuffs_base__empty_io_buffer_meta();
42292
42293 while (true) {
42294 minfo = wuffs_base__empty_more_information();
42295 wuffs_base__status status = (*tell_me_more_func)(
42296 tell_me_more_receiver, &raw.m_buf, &minfo, &io_buf);
42297 switch (minfo.flavor) {
42298 case 0:
42299 case WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_TRANSFORM:
42300 case WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED:
42301 break;
42302
42303 case WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH: {
42304 wuffs_base__range_ie_u64 r = minfo.metadata_raw_passthrough__range();
42305 if (r.is_empty()) {
42306 break;
42307 }
42308 uint64_t num_to_copy = r.length();
42309 if (num_to_copy > (raw.m_max_incl - raw.m_buf.meta.wi)) {
42310 return error_messages.resolve(
42311 error_messages.max_incl_metadata_length_exceeded);
42312 } else if (num_to_copy > (raw.m_buf.data.len - raw.m_buf.meta.wi)) {
42313 switch (raw.grow(num_to_copy + raw.m_buf.meta.wi)) {
42314 case sync_io::DynIOBuffer::GrowResult::OK:
42315 break;
42316 case sync_io::DynIOBuffer::GrowResult::FailedMaxInclExceeded:
42317 return error_messages.resolve(
42318 error_messages.max_incl_metadata_length_exceeded);
42319 case sync_io::DynIOBuffer::GrowResult::FailedOutOfMemory:
42320 return error_messages.resolve(error_messages.out_of_memory);
42321 }
42322 }
42323
42324 if (io_buf.reader_position() > r.min_incl) {
42325 return error_messages.resolve(error_messages.unsupported_metadata);
42326 } else {
42327 std::string error_message =
42328 AdvanceIOBufferTo(error_messages, input, io_buf, r.min_incl);
42329 if (!error_message.empty()) {
42330 return error_message;
42331 }
42332 }
42333
42334 while (true) {
42335 uint64_t n =
42336 wuffs_base__u64__min(num_to_copy, io_buf.reader_length());
42337 memcpy(raw.m_buf.writer_pointer(), io_buf.reader_pointer(), n);
42338 raw.m_buf.meta.wi += n;
42339 io_buf.meta.ri += n;
42340 num_to_copy -= n;
42341 if (num_to_copy == 0) {
42342 break;
42343 } else if (io_buf.meta.closed) {
42344 return error_messages.resolve(
42345 error_messages.unexpected_end_of_file);
42346 } else if (!input.BringsItsOwnIOBuffer()) {
42347 io_buf.compact();
42348 }
42349 std::string error_message = input.CopyIn(&io_buf);
42350 if (!error_message.empty()) {
42351 return error_message;
42352 }
42353 }
42354 break;
42355 }
42356
42357 default:
42358 return error_messages.resolve(error_messages.unsupported_metadata);
42359 }
42360
42361 if (status.repr == nullptr) {
42362 break;
42363 } else if (status.repr != wuffs_base__suspension__even_more_information) {
42364 if (status.repr != wuffs_base__suspension__short_write) {
42365 return status.message();
42366 }
42367 switch (raw.grow(wuffs_base__u64__sat_add(raw.m_buf.data.len, 1))) {
42368 case sync_io::DynIOBuffer::GrowResult::OK:
42369 break;
42370 case sync_io::DynIOBuffer::GrowResult::FailedMaxInclExceeded:
42371 return error_messages.resolve(
42372 error_messages.max_incl_metadata_length_exceeded);
42373 case sync_io::DynIOBuffer::GrowResult::FailedOutOfMemory:
42374 return error_messages.resolve(error_messages.out_of_memory);
42375 }
42376 }
42377 }
42378
42379 return (*handle_metadata_func)(handle_metadata_receiver, &minfo,
42380 raw.m_buf.reader_slice());
42381}
42382
42383} // namespace private_impl
42384
Nigel Taoe360a532021-04-05 22:47:03 +100042385} // namespace wuffs_aux
42386
42387#endif // !defined(WUFFS_CONFIG__MODULES) ||
42388 // defined(WUFFS_CONFIG__MODULE__AUX__BASE)
42389
42390// ---------------- Auxiliary - CBOR
42391
42392#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__CBOR)
42393
42394#include <utility>
42395
42396namespace wuffs_aux {
42397
42398DecodeCborResult::DecodeCborResult(std::string&& error_message0,
42399 uint64_t cursor_position0)
42400 : error_message(std::move(error_message0)),
42401 cursor_position(cursor_position0) {}
42402
42403DecodeCborCallbacks::~DecodeCborCallbacks() {}
42404
42405void //
42406DecodeCborCallbacks::Done(DecodeCborResult& result,
42407 sync_io::Input& input,
42408 IOBuffer& buffer) {}
42409
Nigel Taobf9dab32021-11-18 19:19:55 +110042410DecodeCborArgQuirks::DecodeCborArgQuirks(wuffs_base__slice_u32 repr0)
42411 : repr(repr0) {}
42412
42413DecodeCborArgQuirks::DecodeCborArgQuirks(uint32_t* ptr0, size_t len0)
42414 : repr(wuffs_base__make_slice_u32(ptr0, len0)) {}
42415
42416DecodeCborArgQuirks //
42417DecodeCborArgQuirks::DefaultValue() {
42418 return DecodeCborArgQuirks(wuffs_base__empty_slice_u32());
42419}
42420
Nigel Taoe360a532021-04-05 22:47:03 +100042421DecodeCborResult //
42422DecodeCbor(DecodeCborCallbacks& callbacks,
42423 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110042424 DecodeCborArgQuirks quirks) {
Nigel Taoe360a532021-04-05 22:47:03 +100042425 // Prepare the wuffs_base__io_buffer and the resultant error_message.
42426 wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
42427 wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
42428 std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);
42429 if (!io_buf) {
42430 fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[4096]);
42431 fallback_io_buf = wuffs_base__ptr_u8__writer(fallback_io_array.get(), 4096);
42432 io_buf = &fallback_io_buf;
42433 }
42434 // cursor_index is discussed at
42435 // https://nigeltao.github.io/blog/2020/jsonptr.html#the-cursor-index
42436 size_t cursor_index = 0;
42437 std::string ret_error_message;
42438 std::string io_error_message;
42439
42440 do {
42441 // Prepare the low-level CBOR decoder.
42442 wuffs_cbor__decoder::unique_ptr dec = wuffs_cbor__decoder::alloc();
42443 if (!dec) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042444 ret_error_message = "wuffs_aux::DecodeCbor: out of memory";
Nigel Taoe360a532021-04-05 22:47:03 +100042445 goto done;
42446 }
Nigel Taobf9dab32021-11-18 19:19:55 +110042447 for (size_t i = 0; i < quirks.repr.len; i++) {
42448 dec->set_quirk_enabled(quirks.repr.ptr[i], true);
Nigel Taoe360a532021-04-05 22:47:03 +100042449 }
42450
42451 // Prepare the wuffs_base__tok_buffer. 256 tokens is 2KiB.
42452 wuffs_base__token tok_array[256];
42453 wuffs_base__token_buffer tok_buf =
42454 wuffs_base__slice_token__writer(wuffs_base__make_slice_token(
42455 &tok_array[0], (sizeof(tok_array) / sizeof(tok_array[0]))));
42456 wuffs_base__status tok_status = wuffs_base__make_status(nullptr);
42457
42458 // Prepare other state.
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042459 int32_t depth = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100042460 std::string str;
42461 int64_t extension_category = 0;
42462 uint64_t extension_detail = 0;
42463
42464 // Valid token's VBCs range in 0 ..= 15. Values over that are for tokens
42465 // from outside of the base package, such as the CBOR package.
42466 constexpr int64_t EXT_CAT__CBOR_TAG = 16;
42467
42468 // Loop, doing these two things:
42469 // 1. Get the next token.
42470 // 2. Process that token.
42471 while (true) {
42472 // 1. Get the next token.
42473
42474 while (tok_buf.meta.ri >= tok_buf.meta.wi) {
42475 if (tok_status.repr == nullptr) {
42476 // No-op.
42477 } else if (tok_status.repr == wuffs_base__suspension__short_write) {
42478 tok_buf.compact();
42479 } else if (tok_status.repr == wuffs_base__suspension__short_read) {
42480 // Read from input to io_buf.
42481 if (!io_error_message.empty()) {
42482 ret_error_message = std::move(io_error_message);
42483 goto done;
42484 } else if (cursor_index != io_buf->meta.ri) {
42485 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042486 "wuffs_aux::DecodeCbor: internal error: bad cursor_index";
Nigel Taoe360a532021-04-05 22:47:03 +100042487 goto done;
42488 } else if (io_buf->meta.closed) {
42489 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042490 "wuffs_aux::DecodeCbor: internal error: io_buf is closed";
Nigel Taoe360a532021-04-05 22:47:03 +100042491 goto done;
42492 }
42493 io_buf->compact();
42494 if (io_buf->meta.wi >= io_buf->data.len) {
42495 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042496 "wuffs_aux::DecodeCbor: internal error: io_buf is full";
Nigel Taoe360a532021-04-05 22:47:03 +100042497 goto done;
42498 }
42499 cursor_index = io_buf->meta.ri;
42500 io_error_message = input.CopyIn(io_buf);
42501 } else {
42502 ret_error_message = tok_status.message();
42503 goto done;
42504 }
42505
42506 if (WUFFS_CBOR__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {
42507 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042508 "wuffs_aux::DecodeCbor: internal error: bad WORKBUF_LEN";
Nigel Taoe360a532021-04-05 22:47:03 +100042509 goto done;
42510 }
42511 wuffs_base__slice_u8 work_buf = wuffs_base__empty_slice_u8();
42512 tok_status = dec->decode_tokens(&tok_buf, io_buf, work_buf);
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042513 if ((tok_buf.meta.ri > tok_buf.meta.wi) ||
42514 (tok_buf.meta.wi > tok_buf.data.len) ||
42515 (io_buf->meta.ri > io_buf->meta.wi) ||
42516 (io_buf->meta.wi > io_buf->data.len)) {
42517 ret_error_message =
42518 "wuffs_aux::DecodeCbor: internal error: bad buffer indexes";
42519 goto done;
42520 }
Nigel Taoe360a532021-04-05 22:47:03 +100042521 }
42522
42523 wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++];
42524 uint64_t token_len = token.length();
42525 if ((io_buf->meta.ri < cursor_index) ||
42526 ((io_buf->meta.ri - cursor_index) < token_len)) {
42527 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042528 "wuffs_aux::DecodeCbor: internal error: bad token indexes";
Nigel Taoe360a532021-04-05 22:47:03 +100042529 goto done;
42530 }
42531 uint8_t* token_ptr = io_buf->data.ptr + cursor_index;
42532 cursor_index += static_cast<size_t>(token_len);
42533
42534 // 2. Process that token.
42535
42536 uint64_t vbd = token.value_base_detail();
42537
42538 if (extension_category != 0) {
42539 int64_t ext = token.value_extension();
42540 if ((ext >= 0) && !token.continued()) {
42541 extension_detail = (extension_detail
42542 << WUFFS_BASE__TOKEN__VALUE_EXTENSION__NUM_BITS) |
42543 static_cast<uint64_t>(ext);
42544 switch (extension_category) {
42545 case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED:
42546 extension_category = 0;
42547 ret_error_message =
42548 callbacks.AppendI64(static_cast<int64_t>(extension_detail));
42549 goto parsed_a_value;
42550 case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED:
42551 extension_category = 0;
42552 ret_error_message = callbacks.AppendU64(extension_detail);
42553 goto parsed_a_value;
42554 case EXT_CAT__CBOR_TAG:
42555 extension_category = 0;
42556 ret_error_message = callbacks.AppendCborTag(extension_detail);
42557 if (!ret_error_message.empty()) {
42558 goto done;
42559 }
42560 continue;
42561 }
42562 }
42563 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042564 "wuffs_aux::DecodeCbor: internal error: bad extended token";
Nigel Taoe360a532021-04-05 22:47:03 +100042565 goto done;
42566 }
42567
42568 switch (token.value_base_category()) {
42569 case WUFFS_BASE__TOKEN__VBC__FILLER:
42570 continue;
42571
42572 case WUFFS_BASE__TOKEN__VBC__STRUCTURE: {
42573 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
42574 ret_error_message = callbacks.Push(static_cast<uint32_t>(vbd));
42575 if (!ret_error_message.empty()) {
42576 goto done;
42577 }
42578 depth++;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042579 if (depth > WUFFS_CBOR__DECODER_DEPTH_MAX_INCL) {
42580 ret_error_message =
42581 "wuffs_aux::DecodeCbor: internal error: bad depth";
42582 goto done;
42583 }
Nigel Taoe360a532021-04-05 22:47:03 +100042584 continue;
42585 }
42586 ret_error_message = callbacks.Pop(static_cast<uint32_t>(vbd));
42587 depth--;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042588 if (depth < 0) {
42589 ret_error_message =
42590 "wuffs_aux::DecodeCbor: internal error: bad depth";
42591 goto done;
42592 }
Nigel Taoe360a532021-04-05 22:47:03 +100042593 goto parsed_a_value;
42594 }
42595
42596 case WUFFS_BASE__TOKEN__VBC__STRING: {
42597 if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
42598 // No-op.
42599 } else if (vbd &
42600 WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
42601 const char* ptr = // Convert from (uint8_t*).
42602 static_cast<const char*>(static_cast<void*>(token_ptr));
42603 str.append(ptr, static_cast<size_t>(token_len));
42604 } else {
42605 goto fail;
42606 }
42607 if (token.continued()) {
42608 continue;
42609 }
42610 ret_error_message =
42611 (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8)
42612 ? callbacks.AppendTextString(std::move(str))
42613 : callbacks.AppendByteString(std::move(str));
42614 str.clear();
42615 goto parsed_a_value;
42616 }
42617
42618 case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
42619 uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
42620 size_t n = wuffs_base__utf_8__encode(
42621 wuffs_base__make_slice_u8(
42622 &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
42623 static_cast<uint32_t>(vbd));
42624 const char* ptr = // Convert from (uint8_t*).
42625 static_cast<const char*>(static_cast<void*>(&u[0]));
42626 str.append(ptr, n);
42627 if (token.continued()) {
42628 continue;
42629 }
42630 goto fail;
42631 }
42632
42633 case WUFFS_BASE__TOKEN__VBC__LITERAL: {
42634 if (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__NULL) {
42635 ret_error_message = callbacks.AppendNull();
42636 } else if (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__UNDEFINED) {
42637 ret_error_message = callbacks.AppendUndefined();
42638 } else {
42639 ret_error_message = callbacks.AppendBool(
42640 vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE);
42641 }
42642 goto parsed_a_value;
42643 }
42644
42645 case WUFFS_BASE__TOKEN__VBC__NUMBER: {
42646 const uint64_t cfp_fbbe_fifb =
42647 WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT |
42648 WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN |
42649 WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE;
42650 if ((vbd & cfp_fbbe_fifb) == cfp_fbbe_fifb) {
42651 double f;
42652 switch (token_len) {
42653 case 3:
42654 f = wuffs_base__ieee_754_bit_representation__from_u16_to_f64(
42655 wuffs_base__peek_u16be__no_bounds_check(token_ptr + 1));
42656 break;
42657 case 5:
42658 f = wuffs_base__ieee_754_bit_representation__from_u32_to_f64(
42659 wuffs_base__peek_u32be__no_bounds_check(token_ptr + 1));
42660 break;
42661 case 9:
42662 f = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
42663 wuffs_base__peek_u64be__no_bounds_check(token_ptr + 1));
42664 break;
42665 default:
42666 goto fail;
42667 }
42668 ret_error_message = callbacks.AppendF64(f);
42669 goto parsed_a_value;
42670 }
42671 goto fail;
42672 }
42673
42674 case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED: {
42675 if (token.continued()) {
42676 extension_category = WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED;
42677 extension_detail =
42678 static_cast<uint64_t>(token.value_base_detail__sign_extended());
42679 continue;
42680 }
42681 ret_error_message =
42682 callbacks.AppendI64(token.value_base_detail__sign_extended());
42683 goto parsed_a_value;
42684 }
42685
42686 case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED: {
42687 if (token.continued()) {
42688 extension_category =
42689 WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED;
42690 extension_detail = vbd;
42691 continue;
42692 }
42693 ret_error_message = callbacks.AppendU64(vbd);
42694 goto parsed_a_value;
42695 }
42696 }
42697
42698 if (token.value_major() == WUFFS_CBOR__TOKEN_VALUE_MAJOR) {
42699 uint64_t value_minor = token.value_minor();
42700 if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__MINUS_1_MINUS_X) {
42701 if (token_len == 9) {
42702 ret_error_message = callbacks.AppendMinus1MinusX(
42703 wuffs_base__peek_u64be__no_bounds_check(token_ptr + 1));
42704 goto parsed_a_value;
42705 }
42706 } else if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__SIMPLE_VALUE) {
42707 ret_error_message =
42708 callbacks.AppendCborSimpleValue(static_cast<uint8_t>(
42709 value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK));
42710 goto parsed_a_value;
42711 } else if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__TAG) {
42712 if (token.continued()) {
42713 extension_category = EXT_CAT__CBOR_TAG;
42714 extension_detail =
42715 value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK;
42716 continue;
42717 }
42718 ret_error_message = callbacks.AppendCborTag(
42719 value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK);
42720 if (!ret_error_message.empty()) {
42721 goto done;
42722 }
42723 continue;
42724 }
42725 }
42726
42727 fail:
42728 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042729 "wuffs_aux::DecodeCbor: internal error: unexpected token";
Nigel Taoe360a532021-04-05 22:47:03 +100042730 goto done;
42731
42732 parsed_a_value:
42733 if (!ret_error_message.empty() || (depth == 0)) {
42734 goto done;
42735 }
42736 }
42737 } while (false);
42738
42739done:
42740 DecodeCborResult result(
42741 std::move(ret_error_message),
42742 wuffs_base__u64__sat_add(io_buf->meta.pos, cursor_index));
42743 callbacks.Done(result, input, *io_buf);
42744 return result;
42745}
42746
42747} // namespace wuffs_aux
42748
42749#endif // !defined(WUFFS_CONFIG__MODULES) ||
42750 // defined(WUFFS_CONFIG__MODULE__AUX__CBOR)
42751
42752// ---------------- Auxiliary - Image
42753
42754#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__IMAGE)
42755
42756#include <utility>
42757
42758namespace wuffs_aux {
42759
42760DecodeImageResult::DecodeImageResult(MemOwner&& pixbuf_mem_owner0,
42761 wuffs_base__pixel_buffer pixbuf0,
42762 std::string&& error_message0)
42763 : pixbuf_mem_owner(std::move(pixbuf_mem_owner0)),
42764 pixbuf(pixbuf0),
42765 error_message(std::move(error_message0)) {}
42766
42767DecodeImageResult::DecodeImageResult(std::string&& error_message0)
42768 : pixbuf_mem_owner(nullptr, &free),
42769 pixbuf(wuffs_base__null_pixel_buffer()),
42770 error_message(std::move(error_message0)) {}
42771
42772DecodeImageCallbacks::~DecodeImageCallbacks() {}
42773
42774DecodeImageCallbacks::AllocPixbufResult::AllocPixbufResult(
42775 MemOwner&& mem_owner0,
42776 wuffs_base__pixel_buffer pixbuf0)
42777 : mem_owner(std::move(mem_owner0)), pixbuf(pixbuf0), error_message("") {}
42778
42779DecodeImageCallbacks::AllocPixbufResult::AllocPixbufResult(
42780 std::string&& error_message0)
42781 : mem_owner(nullptr, &free),
42782 pixbuf(wuffs_base__null_pixel_buffer()),
42783 error_message(std::move(error_message0)) {}
42784
42785DecodeImageCallbacks::AllocWorkbufResult::AllocWorkbufResult(
42786 MemOwner&& mem_owner0,
42787 wuffs_base__slice_u8 workbuf0)
42788 : mem_owner(std::move(mem_owner0)), workbuf(workbuf0), error_message("") {}
42789
42790DecodeImageCallbacks::AllocWorkbufResult::AllocWorkbufResult(
42791 std::string&& error_message0)
42792 : mem_owner(nullptr, &free),
42793 workbuf(wuffs_base__empty_slice_u8()),
42794 error_message(std::move(error_message0)) {}
42795
42796wuffs_base__image_decoder::unique_ptr //
42797DecodeImageCallbacks::SelectDecoder(uint32_t fourcc,
42798 wuffs_base__slice_u8 prefix) {
42799 switch (fourcc) {
42800#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP)
42801 case WUFFS_BASE__FOURCC__BMP:
42802 return wuffs_bmp__decoder::alloc_as__wuffs_base__image_decoder();
42803#endif
42804
42805#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF)
42806 case WUFFS_BASE__FOURCC__GIF:
42807 return wuffs_gif__decoder::alloc_as__wuffs_base__image_decoder();
42808#endif
42809
42810#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE)
42811 case WUFFS_BASE__FOURCC__NIE:
42812 return wuffs_nie__decoder::alloc_as__wuffs_base__image_decoder();
42813#endif
42814
42815#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG)
42816 case WUFFS_BASE__FOURCC__PNG: {
42817 auto dec = wuffs_png__decoder::alloc_as__wuffs_base__image_decoder();
42818 // Favor faster decodes over rejecting invalid checksums.
42819 dec->set_quirk_enabled(WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true);
42820 return dec;
42821 }
42822#endif
42823
42824#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP)
42825 case WUFFS_BASE__FOURCC__WBMP:
42826 return wuffs_wbmp__decoder::alloc_as__wuffs_base__image_decoder();
42827#endif
42828 }
42829
42830 return wuffs_base__image_decoder::unique_ptr(nullptr, &free);
42831}
42832
Nigel Taobf9dab32021-11-18 19:19:55 +110042833std::string //
42834DecodeImageCallbacks::HandleMetadata(const wuffs_base__more_information& minfo,
42835 wuffs_base__slice_u8 raw) {
42836 return "";
42837}
42838
Nigel Taoe360a532021-04-05 22:47:03 +100042839wuffs_base__pixel_format //
42840DecodeImageCallbacks::SelectPixfmt(
42841 const wuffs_base__image_config& image_config) {
42842 return wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL);
42843}
42844
42845DecodeImageCallbacks::AllocPixbufResult //
42846DecodeImageCallbacks::AllocPixbuf(const wuffs_base__image_config& image_config,
42847 bool allow_uninitialized_memory) {
42848 uint32_t w = image_config.pixcfg.width();
42849 uint32_t h = image_config.pixcfg.height();
42850 if ((w == 0) || (h == 0)) {
42851 return AllocPixbufResult("");
42852 }
42853 uint64_t len = image_config.pixcfg.pixbuf_len();
42854 if ((len == 0) || (SIZE_MAX < len)) {
42855 return AllocPixbufResult(DecodeImage_UnsupportedPixelConfiguration);
42856 }
42857 void* ptr =
42858 allow_uninitialized_memory ? malloc((size_t)len) : calloc((size_t)len, 1);
42859 if (!ptr) {
42860 return AllocPixbufResult(DecodeImage_OutOfMemory);
42861 }
42862 wuffs_base__pixel_buffer pixbuf;
42863 wuffs_base__status status = pixbuf.set_from_slice(
42864 &image_config.pixcfg,
42865 wuffs_base__make_slice_u8((uint8_t*)ptr, (size_t)len));
42866 if (!status.is_ok()) {
42867 free(ptr);
42868 return AllocPixbufResult(status.message());
42869 }
42870 return AllocPixbufResult(MemOwner(ptr, &free), pixbuf);
42871}
42872
42873DecodeImageCallbacks::AllocWorkbufResult //
42874DecodeImageCallbacks::AllocWorkbuf(wuffs_base__range_ii_u64 len_range,
42875 bool allow_uninitialized_memory) {
42876 uint64_t len = len_range.max_incl;
42877 if (len == 0) {
42878 return AllocWorkbufResult("");
42879 } else if (SIZE_MAX < len) {
42880 return AllocWorkbufResult(DecodeImage_OutOfMemory);
42881 }
42882 void* ptr =
42883 allow_uninitialized_memory ? malloc((size_t)len) : calloc((size_t)len, 1);
42884 if (!ptr) {
42885 return AllocWorkbufResult(DecodeImage_OutOfMemory);
42886 }
42887 return AllocWorkbufResult(
42888 MemOwner(ptr, &free),
42889 wuffs_base__make_slice_u8((uint8_t*)ptr, (size_t)len));
42890}
42891
42892void //
42893DecodeImageCallbacks::Done(
42894 DecodeImageResult& result,
42895 sync_io::Input& input,
42896 IOBuffer& buffer,
42897 wuffs_base__image_decoder::unique_ptr image_decoder) {}
42898
42899const char DecodeImage_BufferIsTooShort[] = //
42900 "wuffs_aux::DecodeImage: buffer is too short";
42901const char DecodeImage_MaxInclDimensionExceeded[] = //
42902 "wuffs_aux::DecodeImage: max_incl_dimension exceeded";
Nigel Taobf9dab32021-11-18 19:19:55 +110042903const char DecodeImage_MaxInclMetadataLengthExceeded[] = //
42904 "wuffs_aux::DecodeImage: max_incl_metadata_length exceeded";
Nigel Taoe360a532021-04-05 22:47:03 +100042905const char DecodeImage_OutOfMemory[] = //
42906 "wuffs_aux::DecodeImage: out of memory";
42907const char DecodeImage_UnexpectedEndOfFile[] = //
42908 "wuffs_aux::DecodeImage: unexpected end of file";
42909const char DecodeImage_UnsupportedImageFormat[] = //
42910 "wuffs_aux::DecodeImage: unsupported image format";
Nigel Taobf9dab32021-11-18 19:19:55 +110042911const char DecodeImage_UnsupportedMetadata[] = //
42912 "wuffs_aux::DecodeImage: unsupported metadata";
Nigel Taoe360a532021-04-05 22:47:03 +100042913const char DecodeImage_UnsupportedPixelBlend[] = //
42914 "wuffs_aux::DecodeImage: unsupported pixel blend";
42915const char DecodeImage_UnsupportedPixelConfiguration[] = //
42916 "wuffs_aux::DecodeImage: unsupported pixel configuration";
42917const char DecodeImage_UnsupportedPixelFormat[] = //
42918 "wuffs_aux::DecodeImage: unsupported pixel format";
42919
Nigel Taobf9dab32021-11-18 19:19:55 +110042920DecodeImageArgQuirks::DecodeImageArgQuirks(wuffs_base__slice_u32 repr0)
42921 : repr(repr0) {}
42922
42923DecodeImageArgQuirks::DecodeImageArgQuirks(uint32_t* ptr0, size_t len0)
42924 : repr(wuffs_base__make_slice_u32(ptr0, len0)) {}
42925
42926DecodeImageArgQuirks //
42927DecodeImageArgQuirks::DefaultValue() {
42928 return DecodeImageArgQuirks(wuffs_base__empty_slice_u32());
42929}
42930
42931DecodeImageArgFlags::DecodeImageArgFlags(uint64_t repr0) : repr(repr0) {}
42932
42933DecodeImageArgFlags //
42934DecodeImageArgFlags::DefaultValue() {
42935 return DecodeImageArgFlags(0);
42936}
42937
42938DecodeImageArgPixelBlend::DecodeImageArgPixelBlend(
42939 wuffs_base__pixel_blend repr0)
42940 : repr(repr0) {}
42941
42942DecodeImageArgPixelBlend //
42943DecodeImageArgPixelBlend::DefaultValue() {
42944 return DecodeImageArgPixelBlend(WUFFS_BASE__PIXEL_BLEND__SRC);
42945}
42946
42947DecodeImageArgBackgroundColor::DecodeImageArgBackgroundColor(
42948 wuffs_base__color_u32_argb_premul repr0)
42949 : repr(repr0) {}
42950
42951DecodeImageArgBackgroundColor //
42952DecodeImageArgBackgroundColor::DefaultValue() {
42953 return DecodeImageArgBackgroundColor(1);
42954}
42955
42956DecodeImageArgMaxInclDimension::DecodeImageArgMaxInclDimension(uint32_t repr0)
42957 : repr(repr0) {}
42958
42959DecodeImageArgMaxInclDimension //
42960DecodeImageArgMaxInclDimension::DefaultValue() {
42961 return DecodeImageArgMaxInclDimension(1048575);
42962}
42963
42964DecodeImageArgMaxInclMetadataLength::DecodeImageArgMaxInclMetadataLength(
42965 uint64_t repr0)
42966 : repr(repr0) {}
42967
42968DecodeImageArgMaxInclMetadataLength //
42969DecodeImageArgMaxInclMetadataLength::DefaultValue() {
42970 return DecodeImageArgMaxInclMetadataLength(16777215);
42971}
42972
Nigel Taoe360a532021-04-05 22:47:03 +100042973// --------
42974
42975namespace {
42976
Nigel Taobf9dab32021-11-18 19:19:55 +110042977const private_impl::ErrorMessages DecodeImageErrorMessages = {
42978 DecodeImage_MaxInclMetadataLengthExceeded, //
42979 DecodeImage_OutOfMemory, //
42980 DecodeImage_UnexpectedEndOfFile, //
42981 DecodeImage_UnsupportedMetadata, //
42982 DecodeImage_UnsupportedImageFormat, //
42983};
42984
Nigel Taoe360a532021-04-05 22:47:03 +100042985std::string //
Nigel Taobf9dab32021-11-18 19:19:55 +110042986DecodeImageAdvanceIOBufferTo(sync_io::Input& input,
42987 wuffs_base__io_buffer& io_buf,
42988 uint64_t absolute_position) {
42989 return private_impl::AdvanceIOBufferTo(DecodeImageErrorMessages, input,
42990 io_buf, absolute_position);
42991}
42992
42993wuffs_base__status //
42994DIHM0(void* self,
42995 wuffs_base__io_buffer* a_dst,
42996 wuffs_base__more_information* a_minfo,
42997 wuffs_base__io_buffer* a_src) {
42998 return wuffs_base__image_decoder__tell_me_more(
42999 static_cast<wuffs_base__image_decoder*>(self), a_dst, a_minfo, a_src);
43000}
43001
43002std::string //
43003DIHM1(void* self,
43004 const wuffs_base__more_information* minfo,
43005 wuffs_base__slice_u8 raw) {
43006 return static_cast<DecodeImageCallbacks*>(self)->HandleMetadata(*minfo, raw);
43007}
43008
43009std::string //
43010DecodeImageHandleMetadata(wuffs_base__image_decoder::unique_ptr& image_decoder,
43011 DecodeImageCallbacks& callbacks,
43012 sync_io::Input& input,
43013 wuffs_base__io_buffer& io_buf,
43014 sync_io::DynIOBuffer& raw_metadata_buf) {
43015 return private_impl::HandleMetadata(DecodeImageErrorMessages, input, io_buf,
43016 raw_metadata_buf, DIHM0,
43017 static_cast<void*>(image_decoder.get()),
43018 DIHM1, static_cast<void*>(&callbacks));
Nigel Taoe360a532021-04-05 22:47:03 +100043019}
43020
43021DecodeImageResult //
43022DecodeImage0(wuffs_base__image_decoder::unique_ptr& image_decoder,
43023 DecodeImageCallbacks& callbacks,
43024 sync_io::Input& input,
43025 wuffs_base__io_buffer& io_buf,
Nigel Taobf9dab32021-11-18 19:19:55 +110043026 wuffs_base__slice_u32 quirks,
43027 uint64_t flags,
Nigel Taoe360a532021-04-05 22:47:03 +100043028 wuffs_base__pixel_blend pixel_blend,
43029 wuffs_base__color_u32_argb_premul background_color,
Nigel Taobf9dab32021-11-18 19:19:55 +110043030 uint32_t max_incl_dimension,
43031 uint64_t max_incl_metadata_length) {
Nigel Taoe360a532021-04-05 22:47:03 +100043032 // Check args.
43033 switch (pixel_blend) {
43034 case WUFFS_BASE__PIXEL_BLEND__SRC:
43035 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
43036 break;
43037 default:
43038 return DecodeImageResult(DecodeImage_UnsupportedPixelBlend);
43039 }
43040
43041 wuffs_base__image_config image_config = wuffs_base__null_image_config();
Nigel Taobf9dab32021-11-18 19:19:55 +110043042 sync_io::DynIOBuffer raw_metadata_buf(max_incl_metadata_length);
Nigel Taoe360a532021-04-05 22:47:03 +100043043 uint64_t start_pos = io_buf.reader_position();
43044 bool redirected = false;
43045 int32_t fourcc = 0;
43046redirect:
43047 do {
43048 // Determine the image format.
43049 if (!redirected) {
43050 while (true) {
43051 fourcc = wuffs_base__magic_number_guess_fourcc(io_buf.reader_slice());
43052 if (fourcc > 0) {
43053 break;
43054 } else if ((fourcc == 0) && (io_buf.reader_length() >= 64)) {
43055 break;
43056 } else if (io_buf.meta.closed || (io_buf.writer_length() == 0)) {
43057 fourcc = 0;
43058 break;
43059 }
43060 std::string error_message = input.CopyIn(&io_buf);
43061 if (!error_message.empty()) {
43062 return DecodeImageResult(std::move(error_message));
43063 }
43064 }
43065 } else {
43066 wuffs_base__io_buffer empty = wuffs_base__empty_io_buffer();
43067 wuffs_base__more_information minfo = wuffs_base__empty_more_information();
43068 wuffs_base__status tmm_status =
43069 image_decoder->tell_me_more(&empty, &minfo, &io_buf);
43070 if (tmm_status.repr != nullptr) {
43071 return DecodeImageResult(tmm_status.message());
43072 }
43073 if (minfo.flavor != WUFFS_BASE__MORE_INFORMATION__FLAVOR__IO_REDIRECT) {
43074 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
43075 }
43076 uint64_t pos = minfo.io_redirect__range().min_incl;
Nigel Taobf9dab32021-11-18 19:19:55 +110043077 if (pos <= start_pos) {
43078 // Redirects must go forward.
43079 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
43080 }
43081 std::string error_message =
43082 DecodeImageAdvanceIOBufferTo(input, io_buf, pos);
Nigel Taoe360a532021-04-05 22:47:03 +100043083 if (!error_message.empty()) {
43084 return DecodeImageResult(std::move(error_message));
43085 }
43086 fourcc = (int32_t)(minfo.io_redirect__fourcc());
43087 if (fourcc == 0) {
43088 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
43089 }
43090 image_decoder.reset();
43091 }
43092
43093 // Select the image decoder.
43094 image_decoder = callbacks.SelectDecoder(
43095 (uint32_t)fourcc,
43096 fourcc ? wuffs_base__empty_slice_u8() : io_buf.reader_slice());
43097 if (!image_decoder) {
43098 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
43099 }
43100
Nigel Taobf9dab32021-11-18 19:19:55 +110043101 // Apply quirks.
43102 for (size_t i = 0; i < quirks.len; i++) {
43103 image_decoder->set_quirk_enabled(quirks.ptr[i], true);
43104 }
43105
43106 // Apply flags.
43107 if (flags != 0) {
43108 if (flags & DecodeImageArgFlags::REPORT_METADATA_CHRM) {
43109 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__CHRM, true);
43110 }
43111 if (flags & DecodeImageArgFlags::REPORT_METADATA_GAMA) {
43112 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__GAMA, true);
43113 }
43114 if (flags & DecodeImageArgFlags::REPORT_METADATA_ICCP) {
43115 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__ICCP, true);
43116 }
43117 if (flags & DecodeImageArgFlags::REPORT_METADATA_KVP) {
43118 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__KVP, true);
43119 }
43120 if (flags & DecodeImageArgFlags::REPORT_METADATA_SRGB) {
43121 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__SRGB, true);
43122 }
43123 if (flags & DecodeImageArgFlags::REPORT_METADATA_XMP) {
43124 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__XMP, true);
43125 }
43126 }
43127
Nigel Taoe360a532021-04-05 22:47:03 +100043128 // Decode the image config.
43129 while (true) {
43130 wuffs_base__status id_dic_status =
43131 image_decoder->decode_image_config(&image_config, &io_buf);
43132 if (id_dic_status.repr == nullptr) {
43133 break;
43134 } else if (id_dic_status.repr == wuffs_base__note__i_o_redirect) {
43135 if (redirected) {
43136 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
43137 }
43138 redirected = true;
43139 goto redirect;
Nigel Taobf9dab32021-11-18 19:19:55 +110043140 } else if (id_dic_status.repr == wuffs_base__note__metadata_reported) {
43141 std::string error_message = DecodeImageHandleMetadata(
43142 image_decoder, callbacks, input, io_buf, raw_metadata_buf);
43143 if (!error_message.empty()) {
43144 return DecodeImageResult(std::move(error_message));
43145 }
Nigel Taoe360a532021-04-05 22:47:03 +100043146 } else if (id_dic_status.repr != wuffs_base__suspension__short_read) {
43147 return DecodeImageResult(id_dic_status.message());
43148 } else if (io_buf.meta.closed) {
43149 return DecodeImageResult(DecodeImage_UnexpectedEndOfFile);
43150 } else {
43151 std::string error_message = input.CopyIn(&io_buf);
43152 if (!error_message.empty()) {
43153 return DecodeImageResult(std::move(error_message));
43154 }
43155 }
43156 }
43157 } while (false);
Nigel Taobf9dab32021-11-18 19:19:55 +110043158 raw_metadata_buf.drop();
Nigel Taoe360a532021-04-05 22:47:03 +100043159
43160 // Select the pixel format.
43161 uint32_t w = image_config.pixcfg.width();
43162 uint32_t h = image_config.pixcfg.height();
43163 if ((w > max_incl_dimension) || (h > max_incl_dimension)) {
43164 return DecodeImageResult(DecodeImage_MaxInclDimensionExceeded);
43165 }
43166 wuffs_base__pixel_format pixel_format = callbacks.SelectPixfmt(image_config);
43167 if (pixel_format.repr != image_config.pixcfg.pixel_format().repr) {
43168 switch (pixel_format.repr) {
43169 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
43170 case WUFFS_BASE__PIXEL_FORMAT__BGR:
43171 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
43172 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
43173 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
43174 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
43175 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
43176 break;
43177 default:
43178 return DecodeImageResult(DecodeImage_UnsupportedPixelFormat);
43179 }
43180 image_config.pixcfg.set(pixel_format.repr,
43181 WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, w, h);
43182 }
43183
43184 // Allocate the pixel buffer.
43185 bool valid_background_color =
43186 wuffs_base__color_u32_argb_premul__is_valid(background_color);
43187 DecodeImageCallbacks::AllocPixbufResult alloc_pixbuf_result =
43188 callbacks.AllocPixbuf(image_config, valid_background_color);
43189 if (!alloc_pixbuf_result.error_message.empty()) {
43190 return DecodeImageResult(std::move(alloc_pixbuf_result.error_message));
43191 }
43192 wuffs_base__pixel_buffer pixel_buffer = alloc_pixbuf_result.pixbuf;
43193 if (valid_background_color) {
43194 wuffs_base__status pb_scufr_status = pixel_buffer.set_color_u32_fill_rect(
43195 pixel_buffer.pixcfg.bounds(), background_color);
43196 if (pb_scufr_status.repr != nullptr) {
43197 return DecodeImageResult(pb_scufr_status.message());
43198 }
43199 }
43200
43201 // Allocate the work buffer. Wuffs' decoders conventionally assume that this
43202 // can be uninitialized memory.
43203 wuffs_base__range_ii_u64 workbuf_len = image_decoder->workbuf_len();
43204 DecodeImageCallbacks::AllocWorkbufResult alloc_workbuf_result =
43205 callbacks.AllocWorkbuf(workbuf_len, true);
43206 if (!alloc_workbuf_result.error_message.empty()) {
43207 return DecodeImageResult(std::move(alloc_workbuf_result.error_message));
43208 } else if (alloc_workbuf_result.workbuf.len < workbuf_len.min_incl) {
43209 return DecodeImageResult(DecodeImage_BufferIsTooShort);
43210 }
43211
43212 // Decode the frame config.
43213 wuffs_base__frame_config frame_config = wuffs_base__null_frame_config();
43214 while (true) {
43215 wuffs_base__status id_dfc_status =
43216 image_decoder->decode_frame_config(&frame_config, &io_buf);
43217 if (id_dfc_status.repr == nullptr) {
43218 break;
43219 } else if (id_dfc_status.repr != wuffs_base__suspension__short_read) {
43220 return DecodeImageResult(id_dfc_status.message());
43221 } else if (io_buf.meta.closed) {
43222 return DecodeImageResult(DecodeImage_UnexpectedEndOfFile);
43223 } else {
43224 std::string error_message = input.CopyIn(&io_buf);
43225 if (!error_message.empty()) {
43226 return DecodeImageResult(std::move(error_message));
43227 }
43228 }
43229 }
43230
43231 // Decode the frame (the pixels).
43232 //
43233 // From here on, always returns the pixel_buffer. If we get this far, we can
43234 // still display a partial image, even if we encounter an error.
43235 std::string message("");
43236 if ((pixel_blend == WUFFS_BASE__PIXEL_BLEND__SRC_OVER) &&
43237 frame_config.overwrite_instead_of_blend()) {
43238 pixel_blend = WUFFS_BASE__PIXEL_BLEND__SRC;
43239 }
43240 while (true) {
43241 wuffs_base__status id_df_status =
43242 image_decoder->decode_frame(&pixel_buffer, &io_buf, pixel_blend,
43243 alloc_workbuf_result.workbuf, nullptr);
43244 if (id_df_status.repr == nullptr) {
43245 break;
43246 } else if (id_df_status.repr != wuffs_base__suspension__short_read) {
43247 message = id_df_status.message();
43248 break;
43249 } else if (io_buf.meta.closed) {
43250 message = DecodeImage_UnexpectedEndOfFile;
43251 break;
43252 } else {
43253 std::string error_message = input.CopyIn(&io_buf);
43254 if (!error_message.empty()) {
43255 message = std::move(error_message);
43256 break;
43257 }
43258 }
43259 }
43260 return DecodeImageResult(std::move(alloc_pixbuf_result.mem_owner),
43261 pixel_buffer, std::move(message));
43262}
43263
43264} // namespace
43265
43266DecodeImageResult //
43267DecodeImage(DecodeImageCallbacks& callbacks,
43268 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110043269 DecodeImageArgQuirks quirks,
43270 DecodeImageArgFlags flags,
43271 DecodeImageArgPixelBlend pixel_blend,
43272 DecodeImageArgBackgroundColor background_color,
43273 DecodeImageArgMaxInclDimension max_incl_dimension,
43274 DecodeImageArgMaxInclMetadataLength max_incl_metadata_length) {
Nigel Taoe360a532021-04-05 22:47:03 +100043275 wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
43276 wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
43277 std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);
43278 if (!io_buf) {
43279 fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[32768]);
43280 fallback_io_buf =
43281 wuffs_base__ptr_u8__writer(fallback_io_array.get(), 32768);
43282 io_buf = &fallback_io_buf;
43283 }
43284
43285 wuffs_base__image_decoder::unique_ptr image_decoder(nullptr, &free);
43286 DecodeImageResult result =
Nigel Taobf9dab32021-11-18 19:19:55 +110043287 DecodeImage0(image_decoder, callbacks, input, *io_buf, quirks.repr,
43288 flags.repr, pixel_blend.repr, background_color.repr,
43289 max_incl_dimension.repr, max_incl_metadata_length.repr);
Nigel Taoe360a532021-04-05 22:47:03 +100043290 callbacks.Done(result, input, *io_buf, std::move(image_decoder));
43291 return result;
43292}
43293
43294} // namespace wuffs_aux
43295
43296#endif // !defined(WUFFS_CONFIG__MODULES) ||
43297 // defined(WUFFS_CONFIG__MODULE__AUX__IMAGE)
43298
43299// ---------------- Auxiliary - JSON
43300
43301#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__JSON)
43302
43303#include <utility>
43304
43305namespace wuffs_aux {
43306
43307DecodeJsonResult::DecodeJsonResult(std::string&& error_message0,
43308 uint64_t cursor_position0)
43309 : error_message(std::move(error_message0)),
43310 cursor_position(cursor_position0) {}
43311
43312DecodeJsonCallbacks::~DecodeJsonCallbacks() {}
43313
43314void //
43315DecodeJsonCallbacks::Done(DecodeJsonResult& result,
43316 sync_io::Input& input,
43317 IOBuffer& buffer) {}
43318
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043319const char DecodeJson_BadJsonPointer[] = //
Nigel Taoe360a532021-04-05 22:47:03 +100043320 "wuffs_aux::DecodeJson: bad JSON Pointer";
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043321const char DecodeJson_NoMatch[] = //
43322 "wuffs_aux::DecodeJson: no match";
Nigel Taoe360a532021-04-05 22:47:03 +100043323
Nigel Taobf9dab32021-11-18 19:19:55 +110043324DecodeJsonArgQuirks::DecodeJsonArgQuirks(wuffs_base__slice_u32 repr0)
43325 : repr(repr0) {}
43326
43327DecodeJsonArgQuirks::DecodeJsonArgQuirks(uint32_t* ptr0, size_t len0)
43328 : repr(wuffs_base__make_slice_u32(ptr0, len0)) {}
43329
43330DecodeJsonArgQuirks //
43331DecodeJsonArgQuirks::DefaultValue() {
43332 return DecodeJsonArgQuirks(wuffs_base__empty_slice_u32());
43333}
43334
43335DecodeJsonArgJsonPointer::DecodeJsonArgJsonPointer(std::string repr0)
43336 : repr(repr0) {}
43337
43338DecodeJsonArgJsonPointer //
43339DecodeJsonArgJsonPointer::DefaultValue() {
43340 return DecodeJsonArgJsonPointer(std::string());
43341}
43342
Nigel Taoe360a532021-04-05 22:47:03 +100043343// --------
43344
Nigel Taod5b8cfa2021-07-18 11:37:27 +100043345#define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN \
43346 while (tok_buf.meta.ri >= tok_buf.meta.wi) { \
43347 if (tok_status.repr == nullptr) { \
43348 goto done; \
43349 } else if (tok_status.repr == wuffs_base__suspension__short_write) { \
43350 tok_buf.compact(); \
43351 } else if (tok_status.repr == wuffs_base__suspension__short_read) { \
43352 if (!io_error_message.empty()) { \
43353 ret_error_message = std::move(io_error_message); \
43354 goto done; \
43355 } else if (cursor_index != io_buf->meta.ri) { \
43356 ret_error_message = \
43357 "wuffs_aux::DecodeJson: internal error: bad cursor_index"; \
43358 goto done; \
43359 } else if (io_buf->meta.closed) { \
43360 ret_error_message = \
43361 "wuffs_aux::DecodeJson: internal error: io_buf is closed"; \
43362 goto done; \
43363 } \
43364 io_buf->compact(); \
43365 if (io_buf->meta.wi >= io_buf->data.len) { \
43366 ret_error_message = \
43367 "wuffs_aux::DecodeJson: internal error: io_buf is full"; \
43368 goto done; \
43369 } \
43370 cursor_index = io_buf->meta.ri; \
43371 io_error_message = input.CopyIn(io_buf); \
43372 } else { \
43373 ret_error_message = tok_status.message(); \
43374 goto done; \
43375 } \
43376 tok_status = \
43377 dec->decode_tokens(&tok_buf, io_buf, wuffs_base__empty_slice_u8()); \
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043378 if ((tok_buf.meta.ri > tok_buf.meta.wi) || \
43379 (tok_buf.meta.wi > tok_buf.data.len) || \
43380 (io_buf->meta.ri > io_buf->meta.wi) || \
43381 (io_buf->meta.wi > io_buf->data.len)) { \
43382 ret_error_message = \
43383 "wuffs_aux::DecodeJson: internal error: bad buffer indexes"; \
43384 goto done; \
43385 } \
Nigel Taod5b8cfa2021-07-18 11:37:27 +100043386 } \
43387 wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++]; \
43388 uint64_t token_len = token.length(); \
43389 if ((io_buf->meta.ri < cursor_index) || \
43390 ((io_buf->meta.ri - cursor_index) < token_len)) { \
43391 ret_error_message = \
43392 "wuffs_aux::DecodeJson: internal error: bad token indexes"; \
43393 goto done; \
43394 } \
43395 uint8_t* token_ptr = io_buf->data.ptr + cursor_index; \
43396 (void)(token_ptr); \
Nigel Taoe360a532021-04-05 22:47:03 +100043397 cursor_index += static_cast<size_t>(token_len)
43398
43399// --------
43400
43401namespace {
43402
43403// DecodeJson_SplitJsonPointer returns ("bar", 8) for ("/foo/bar/b~1z/qux", 5,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043404// etc). It returns a 0 size_t when s has invalid JSON Pointer syntax or i is
43405// out of bounds.
Nigel Taoe360a532021-04-05 22:47:03 +100043406//
43407// The string returned is unescaped. If calling it again, this time with i=8,
43408// the "b~1z" substring would be returned as "b/z".
43409std::pair<std::string, size_t> //
43410DecodeJson_SplitJsonPointer(std::string& s,
43411 size_t i,
43412 bool allow_tilde_n_tilde_r_tilde_t) {
43413 std::string fragment;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043414 if (i > s.size()) {
43415 return std::make_pair(std::string(), 0);
43416 }
Nigel Taoe360a532021-04-05 22:47:03 +100043417 while (i < s.size()) {
43418 char c = s[i];
43419 if (c == '/') {
43420 break;
43421 } else if (c != '~') {
43422 fragment.push_back(c);
43423 i++;
43424 continue;
43425 }
43426 i++;
43427 if (i >= s.size()) {
43428 return std::make_pair(std::string(), 0);
43429 }
43430 c = s[i];
43431 if (c == '0') {
43432 fragment.push_back('~');
43433 i++;
43434 continue;
43435 } else if (c == '1') {
43436 fragment.push_back('/');
43437 i++;
43438 continue;
43439 } else if (allow_tilde_n_tilde_r_tilde_t) {
43440 if (c == 'n') {
43441 fragment.push_back('\n');
43442 i++;
43443 continue;
43444 } else if (c == 'r') {
43445 fragment.push_back('\r');
43446 i++;
43447 continue;
43448 } else if (c == 't') {
43449 fragment.push_back('\t');
43450 i++;
43451 continue;
43452 }
43453 }
43454 return std::make_pair(std::string(), 0);
43455 }
43456 return std::make_pair(std::move(fragment), i);
43457}
43458
43459// --------
43460
43461std::string //
43462DecodeJson_WalkJsonPointerFragment(wuffs_base__token_buffer& tok_buf,
43463 wuffs_base__status& tok_status,
43464 wuffs_json__decoder::unique_ptr& dec,
43465 wuffs_base__io_buffer* io_buf,
43466 std::string& io_error_message,
43467 size_t& cursor_index,
43468 sync_io::Input& input,
43469 std::string& json_pointer_fragment) {
43470 std::string ret_error_message;
43471 while (true) {
43472 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
43473
43474 int64_t vbc = token.value_base_category();
43475 uint64_t vbd = token.value_base_detail();
43476 if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
43477 continue;
43478 } else if ((vbc != WUFFS_BASE__TOKEN__VBC__STRUCTURE) ||
43479 !(vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH)) {
43480 return DecodeJson_NoMatch;
43481 } else if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST) {
43482 goto do_list;
43483 }
43484 goto do_dict;
43485 }
43486
43487do_dict:
43488 // Alternate between these two things:
43489 // 1. Decode the next dict key (a string). If it matches the fragment, we're
43490 // done (success). If we've reached the dict's end (VBD__STRUCTURE__POP)
43491 // so that there was no next dict key, we're done (failure).
43492 // 2. Otherwise, skip the next dict value.
43493 while (true) {
43494 for (std::string str; true;) {
43495 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
43496
43497 int64_t vbc = token.value_base_category();
43498 uint64_t vbd = token.value_base_detail();
43499 switch (vbc) {
43500 case WUFFS_BASE__TOKEN__VBC__FILLER:
43501 continue;
43502
43503 case WUFFS_BASE__TOKEN__VBC__STRUCTURE:
43504 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
43505 goto fail;
43506 }
43507 return DecodeJson_NoMatch;
43508
43509 case WUFFS_BASE__TOKEN__VBC__STRING: {
43510 if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
43511 // No-op.
43512 } else if (vbd &
43513 WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
43514 const char* ptr = // Convert from (uint8_t*).
43515 static_cast<const char*>(static_cast<void*>(token_ptr));
43516 str.append(ptr, static_cast<size_t>(token_len));
43517 } else {
43518 goto fail;
43519 }
43520 break;
43521 }
43522
43523 case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
43524 uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
43525 size_t n = wuffs_base__utf_8__encode(
43526 wuffs_base__make_slice_u8(
43527 &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
43528 static_cast<uint32_t>(vbd));
43529 const char* ptr = // Convert from (uint8_t*).
43530 static_cast<const char*>(static_cast<void*>(&u[0]));
43531 str.append(ptr, n);
43532 break;
43533 }
43534
43535 default:
43536 goto fail;
43537 }
43538
43539 if (token.continued()) {
43540 continue;
43541 }
43542 if (str == json_pointer_fragment) {
43543 return "";
43544 }
43545 goto skip_the_next_dict_value;
43546 }
43547
43548 skip_the_next_dict_value:
43549 for (uint32_t skip_depth = 0; true;) {
43550 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
43551
43552 int64_t vbc = token.value_base_category();
43553 uint64_t vbd = token.value_base_detail();
43554 if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
43555 continue;
43556 } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
43557 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
43558 skip_depth++;
43559 continue;
43560 }
43561 skip_depth--;
43562 }
43563
43564 if (skip_depth == 0) {
43565 break;
43566 }
43567 } // skip_the_next_dict_value
43568 } // do_dict
43569
43570do_list:
43571 do {
43572 wuffs_base__result_u64 result_u64 = wuffs_base__parse_number_u64(
43573 wuffs_base__make_slice_u8(
43574 static_cast<uint8_t*>(static_cast<void*>(
43575 const_cast<char*>(json_pointer_fragment.data()))),
43576 json_pointer_fragment.size()),
43577 WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
43578 if (!result_u64.status.is_ok()) {
43579 return DecodeJson_NoMatch;
43580 }
43581 uint64_t remaining = result_u64.value;
43582 if (remaining == 0) {
43583 goto check_that_a_value_follows;
43584 }
43585 for (uint32_t skip_depth = 0; true;) {
43586 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
43587
43588 int64_t vbc = token.value_base_category();
43589 uint64_t vbd = token.value_base_detail();
43590 if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
43591 continue;
43592 } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
43593 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
43594 skip_depth++;
43595 continue;
43596 }
43597 if (skip_depth == 0) {
43598 return DecodeJson_NoMatch;
43599 }
43600 skip_depth--;
43601 }
43602
43603 if (skip_depth > 0) {
43604 continue;
43605 }
43606 remaining--;
43607 if (remaining == 0) {
43608 goto check_that_a_value_follows;
43609 }
43610 }
43611 } while (false); // do_list
43612
43613check_that_a_value_follows:
43614 while (true) {
43615 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
43616
43617 int64_t vbc = token.value_base_category();
43618 uint64_t vbd = token.value_base_detail();
43619 if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
43620 continue;
43621 }
43622
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043623 // Undo the last part of WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN, so
43624 // that we're only peeking at the next token.
Nigel Taoe360a532021-04-05 22:47:03 +100043625 tok_buf.meta.ri--;
43626 cursor_index -= static_cast<size_t>(token_len);
43627
43628 if ((vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) &&
43629 (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP)) {
43630 return DecodeJson_NoMatch;
43631 }
43632 return "";
43633 } // check_that_a_value_follows
43634
43635fail:
43636 return "wuffs_aux::DecodeJson: internal error: unexpected token";
43637done:
43638 return ret_error_message;
43639}
43640
43641} // namespace
43642
43643// --------
43644
43645DecodeJsonResult //
43646DecodeJson(DecodeJsonCallbacks& callbacks,
43647 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110043648 DecodeJsonArgQuirks quirks,
43649 DecodeJsonArgJsonPointer json_pointer) {
Nigel Taoe360a532021-04-05 22:47:03 +100043650 // Prepare the wuffs_base__io_buffer and the resultant error_message.
43651 wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
43652 wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
43653 std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);
43654 if (!io_buf) {
43655 fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[4096]);
43656 fallback_io_buf = wuffs_base__ptr_u8__writer(fallback_io_array.get(), 4096);
43657 io_buf = &fallback_io_buf;
43658 }
43659 // cursor_index is discussed at
43660 // https://nigeltao.github.io/blog/2020/jsonptr.html#the-cursor-index
43661 size_t cursor_index = 0;
43662 std::string ret_error_message;
43663 std::string io_error_message;
43664
43665 do {
43666 // Prepare the low-level JSON decoder.
43667 wuffs_json__decoder::unique_ptr dec = wuffs_json__decoder::alloc();
43668 if (!dec) {
43669 ret_error_message = "wuffs_aux::DecodeJson: out of memory";
43670 goto done;
Nigel Taod5b8cfa2021-07-18 11:37:27 +100043671 } else if (WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {
43672 ret_error_message =
43673 "wuffs_aux::DecodeJson: internal error: bad WORKBUF_LEN";
43674 goto done;
Nigel Taoe360a532021-04-05 22:47:03 +100043675 }
43676 bool allow_tilde_n_tilde_r_tilde_t = false;
Nigel Taobf9dab32021-11-18 19:19:55 +110043677 for (size_t i = 0; i < quirks.repr.len; i++) {
43678 dec->set_quirk_enabled(quirks.repr.ptr[i], true);
43679 if (quirks.repr.ptr[i] ==
Nigel Taoe360a532021-04-05 22:47:03 +100043680 WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_N_TILDE_R_TILDE_T) {
43681 allow_tilde_n_tilde_r_tilde_t = true;
43682 }
43683 }
43684
43685 // Prepare the wuffs_base__tok_buffer. 256 tokens is 2KiB.
43686 wuffs_base__token tok_array[256];
43687 wuffs_base__token_buffer tok_buf =
43688 wuffs_base__slice_token__writer(wuffs_base__make_slice_token(
43689 &tok_array[0], (sizeof(tok_array) / sizeof(tok_array[0]))));
Nigel Taod5b8cfa2021-07-18 11:37:27 +100043690 wuffs_base__status tok_status =
43691 dec->decode_tokens(&tok_buf, io_buf, wuffs_base__empty_slice_u8());
Nigel Taoe360a532021-04-05 22:47:03 +100043692
43693 // Prepare other state.
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043694 int32_t depth = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100043695 std::string str;
43696
43697 // Walk the (optional) JSON Pointer.
Nigel Taobf9dab32021-11-18 19:19:55 +110043698 for (size_t i = 0; i < json_pointer.repr.size();) {
43699 if (json_pointer.repr[i] != '/') {
Nigel Taoe360a532021-04-05 22:47:03 +100043700 ret_error_message = DecodeJson_BadJsonPointer;
43701 goto done;
43702 }
43703 std::pair<std::string, size_t> split = DecodeJson_SplitJsonPointer(
Nigel Taobf9dab32021-11-18 19:19:55 +110043704 json_pointer.repr, i + 1, allow_tilde_n_tilde_r_tilde_t);
Nigel Taod5b8cfa2021-07-18 11:37:27 +100043705 i = split.second;
Nigel Taoe360a532021-04-05 22:47:03 +100043706 if (i == 0) {
43707 ret_error_message = DecodeJson_BadJsonPointer;
43708 goto done;
43709 }
43710 ret_error_message = DecodeJson_WalkJsonPointerFragment(
43711 tok_buf, tok_status, dec, io_buf, io_error_message, cursor_index,
43712 input, split.first);
43713 if (!ret_error_message.empty()) {
43714 goto done;
43715 }
43716 }
43717
43718 // Loop, doing these two things:
43719 // 1. Get the next token.
43720 // 2. Process that token.
43721 while (true) {
43722 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
43723
43724 int64_t vbc = token.value_base_category();
43725 uint64_t vbd = token.value_base_detail();
43726 switch (vbc) {
43727 case WUFFS_BASE__TOKEN__VBC__FILLER:
43728 continue;
43729
43730 case WUFFS_BASE__TOKEN__VBC__STRUCTURE: {
43731 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
43732 ret_error_message = callbacks.Push(static_cast<uint32_t>(vbd));
43733 if (!ret_error_message.empty()) {
43734 goto done;
43735 }
43736 depth++;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043737 if (depth > WUFFS_JSON__DECODER_DEPTH_MAX_INCL) {
43738 ret_error_message =
43739 "wuffs_aux::DecodeJson: internal error: bad depth";
43740 goto done;
43741 }
Nigel Taoe360a532021-04-05 22:47:03 +100043742 continue;
43743 }
43744 ret_error_message = callbacks.Pop(static_cast<uint32_t>(vbd));
43745 depth--;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100043746 if (depth < 0) {
43747 ret_error_message =
43748 "wuffs_aux::DecodeJson: internal error: bad depth";
43749 goto done;
43750 }
Nigel Taoe360a532021-04-05 22:47:03 +100043751 goto parsed_a_value;
43752 }
43753
43754 case WUFFS_BASE__TOKEN__VBC__STRING: {
43755 if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
43756 // No-op.
43757 } else if (vbd &
43758 WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
43759 const char* ptr = // Convert from (uint8_t*).
43760 static_cast<const char*>(static_cast<void*>(token_ptr));
43761 str.append(ptr, static_cast<size_t>(token_len));
43762 } else {
43763 goto fail;
43764 }
43765 if (token.continued()) {
43766 continue;
43767 }
43768 ret_error_message = callbacks.AppendTextString(std::move(str));
43769 str.clear();
43770 goto parsed_a_value;
43771 }
43772
43773 case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
43774 uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
43775 size_t n = wuffs_base__utf_8__encode(
43776 wuffs_base__make_slice_u8(
43777 &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
43778 static_cast<uint32_t>(vbd));
43779 const char* ptr = // Convert from (uint8_t*).
43780 static_cast<const char*>(static_cast<void*>(&u[0]));
43781 str.append(ptr, n);
43782 if (token.continued()) {
43783 continue;
43784 }
43785 goto fail;
43786 }
43787
43788 case WUFFS_BASE__TOKEN__VBC__LITERAL: {
43789 ret_error_message =
43790 (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__NULL)
43791 ? callbacks.AppendNull()
43792 : callbacks.AppendBool(vbd &
43793 WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE);
43794 goto parsed_a_value;
43795 }
43796
43797 case WUFFS_BASE__TOKEN__VBC__NUMBER: {
43798 if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT) {
43799 if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED) {
43800 wuffs_base__result_i64 r = wuffs_base__parse_number_i64(
43801 wuffs_base__make_slice_u8(token_ptr,
43802 static_cast<size_t>(token_len)),
43803 WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
43804 if (r.status.is_ok()) {
43805 ret_error_message = callbacks.AppendI64(r.value);
43806 goto parsed_a_value;
43807 }
43808 }
43809 if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT) {
43810 wuffs_base__result_f64 r = wuffs_base__parse_number_f64(
43811 wuffs_base__make_slice_u8(token_ptr,
43812 static_cast<size_t>(token_len)),
43813 WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
43814 if (r.status.is_ok()) {
43815 ret_error_message = callbacks.AppendF64(r.value);
43816 goto parsed_a_value;
43817 }
43818 }
43819 } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF) {
43820 ret_error_message = callbacks.AppendF64(
43821 wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
43822 0xFFF0000000000000ul));
43823 goto parsed_a_value;
43824 } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF) {
43825 ret_error_message = callbacks.AppendF64(
43826 wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
43827 0x7FF0000000000000ul));
43828 goto parsed_a_value;
43829 } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN) {
43830 ret_error_message = callbacks.AppendF64(
43831 wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
43832 0xFFFFFFFFFFFFFFFFul));
43833 goto parsed_a_value;
43834 } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN) {
43835 ret_error_message = callbacks.AppendF64(
43836 wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
43837 0x7FFFFFFFFFFFFFFFul));
43838 goto parsed_a_value;
43839 }
43840 goto fail;
43841 }
43842 }
43843
43844 fail:
43845 ret_error_message =
43846 "wuffs_aux::DecodeJson: internal error: unexpected token";
43847 goto done;
43848
43849 parsed_a_value:
Nigel Taod5b8cfa2021-07-18 11:37:27 +100043850 // If an error was encountered, we are done. Otherwise, (depth == 0)
43851 // after parsing a value is equivalent to having decoded the entire JSON
43852 // value (for an empty json_pointer query) or having decoded the
43853 // pointed-to JSON value (for a non-empty json_pointer query). In the
43854 // latter case, we are also done.
43855 //
43856 // However, if quirks like WUFFS_JSON__QUIRK_ALLOW_TRAILING_FILLER or
43857 // WUFFS_JSON__QUIRK_EXPECT_TRAILING_NEW_LINE_OR_EOF are passed, decoding
43858 // the entire JSON value should also consume any trailing filler, in case
43859 // the DecodeJson caller wants to subsequently check that the input is
43860 // completely exhausted (and otherwise raise "valid JSON followed by
43861 // further (unexpected) data"). We aren't done yet. Instead, keep the
43862 // loop running until WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN's
43863 // decode_tokens returns an ok status.
43864 if (!ret_error_message.empty() ||
Nigel Taobf9dab32021-11-18 19:19:55 +110043865 ((depth == 0) && !json_pointer.repr.empty())) {
Nigel Taoe360a532021-04-05 22:47:03 +100043866 goto done;
43867 }
43868 }
43869 } while (false);
43870
43871done:
43872 DecodeJsonResult result(
43873 std::move(ret_error_message),
43874 wuffs_base__u64__sat_add(io_buf->meta.pos, cursor_index));
43875 callbacks.Done(result, input, *io_buf);
43876 return result;
43877}
43878
43879#undef WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN
43880
43881} // namespace wuffs_aux
43882
43883#endif // !defined(WUFFS_CONFIG__MODULES) ||
43884 // defined(WUFFS_CONFIG__MODULE__AUX__JSON)
43885
43886#endif // defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
43887
43888#endif // WUFFS_IMPLEMENTATION
43889
43890#if defined(__GNUC__)
43891#pragma GCC diagnostic pop
Nigel Taobb778712021-06-25 15:38:45 +100043892#elif defined(__clang__)
43893#pragma clang diagnostic pop
Nigel Taoe360a532021-04-05 22:47:03 +100043894#endif
43895
43896#endif // WUFFS_INCLUDE_GUARD